最近最有趣的成果是复现了cve-2025-4609, 这个漏洞可以在渲染器进程获取一个browser线程的句柄, 结合前面两篇的v8的洞, 达到了完整120-132左右的chrome利用链.
这个洞一开始看感觉复现起来的难度十分的大, 作者给出的poc是在renderer进程源码层面的patch, 但正常打renderer进程拿到的是任意shellcode执行, 更何况chromium的源码是cpp, 那在shellcode层面去复现的难度就更大了.
1
我就掏出了之前玩hook sshd的小技巧, 主体用c写, 最后再编译成shellcode. 这样就省力很多了. 甚至很多时候还可以直接#include "Windows.h"来引用windows的结构体, 不需要自己实现
但要注意的一点是static变量不能用, 我只注入了.text段的代码, 而static变量处在data段. 另外像是一些大数组的初始化, 编译器通常会将其优化成memcpy, 从data段复制过来需要的数据, 这也需要避免. 我的方法是让ai给我搓了一个辅助脚本builtin_arrays.py, 随后脚本会辅助生成手动初始化大数组的函数.
再后来我要考虑的就是用c的inline hook, 去把renderer进程内的函数按照作者给出的源码patch一点一点还原. 但也有一些是不需要还原的, 例如判断是否在renderer进程内(因为实际攻击场景我们拿到的肯定是renderer)
2
另一个比较大的困难就是如何用c去还原和实现cpp的代码, chrome里面复杂的cpp对象一大堆, 人工去确定这个cpp对象然后塞到c结构体里面感觉不太现实.
于是我选择了ai一把梭, 让ida加载chrome.dll, 并且通过ida-no-mcp导出结果, 让codex读代码和ida解析的二进制结构体偏移, 并且把大部分用到的cpp函数和对象全部用c重写一遍.
这样我们用c手搓了chrome里面的一些cpp对象, cpp的函数调用倒还好, 有些简单的函数(比如getter方法)我也让codex实现了.
但某些cpp函数过于复杂, 没必要自己实现, 计算好该函数偏移, 强制跳转到chrome.dll里面对应实现就可以了. 还遇到一些问题, 比如内联的函数我没法直接调用, 于是只好让codex再多实现一层, 只留下非内联的函数不实现, 由我来找偏移并且手动跳转.
还有个小巧思是当时codex的道德限制比较严格, 于是我只是让他自己用c来实现一遍我需要的部分代码, 最后我再整理进我的exp. 所以codex从头到尾都不知道他其实在帮我打洞(笑.
3
在还原了作者的patch之后再手动调用RequestIntroduction即可触发整条链子, 拿到浏览器线程句柄. 随后我用NtSetThreadContext这几个函数来设置浏览器线程的寄存器.
不过很扯是SetThreadContext只能控制非易失寄存器, 微软官方文档也不写一句, 而且看cve-2025-4609作者的exp似乎又可以设置所有寄存器, 当时让我挺困惑的. 好在最后还是找到gadget来用, 还是能打出来.
4
顺带一提在后续做适配的时候, 为了自动化的拉取制定版本的chrome.dll和chrome.dll.pdb, 开了一个新的chrome_version2dll, 有一些自动脚本, 欢迎使用XD