12558网页游戏私服论坛

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

从零开始的Linux堆利用(一)

[复制链接]

303

主题

303

帖子

616

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
616
发表于 2021-5-8 00:43:06 | 显示全部楼层 |阅读模式
感觉栈相干简朴的漏洞根本原理学的差不多了,准备学一学堆相干的;
这个主要是学习Linux Heap Exploitation时的笔记,具体的课可以去Udemy上看,感觉讲的蛮不错的;
然后内容都是自己的博客,原文在https://hack1s.fun/,欢迎大家去看
introduction

Glibc

ldd是list dymic dependencies,可以体现出二进制程序运行时需要加载的动态链接库
libc是linux中最根本的动态链接库,绝大多数程序都需要用到libc,如果删除libc的链接,关机都会关不掉;
malloc

堆是程序在执行中可以使用malloc向内核请求一段连续的内存空间;
I/O、文件读写等等都是通过堆来实现的;
堆与malloc

首先需要对堆有一个根本的明白,堆通过malloc分配chunk,通过free来释放chunk
首先是一个demo例子用于明白堆
在pwndbg中执行
set context-sections code这样可以让之后每一次体现context只体现源代码部分

这个程序主要做的事情就是调用了几次malloc,之后return
vmmap可以体现出进程当前的内存空间,在这一句malloc还没有执行的时候,程序内存空间不存在堆的区域

当第一次malloc执行之后,检察vmmap会发现多出来了一个堆的空间

在pwndbg中的下令vis_heap_chunk简写为vis可以检察堆的chunk分布

我们虽然是执行了malloc(9),申请了9的空间,但是实际上给了我们3*8=24字节的空间(蓝色部分的第一个8字节是头部,不是用户可以用的)
也就是说malloc(9)分配给了24字节的user data以及8个字节的meta data,这个chunk一共占了32字节;
malloc分配的最小chunk就是这样0x20的大小,即24字节的user data和8个字节的meta data
即使执行的是malloc(0)、malloc(1)仍然会分配一个0x20大小的chunk

图中几个chunk分别是malloc(9)、malloc(1)、malloc(0)、malloc(24)分配的;
可以看到实际上内容都是一样的占了0x20字节;
但是也可以留意到,其中meta data部分并不是存储了0x20,而是0x21;
这是因为meta data这里两个字段,一是chunk size,表示整个chunk(包含user和meta两部分)的大小,另外由于chunk分配时是按照16字节对齐的,最低位就可以用来表示其他信息;这个字段就是previous_inuse,用来表示这一个chunk相邻的前一个chunk是否是在使用的状态,如果是就为1,否则为0;
下面如果继续执行malloc(25)会分配一个0x30的空间

虽然最后16个字节只用到了1个字节,但还是按照16字节对齐进行分配的。
最后就是Top chunk,可以看到在我们自己申请的Chunk之后有一个Top Chunk的meta data;
并且随着一次次的申请新的堆空间,这个Top Chunk的大小会发生变革。
这是因为内核在分配堆的内存空间时是创建一块大的Top Chunk,每一次用户执行的malloc就是压缩top chunk分配给用户,直到Top Chunk的空间不足以分配,就会再向下拓展Top Chunk

在Top Chunk中有一个值得留意的地方是,在Glibc的许多版本中,Top Chunk的Size字段都是没有完备性检查的,这就是The House of Force的根本原理
在2005年,第一次出现了一篇名为The Malloc Maleficarum的论文,其中写了5种堆使用的技巧;

  • Houses of Prime
  • Houses of Mind
  • Houses of Force
  • Houses of Lore
  • Houses of Spirit
今后之后的堆使用技巧也因此都叫"house of  XX"这样的形式
House of Force

原理

house of force的原理就是前面提到的,没有对Top Chunk的size字段进行完备性检查;
这导致在分配了一个比较小的chunk后,如果输入的内容大于chunk的大小,进而溢出到top chunk的size 字段,就可以伪造控制top chunk的大小;
之后再一次使用malloc分配chunk,可以到达一个任意地址写的结果,运用恰当也可以实现RCE的结果;
漏洞程序本身

程序本身是一个类似CTF中堆题的布局

为了方便学习漏洞本身,程序运行前输出了puts的地址以及heap开始的地址
选项1是malloc,之后可以输入要申请的大小以及输入的内容
例如上面申请了24,但是输入了24个a以及7个b最后和一个\n
这是我们后回到pwndbg,可以用vis看到现在的堆

