news 2026/9/27 22:46:07

House of Orange

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
House of Orange

“House of Orange” 是在 CTF(网络安全夺旗赛)和真实漏洞利用中非常经典且高级的一种堆溢出利用技术。它的名字来源于 2016 年 HITCON CTF 比赛中的一道同名题目。

为什么会有 House of Orange?(它的核心亮点)

在常规的黑客攻击中,如果你想利用内存里的“堆(Heap)”干坏事,通常需要程序里有一个free()函数(把内存还给系统的函数)。但有些程序写得很“死”,它只允许你申请内存(malloc),根本没有提供释放内存(free)的功能。

House of Orange 的出现就是为了打破这个限制:它能在没有free函数的情况下,强行制造出一个被释放的内存块,从而完成后续的攻击。


基础知识铺垫(你必须知道的 3 个概念)

为了看懂这个魔法,你需要知道 Linux 系统分配内存时的三个设定:

  1. Top Chunk(顶层块):
    想象系统最初给了你一块巨大无比的蛋糕(堆内存)。每次程序调用malloc申请内存,系统就从这块大蛋糕上切一块给你。切剩下来的那一块巨大的、还没有被分配出去的内存,就叫Top Chunk。
  2. sysmalloc(系统扩容):
    如果你某次狮子大开口,要申请一块巨大的内存,但当前的 Top Chunk 已经不够切了怎么办?系统会触发一个叫sysmalloc的机制,重新向操作系统申请一块新的大蛋糕。
  3. Unsorted Bin(垃圾桶):
    在触发sysmalloc申请新蛋糕时,系统是一个很节约的人,它不会把原来那块没用完的旧 Top Chunk 直接扔掉,而是把它放进一个叫Unsorted Bin的垃圾桶(回收站)里,留着以后给那些申请小块内存的需求用。

重点来了:只要一块内存进入了 Unsorted Bin,它就等同于被free(释放)了!这就是 House of Orange 的突破口。


House of Orange 的攻击四部曲

现在我们来看看,黑客是如何一步步无中生有,拿下服务器权限的。

第一步:篡改 Top Chunk 的大小(骗过系统)

程序里存在一个堆溢出漏洞。黑客利用这个漏洞,在往某块已经申请的内存里写数据时,故意写得太长,越界覆盖到了紧挨着它的 Top Chunk 的头部数据。
Top Chunk 的头部记录着它自己的大小(Size)。黑客通过溢出,把原本比如有 131072 字节(0x20000)大小的 Top Chunk,强行修改成了一个很小的值,比如 4096 字节(0x1000)。

新手注意:这个假大小不能随便瞎写,必须满足系统的检查条件,主要是:

  • 必须大于最小限制(通常是 0x20)。
  • 必须和系统的内存页(Page)对齐,通常大小要是 4096 的倍数(末尾是 000)。
  • 它的“前一个块正在使用”标志位(PREV_INUSE)必须是 1。

第二步:触发扩容,获得“释放”的内存

现在系统以为当前的 Top Chunk 只剩 4096 字节了。这时,黑客操控程序,强行申请一块大于 4096 字节的内存(比如申请 4097 字节)。

系统一看:哎呀,Top Chunk 只有 4096 了,不够切啊!于是系统乖乖地触发了sysmalloc去要新蛋糕,顺手就把我们那个被篡改过大小的旧 Top Chunk扔进了 Unsorted Bin 里。
至此,黑客在没有调用任何free函数的情况下,成功获得了一块被释放的内存!

第三步:Unsorted Bin Attack(改写关键指针)

旧 Top Chunk 进垃圾桶后,黑客通过漏洞再次修改这块垃圾桶里的内存,把它内部的指针(bk指针)指向系统内核中一个极其敏感的地方——_IO_list_all。
(_IO_list_all是 Linux 系统用来记录所有输入输出流,比如标准输入、标准错误输出的链表头。)

当系统下次再去整理垃圾桶(Unsorted Bin)时,会触发一个漏洞机制,不小心把垃圾桶在系统里的地址,强行写到了_IO_list_all里面。这就好比黑客把系统内部的高铁调度中心,强行指向了黑客自己搭建的一条野鸡铁轨上。

第四步:FSOP 劫持程序流(最终绝杀)

这是最复杂但也是最致命的一步,被称为FSOP (File Stream Orientation Programming)。

黑客在堆内存里提前伪造好了一个假的“文件流结构体(_IO_FILE)”和一套“假的执行函数表(vtable)”。因为第三步已经把_IO_list_all指向了堆里,系统现在会把黑客伪造的数据当成合法的文件操作流。

接着,黑客故意在系统中制造一个内存崩溃错误(比如再次破坏堆的结构)。当系统发现堆坏了,想要通过标准错误流(stderr)打印一句“Malloc: memory corrupted!”这样的报错信息时,它会去读取_IO_list_all。

