news 2026/9/26 8:05:47

House Of Force

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
House Of Force

你可以把内存想象成一片巨大的未开发的土地,而House Of Force就是一种通过“篡改土地面积”,让你能够瞬间把房子盖到操作系统最核心区域的黑客魔法。


第一步:认识“Top Chunk”(荒野)

在 C 语言的malloc机制中,当你向系统申请内存时,系统会先给你划出一大块连续的内存区域(这就是堆 Heap)。

每次你调用malloc,系统就像切蛋糕一样,从这块区域里切下一小块给你。切剩下来的、最后面那块最大最完整的内存,被称为Top Chunk(也叫 Wilderness,荒野)。

Top Chunk 有一个非常重要的属性:它记录了自己还剩多大(Size)。
当你要申请的内存大于 Top Chunk 的剩余大小时,系统就会发现“哎呀,内存不够了”,然后去向操作系统申请扩容。

第二步:核心漏洞——“指鹿为马”

House Of Force 的起点,是你要有一个漏洞(比如堆溢出),能够让你修改 Top Chunk 的 Size。

试想一下,如果 Top Chunk 原本只剩0x1000大小,但你通过溢出漏洞,把它的 Size 强行改成了-1。

在计算机的无符号整数(unsigned)世界里,-1就是最大的数字(在 64 位系统下是0xFFFFFFFFFFFFFFFF)。

这时候,系统就被你骗了!
系统一看 Top Chunk 的 Size:“哇!原来我还有无限大的内存空间!”
从此以后,无论你向系统malloc申请多大的内存,它都不会去向操作系统要新的空间,而是直接从现在的 Top Chunk 往下切给你。

第三步:空间跳跃魔法

既然系统认为 Top Chunk 无限大,我们就可以利用它进行“空间跳跃”。

假设当前的 Top Chunk 在地址0x10000,而你想去改写系统的核心函数指针(假设在目标地址0x80000)。你要怎么过去呢?

系统切分配内存的逻辑非常简单粗暴:
新的 Top Chunk 地址 = 现在的 Top Chunk 地址 + 你申请的内存大小

所以,你只需要做一道简单的减法题:
偏移量 = 目标地址 - 当前 Top Chunk 地址 - 头部大小(0x10)

你直接调用malloc(偏移量)。
系统一看,你要这么大的内存?没问题,我的 Top Chunk 是“无限大”的!于是它大笔一挥,把 Top Chunk 的指针直接向前推移了这么多距离。

此时,Top Chunk 的位置,已经被你精准地移动到了目标地址(0x80000)的前面!

(注:如果目标地址在 Top Chunk 的“上面”即低地址区,这个减法算出来会是一个负数。但没关系,计算机里的负数相加会产生“整数溢出”,照样能精准绕回到低地址!)

第四步:完成绝杀

现在,Top Chunk 就在你梦寐以求的目标地址门口了。

你只需要再执行一次普通的malloc,比如malloc(0x20)。
系统就会把目标地址(比如0x80000)分配给你。

此时,这个目标地址可能存放着非常重要的东西(比如__malloc_hook,或者 GOT 表中的puts函数指针)。你往这个新申请的内存里写入你的恶意代码地址(比如system("/bin/sh"))。

下次程序再调用相应的函数时,就会直接执行你的恶意代码,拿下服务器的控制权。


总结:House Of Force 的攻击三部曲

  1. 破门 (Overwrite Top Chunk Size):利用溢出漏洞,把 Top Chunk 的 size 改成-1(最大值)。
  2. 铺路 (Bridge the Gap):计算目标地址和 Top Chunk 的距离,申请一个巨大(或极小)的内存块,把 Top Chunk 的指针推到目标地址附近。
  3. 夺权 (Arbitrary Write):再次申请内存,拿到目标地址的控制权,写入恶意数据。

发动这个魔法必须具备的三个条件:

  1. 能够覆盖 Top Chunk 的 size(通常需要一个 Heap Overflow 漏洞)。
  2. 能够自由控制malloc申请的尺寸(需要传入我们计算出的偏移量)。
  3. 知道地址(需要有信息泄露漏洞,知道当前 Top Chunk 在哪,以及你想打的目标地址在哪)。

目前的现状:
这个方法非常经典且暴力,但在较新的 glibc 版本(2.29 及以后)中,加入了对 Top Chunk size 的合法性检查,直接把 size 改成-1会导致程序崩溃。但这依然是理解堆利用(Heap Exploitation)和内存布局最棒的入门级手法。

有没有哪个步骤的逻辑你觉得跳跃了?我们可以针对那一部分再细聊。

例子

我们用一个具体的数字推演,结合几行简单的代码,来看看这场“空间跳跃”是如何在内存中真实发生的。

假设我们有一个存在漏洞的 C 语言程序,并且我们已经通过某种方式(信息泄露漏洞)知道了内存中的两个关键位置:

  1. 当前 Top Chunk 的地址:0x602020
  2. 我们的攻击目标地址:0x804010(比如这里存放着一个只有管理员才能调用的函数指针,我们想把它改成我们的恶意代码地址)

第一步:破门(篡改 Top Chunk Size)

假设程序允许我们申请一段内存,并且存在越界写入(Heap Overflow)的漏洞。

