注入工具

2019年,注入工具一个叫“哥斯拉”的注入工具注入工具在圈子里传开了。它不是注入工具什么正经软件,界面粗糙得像半成品,注入工具但能往目标进程里塞shellcode,注入工具绕过当时主流的注入工具几家EDR。写它的注入工具人在GitHub上留了句话:“别问,问就是注入工具拿来打内网的。”

注入工具的注入工具本质就这么粗暴——把一段代码硬塞进另一个正在运行的进程里,让它替你做事。注入工具听起来简单,注入工具做起来全是注入工具坑。Windows这边,注入工具从最早的注入工具CreateRemoteThread到后来的APC注入、线程劫持、注入工具模块踩踏,每出一种新方法,杀软就跟着更新一波特征库。攻防两边像在玩猫鼠游戏,只不过老鼠每次都得换个新洞钻。

我真正开始接触这块是2020年。当时手上有个项目需要做进程监控,得把探针注入到目标进程里采集数据。试了微软官方的Detours库,功能全但太重,编译出来的DLL快2MB,注入进去目标进程直接卡顿。后来换了个叫minhook的轻量库,体积缩到几十KB,但只支持x86。最后自己动手写了个基于SetWindowsHookEx的简易注入器,代码不到200行,够用。

那段时间我养成了一个习惯:每看到一个注入工具,先看它怎么处理ASLR和DEP。这两个是绕不过去的坎。有些工具图省事,直接要求目标进程关闭DEP,这种在实际环境里根本没法用。好的注入器会在运行时动态解析API地址,用VirtualProtect改内存属性,再恢复现场。细节决定成败,这话在注入领域是字面意思。

注入工具分几大类。最基础的是远程线程注入,OpenProcess拿到句柄,VirtualAllocEx分配内存,WriteProcessMemory写数据,CreateRemoteThread执行。这套流程教科书上都有,但实际用起来,杀软对CreateRemoteThread的监控严得离谱。后来有人发明了“线程池注入”——利用目标进程已有的线程池,往里面插一个工作项。这招隐蔽多了,因为不创建新线程,行为上更像正常程序在调度任务。

再往后是“映射注入”。不写内存,直接用NtMapViewOfSection把一段共享内存映射到目标进程。这种方式连WriteProcessMemory都省了,但需要处理section对象的权限问题。我见过一个叫“黑曼巴”的工具,用这招往浏览器里注入,跑了三个月没被任何杀软报毒。后来作者在论坛上发帖说,原理其实不复杂,关键是选对了目标——浏览器进程本身就有大量共享内存操作,多一个section没人注意。

注入工具的另一面是防御。做安全产品的人得知道攻击者怎么进来,才能把门堵上。微软从Windows 10开始推ACG(Arbitrary Code Guard)和CIG(Code Integrity Guard),直接禁止动态生成代码和加载未签名模块。这招挺狠,把很多老注入工具直接废了。但道高一尺魔高一丈,有人开始研究“合法模块滥用”——不注入自己的代码,而是操纵目标进程已有的合法模块去执行恶意逻辑。这种攻击连ACG都拦不住,因为代码本身就是合法的。

写注入工具的人大多不爱说话。GitHub上那些项目,README往往就几行字,连编译说明都懒得写。但代码质量参差不齐。有的工具连基本的错误处理都没有,注入失败就崩给你看。有的则精细到会检测目标进程的架构、版本、甚至杀软类型,自动选择最合适的注入方式。后者通常是商业渗透测试工具,卖得死贵,但确实好用。

我自己的工具箱里常备三个注入器:一个轻量级的用于日常调试,一个支持多种注入方式的用于对抗环境,还有一个是自己写的“土炮”,专门对付某些奇葩场景。比如有一次遇到个目标进程,常规方法全失效,最后发现它居然没开ASLR,直接硬编码地址就搞定了。这种时候你会觉得,工具再先进,也比不上对目标环境的理解。

注入工具不会消失。只要还有进程隔离,就有人想打破它。区别只在于,下一次突破会从哪个角落冒出来。