这一读就中计了!系统顺着黑客伪造的结构体,找到了黑客伪造的函数表,本来是想执行“打印报错”的函数,结果却执行了黑客提前写好的system("/bin/sh")。

瞬间,黑客拿到了服务器的 Shell 控制台,游戏结束。


总结一下流程

对于 0 基础的你,只需要在脑海里建立这样一条逻辑链:

  1. 没有 free?-> 用堆溢出修改 Top Chunk 大小,骗它说蛋糕不够了。
  2. 触发 sysmalloc!-> 申请大内存,强迫系统把旧 Top Chunk 扔进回收站(等同于 free)。
  3. 改写 _IO_list_all!-> 利用回收站的机制,把系统的关键 IO 链表指向黑客控制的区域。
  4. 报错触发后门!-> 故意制造错误让系统打印信息,系统在打印时使用被篡改的 IO 链表,最终执行了黑客的恶意命令。

补充一点历史背景:这种技术在 Glibc 2.23 和 2.24 版本中非常流行且无解。但在后来的 Glibc 2.26+ 甚至更高的版本中,系统增加了各种安全检查(比如引入了 tcache 以及对 vtable 进行了严格校验),原汁原味的 House of Orange 已经很难直接打通了,但这依然是学习高级堆漏洞利用必不可少的里程碑式技术。

例子

为了让你直观地看到这个“魔法”是如何在代码层面发生的,我们通过一个极简的 C 语言示例,带你走完 House of Orange 最核心的前两步:如何利用堆溢出,无中生有地制造出被释放的内存(Unsorted Bin)。

在真实的 Linuxptmalloc内存管理器中,要骗过系统并不容易。我们直接来看代码和内存布局的真实变化。

1. 存在漏洞的 C 代码(靶场环境)

假设我们有下面这段存在堆溢出漏洞的 C 代码:

#include <stdio.h> #include <stdlib.h> int main() { // 1. 程序分配了一小块内存 // malloc(0x10) 实际在内存中会分配 0x20 字节(包含 0x10 的头部控制信息) char *p1 = malloc(0x10); // ========================================== // 此时的内存布局: // [ p1 chunk 头部 (0x10 字节) ] // [ p1 数据区 (0x10 字节) ] <--- p1 指针指向这里 // [ Top Chunk 头部 (Size: 0x20fe1) ] <--- 紧挨着 p1 // [ Top Chunk 巨大的剩余空间... ] // ========================================== // 2. 黑客利用堆溢出漏洞,越界修改紧挨着的 Top Chunk 大小 // 注意:这里的 0x0fe1 不是随便写的,必须满足系统的严格检查 unsigned long *top_chunk_header = (unsigned long *)(p1 + 0x10); *top_chunk_header = 0x0fe1; // 3. 强行申请一块大内存,触发系统扩容 (sysmalloc) char *p2 = malloc(0x1000); return 0; }

2. 黑客视角的详细拆解

动作一:精心计算并修改 Top Chunk 大小

在代码的第 2 步,我们把 Top Chunk 的 Size 从默认的0x20fe1(大约 135 KB)改成了0x0fe1(4065 字节)。

在ptmalloc的底层机制中,这个伪造的大小必须满足三个严苛条件,否则程序会直接崩溃(Segmentation Fault):

  1. 必须大于最小限制:大于MINSIZE(通常是 0x20)。0x0fe1满足。
  2. 前一个块必须是使用中:最低位(PREV_INUSE)必须是 1。0x0fe1的二进制最低位是 1,满足。
  3. 必须与内存页(Page)对齐:这是最难的一点。公式是(Top_Chunk_首地址 + Top_Chunk_Size) & 0xfff == 0。
  • 假设堆的起始地址是0x555555602000。
  • p1 占用了0x20字节,所以 Top Chunk 的首地址是0x555555602020。
  • 0x555555602020 + 0x0fe1 = 0x555555603001。(注意:实际计算对齐时会忽略标志位,即加0x0fe0,结果是0x555555603000)。
  • 0x555555603000的末尾是三个 0(即 4096 的倍数),完美对齐内存页!

动作二:触发sysmalloc榨干 Top Chunk

在代码的第 3 步,程序调用了malloc(0x1000)。

系统内核接到请求后开始思考:

  1. 客户要0x1000字节。
  2. 我去看看 Top Chunk 还有多少... 咦?只有0x0fe0字节了(扣除标志位)。
  3. 0x0fe0 < 0x1000,蛋糕不够切了!
  4. 系统被迫调用sysmalloc向操作系统申请新的一大块内存。
  5. 关键漏洞爆发:秉承着不浪费的原则,系统把旧的这个0x0fe1大小的 Top Chunk,直接丢进了 Unsorted Bin(回收站)里。

至此,虽然整个 C 程序里连一个free()函数都没有写,但黑客已经在内存里拿到了一块合法的、被释放的 Unsorted Bin Chunk。