可以看到由于溢出了7个字节的b和1个字节的\x0a,top chunk处的size已经被覆盖了。
在GDB中使用vmmap libc可以检察程序调用的libc信息
这个程序由于增加了Runpath,连接的是特定的libc

这里使用的是没有开启tcache的程序,但是实际上house of force是可以在tcache存在的libc使用的;
这里使用这样没有开启tcache的libc是为了在还没有学过tcache机制的情况下就可以相识如何使用这个漏洞使用方式
任意地址写

程序的第二个选项可以输出一个变量target
正常来说这个变量的值是一串X

在pwndbg中可以使用dq &target以四个字为单位检察这个变量附近的值

dq的全称是dump qwords,另外也有类似的dw、dd、db
堆起始地址是0x603000,但是可以看到这里实在target的位置是在堆的上方的0x602010
使用malloc只能继续往高地址申请空间,没有办法摸到target
以是我们需要溢出top chunk
这边由于虚拟机的情况有写题目,换了一台虚拟机
首先申请24的空间,然后输入b"Y"*24+b"\xff"*8
这样可以把top chunk覆盖为0xffffffff,在python脚本里面用gdb调试
这里给出的脚本中有几个函数是可以直接辅助在VIM中运行的,在vim输入
:!./% GDB这个功能的实现是通过这一块代码
gs = '''continue'''def start():  if args.GDB:    return gdb.debug(elf.path,gdbscript=gs)  else:    return process(elf.path)相称于直接启动GDB附加这个程序,使用vis看到

top chunk已经是全f了
第二步就是申请一个特别大的chunk,正好到target前面一点点的位置;
这个程序前面输出了heap的地址,在pwntools中读取之后,盘算差值
需要分配的是(0xffffffff-0x603000)+0x602010-0x20-0x20这么大的内容
malloc之后用vis检察

可以看到这时正好在0x602010上方
这之后再malloc申请内存覆盖的就是target的地方,再申请20的空间,在里面任意输入一些内容
发现vis后0x602010处的值就已经不再是XXXXXX了

在菜单里面输出target发现值也变了

这就实现了一个任意地址写的结果
任意代码执行

通过一个任意地址写转换成代码执行的使用有这样几个思路:

  • 修改栈,但是这个程序中栈采用了ASLR;
  • 修改Binary段,修改PLT中的项或修改fini_array,程序中的每一个函数在退出时会运行这个fini_array中的,但是这个程序开启了full-RELRO,在binary加载完成之后原本的二进制区段会变成只读,无法对其进行修改;
  • 修改堆,但是这个程序中除了我们自己的数据,没有影响控制流的数据,以是没用;
  • 修改libc,__exit_funcs、tls_dtors_list这两个指针会在特定情况下调用,比较类似于PLT,但是都被指针完备性保护,并且在这个程序中没有可以触发的地方,以是难以实现;
  • 修改__malloc_hook,在GLIBC中的数据段,修改__malloc_hook可以使程序在调用malloc时调用这里被修改的函数;
这里面修改__malloc_hook是可行的,我们首先将top chunk溢出为全f
之后申请一个空间,从堆中现在top chunk地点的位置到libc的__malloc_hook这么长;
由于libc的区段在堆的下面,不需要像获取任意地址写那样滚一圈内存空间了;
distance = libc.sym.__malloc_hook - 0x20 - (heap + 0x20)调试的时候使用:!./% GDB NOASLR暂时关掉ASLR
分配之后检察__malloc_hook的位置

由于分配时减了0x20,这里看一下__malloc_hook - 2

运行top_chunk看到top_chunk的位置就在这上方

以是我们接下来再用malloc申请一段空间,将__malloc_hook这里的函数指针修改为指向system函数的地址
libc.sym['system']这时用p __malloc_hook看一下可以发现这个函数指针已经变成了__ libc_system

下面就是想办法执行system("/bin/bash")
由于system的参数是一个指向字符串的指针,我们可以在前面几轮malloc填充数据时就直接填充/bin/bash在这里填写其时分配出来的地址

比如把第二轮的malloc中填充的字符串改成/bin/bash
这样最后调用时要填写的字符串地址就是最初的heap+0x30
这次再执行就不需要后面的GDB NOASLR了,直接运行就可以拿到shell

总结一下,这里的house_of_force只对2.28以下的GLIBC有用,再新的GLIBC就增加了top chunk的完备性保护了;


house_of_force.zip
567.13 KB, 下载次数: 14, 下载积分: 吾爱币 -1 CB

二进制程序和脚本模板

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

本帖子中包含更多资源

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

x
楼主热帖
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-25 21:47 , Processed in 0.140625 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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