// 1. 申请一段 0x10 大小的内存 char *p = malloc(0x10); // 此时 p 的地址是 0x602000 // 因为这块内存本身需要 0x10 的头部(存放元数据),加上你申请的 0x10,总共占了 0x20。 // 所以,剩下的 Top Chunk 就在它紧挨着的地方:0x602020。 // 2. 利用溢出漏洞,把 Top Chunk 的 Size 强行覆盖为 -1 (在 64 位下是 0xFFFFFFFFFFFFFFFF) // 正常情况下你只能写 p[0] 到 p[15],但漏洞让你能写得更远 write_overflow(p, data_with_0xFFFFFFFFFFFFFFFF);

经过这一步,系统再去检查地址0x602020(Top Chunk)时,会认为:“我这里还有无限大的内存,随便你要多少!”

第二步:铺路(计算偏移并跨越空间)

现在我们要算一笔账:从现在的 Top Chunk (0x602020),跳到目标地址 (0x804010),中间差了多远?

因为我们下一次malloc申请拿到的内存,其实是从目标地址往后算的。为了让我们最终能够往0x804010里面写东西,我们要让新的 Top Chunk刚好落在目标地址的“头顶上”(也就是目标地址减去 0x10 的块头部大小)。

核心计算公式:
跳跃距离 = 目标地址 - 0x10 (预留头部) - 当前 Top Chunk 地址

代入我们的数字:
跳跃距离 = 0x804010 - 0x10 - 0x602020 = 0x201FE0

接下来,我们在攻击脚本(比如 Python)里向程序发送请求,要求申请这么大的内存:

# 3. 申请巨大内存,完成跳跃 malloc(0x201FE0)

系统一看,你要0x201FE0这么大?没问题,Top Chunk 的 Size 是无限大,够切!
于是系统把 Top Chunk 的指针加上了0x201FE0 + 0x10。
此时,Top Chunk 的新地址已经变成了0x804000。

第三步:夺权(拿到目标并写入)

这就到了激动人心的最后一步。Top Chunk 已经在家门口了。

# 4. 再次申请一个小块内存 malloc(0x10)

系统会从当前的 Top Chunk(0x804000)切下一块。系统会保留 0x10 作为块头部,然后把供你使用的用户区域指针返回给你。

0x804000 + 0x10 = 0x804010

你拿到的返回指针,精准地落在了0x804010!也就是我们最初的目标地址。

# 5. 向刚刚拿到的内存里写入恶意数据的地址(比如 system("/bin/sh")) write_to_new_malloc( "恶意代码地址" )

就这样,目标地址原本合法的函数指针,被你替换成了打开服务器 shell 的钥匙。下次程序尝试调用那个合法函数时,就会直接执行你的命令。

如果目标地址比 Top Chunk 还低怎么办?
在真实的漏洞挖掘中,目标地址(比如 glibc 的__malloc_hook)往往比堆的地址要低。这时候目标地址 - 当前 Top Chunk算出来会是一个负数。
但由于底层是无符号运算,这个负数会变成一个极其巨大的正数。当你malloc这个巨大正数时,内存地址会一直向上加,加到突破内存上限(Integer Overflow),最终“绕了一圈”回到底部,精准落在低地址的目标上。逻辑和上面的加法完全一致!

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

Python数据分析实战工具箱:从环境管理到AI辅助工作流

在数据分析这个行当里摸爬滚打了这些年,我越来越觉得一个朴素的道理:工具不在多,而在精。很多人一上来就追新框架、学大模型,结果连最基本的pandas都用得磕磕绊绊。真正高效的数据分析师,靠的是一套经过实战打磨的、稳…

作者头像 李华
网站建设 2026/9/26 8:02:42

MATLAB经验模态分解(EMD)实战:原理、参数调优与工程应用

如果你在MATLAB里对着一堆非线性非平稳信号发愁,FFT看不出门道,小波又拿不准基函数,那么经验模态分解(EMD)大概率是你需要的东西。这几年我在MATLAB里用EMD处理过不少振动和趋势信号,从最初只会调一句emd(x…

作者头像 李华
网站建设 2026/9/26 8:02:18

XGBoost原理与贝叶斯优化实战:科学调参不再玄学

1. 从一次“调参玄学”说起:为什么Day 12我决定死磕这两个词如果你也在自学机器学习的路上记着学习笔记,大概率会碰到这样一个尴尬场景:模型跑出了还行但不够好的分数,于是你打开某篇“调参宝典”,照着网格搜索列了一堆…

作者头像 李华
网站建设 2026/9/26 8:01:07

ReBarUEFI:老平台启用Resizable BAR的底层实现方案

1. 项目概述:老平台“续命”的关键一跃你手头那块积灰的X99主板,配着i7-5820K或E5-26xx v3/v4,显卡却是新买的RTX 4070——开机进系统后,GPU-Z里“Resizable BAR”那一栏却始终是灰色的。不是显卡不支持,也不是CPU不兼…

作者头像 李华
网站建设 2026/9/26 8:00:27

KV Cache优化实战:从OOM到32路并发,显存压缩与复用全攻略

前几天有个读者跑过来问我,说同样都是 4090 单卡,别人能挂 32 路并发,自家服务跑 4 路就开始一个接一个 OOM,同一个开源模型,同一份推理框架,怎么差别这么大。我让他把启动命令和日志贴出来,扫了…

作者头像 李华
网站建设 2026/9/26 8:00:20

CKEditor保留Word格式全攻略:从配置到标题层级修复

你维护过教育平台的话,一定对这样的工单不陌生:老师把Word写好的讲义直接Copy到网页编辑器里,三级标题变成了二级标题,行距缩成一团,表格边框全没了。第一反应往往是“老师不会用编辑器”,但排查到最后&…

作者头像 李华