3. 后续的绝杀(Python Exploit 伪代码)

拿到这块进入垃圾桶的内存后,黑客会再次利用漏洞向里面写数据。在真实的 CTF 比赛(如使用 Pwntools)中,构造出来的攻击载荷(Payload)大致长这样:

# 假设我们可以再次向旧的 Top Chunk(现在的 Unsorted Bin)写入数据 # 1. 伪造 Chunk 头部信息 payload = p64(0) + p64(0x61) # 2. Unsorted Bin Attack 核心:改写 bk 指针 # 把垃圾桶的后向指针指向系统 IO 链表头 _IO_list_all 的地址减去 0x10 payload += p64(0) + p64(_IO_list_all - 0x10) # 3. 伪造 _IO_FILE 结构体 (FSOP) payload += p64(0) + p64(1) # 绕过底层的 assert 检查 payload += p64(0) * 7 # 填充无关数据 payload += p64(system_addr) # 偷偷塞入 system 函数的地址 # 4. 伪造 vtable (虚函数表) # 把系统本该调用的 _IO_OVERFLOW (比如打印报错信息) 强行指向我们的 system 函数 payload += p64(fake_vtable_addr) # 发送攻击载荷覆盖内存 send(payload) # 再次发起一个会导致堆崩溃的 malloc,触发系统向终端打印报错,瞬间拿到 shell malloc(0x10)

一旦系统因为堆结构被破坏而尝试调用_IO_OVERFLOW打印错误信息,就会顺着被我们污染的_IO_list_all,读到伪造的虚函数表,最终将原本用于报错的字符串"/bin/sh"作为参数,执行了system("/bin/sh")。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 22:45:36

牛商网做网站避坑指南:新手备案不懵圈的最佳实践

牛商网做网站避坑指南:新手备案不懵圈的最佳实践 备案号还没下来,网站上线计划就全乱套了。这种“备案流程一头雾水”的焦虑,几乎是每个初次尝试 牛商网做网站 的创业者都会遇到的死穴。很多团队以为买好服务器、做好页面就能开张,结果卡在工信部的审核环节,眼睁睁看着竞争对手抢跑。…

作者头像 李华
网站建设 2026/9/27 22:45:23

音乐介绍网站怎么做图解步骤及安全加固

音乐介绍网站怎么做图解步骤及安全加固 很多站长在搭建音乐介绍网站时,最头疼的往往不是设计,而是域名备案和服务器配置。特别是涉及到音频文件上传、用户评论功能时,如果不懂底层安全逻辑,很容易被黑客盯上。 这里有一份详细的 图解步骤 ,不仅告诉你怎么建,更教你怎么防。很多新手在 工信部ICP备案系统…

作者头像 李华
网站建设 2026/9/27 22:45:13

2026最新:如何做网站的导航栏,避开域名与服务器部署的3大隐形坑

2026最新:如何做网站的导航栏,避开域名与服务器部署的3大隐形坑 很多老板一上来就问导航栏怎么做,但真正卡住项目的,往往是后台那些看不见的东西——域名解析配置错误、服务器端口被防火墙拦截、SSL证书链断裂导致HTTPS跳转失败。这些底层架构问题,比前端代码复杂十倍,却直接决定用户能不能打开你的网站…

作者头像 李华
网站建设 2026/9/27 22:45:05

3招解决网站浏览器兼容性问题吗图解步骤

3招解决网站浏览器兼容性问题吗图解步骤 昨天凌晨两点,我盯着后台告警信息,手心全是汗。网站突然挂满了赌博广告弹窗,用户投诉电话打爆,我第一反应是删文件、改密码,结果第二天广告又回来了。那一刻我才明白, 网站被黑挂马不知道怎么办…

作者头像 李华
网站建设 2026/9/27 22:45:04

申请网站域名多少钱?从零搭建避坑指南与预算拆解

申请网站域名多少钱?从零搭建避坑指南与预算拆解 找建站公司报价单上写着“域名赠送”,结果年底续费时直接翻脸要钱?或者被忽悠买了个高价后缀,最后发现根本不符合你的业务定位?这种被坑高价的情况,在从零搭建网站的初期阶段太常见了。很多甲方对接人拿到报价单,看到“域名”两个字就点头,根本没意识到这背后藏着续…

作者头像 李华
网站建设 2026/9/27 22:45:02

网站建设见站分析和准备论文对比评测

不会代码想建站?看懂这份报价单,避开90%的坑 自己不会代码,但老板下周就要上线官网,这种焦虑我太懂了。很多人第一反应是找外包,结果一开口,报价单像天书一样糊一脸:有的说五千搞定,有的张口就是五万。这中间的差价,到底差在哪?今天不整虚的,直接拆解 建站报价 里的门道,带你把…

作者头像 李华