各位大侠,大家好。我是Fake77,该文主要是抛砖引玉(我是砖)。
今天为大家带来一个基于Dll劫持的MSVC编译过程劫持思路,我本来是想要研究下MSVC编译器想通过注入的方式劫持编译流,然后通过得出逆向出微软编译器的IR格式,最后通过自己的Pass实现原生的Windows下驱动混淆方案(又或者 编译期代码植入)。
我目前用的方案是自己写的LLVM替换编译工具链的方式来对驱动进行混淆的,但是该方案每次我改动LLVM的时候就需要重新编译LLVM,非常的麻烦。所以我就想着能不能通过注入的方式去做,结果在研究的过程中发现可以通过劫持的方式去做(微软偷懒没有对PASS 相关的DLL进行鉴权导致我们可以利用这个机制进行植入)换句话说这个也是一个代码植入的APT思路,虽然我们已经可以用譬如
等等方式使其编译带毒感染,但是总归都不如通过直接劫持编译器来的快。
更早的没有测过了,至少新版本是可以的

通过替换Dll即可实现。路径如下
如下所示,有两个地方都可以加载Dll并且没有做任何的校验
首先,我们根据cl.exe的名称可以看到他载入后调用了 _InvokeCompilerPassW@16我们可以在IDA里面搜索这个签名。

找到该函数后进入 Trap_callMain 进入编译流程

继续进入 CallMain

继续进入 Trap_main_complie 这里稍微还原以下如果大家是F5看的话应该最后是

他里面还包了一层 main_compile继续

这个非常大的函数就是编译的逻辑了,这里我给出一些大概的东西大家具体可以自己分析。
FileMap句柄(可以通过这个去写文件)
这里可以看到句柄位置

可以通过如下类方法去研究

然后IR的一些格式和操作需要结合 cl.exe的方法才能分析出来,这部分内容我就不写了目前暂不公开,通过如上的句柄已经可以进行劫持了,修改c1.dll通过特征或者PDB获取到句柄后在编译的时候识别标准的__crt_main函数的特征码或者__init_term等等的点都可以注入一些意想不到的东西。我给出c1的主要CFG
该方法挺通用的很多版本都可以用,具体更多用法等大家自己去开发,关于IR的一些研究我就不发了。
.text:00426C20 ; int __fastcall execute(int, int, const WCHAR *lpLibFileName, wchar_t *Name, _DWORD *)
.text:00426C20 ?execute@@YAHW4driver_phases@@PAUpassinfo_t@@PBG2PAPAG@Z proc near in this methods this line
.text:00426E16 call ds:__imp__LoadLibraryExW@12 ; LoadLibraryExW(x,x,x)
they call the loadlibraryExW without check and after that
.text:00426E1C mov ebx, eax
.text:00426E1E test ebx, ebx
.text:00426E20 jz short loc_426E5A
.text:00426E22 push offset aInvokecompiler_0 ; "_InvokeCompilerPassW@16"
.text:00426E27 push ebx ; hModule
.text:00426E28 mov esi, ds:__imp__GetProcAddress@8 ; GetProcAddress(x,x)
.text:00426E2E call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x)
.text:00426E30 mov [ebp+var_28], eax
.text:00426E33 push offset aAbortcompilerp_0 ; "_AbortCompilerPass@4"
.text:00426E38 push ebx ; hModule
.text:00426E39 call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x).text:00426E1C mov ebx, eax (pollute _AbortCompilerPass)
.text:00426E1E test ebx, ebx
.text:00426E20 jz short loc_426E5A
.text:00426E22 push offset aInvokecompiler_0 ; "_InvokeCompilerPassW@16"
.text:00426E27 push ebx ; hModule
.text:00426E28 mov esi, ds:__imp__GetProcAddress@8 ; GetProcAddress(x,x)
.text:00426E2E call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x)
pollute _InvokeCompilerPassW
.text:00426E30 mov [ebp+var_28], eax
.text:00426E33 push offset aAbortcompilerp_0 ; "_AbortCompilerPass@4"
.text:00426E38 push ebx ; hModule
.text:00426E39 call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x)
.text:00426C20 ; int __fastcall execute(int, int, const WCHAR *lpLibFileName, wchar_t *Name, _DWORD *)
.text:00426C20 ?execute@@YAHW4driver_phases@@PAUpassinfo_t@@PBG2PAPAG@Z proc near in this methods this line
.text:00426E16 call ds:__imp__LoadLibraryExW@12 ; LoadLibraryExW(x,x,x)
they call the loadlibraryExW without check and after that
.text:00426E1C mov ebx, eax
.text:00426E1E test ebx, ebx
.text:00426E20 jz short loc_426E5A
.text:00426E22 push offset aInvokecompiler_0 ; "_InvokeCompilerPassW@16"
.text:00426E27 push ebx ; hModule
.text:00426E28 mov esi, ds:__imp__GetProcAddress@8 ; GetProcAddress(x,x)
.text:00426E2E call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x)
.text:00426E30 mov [ebp+var_28], eax
.text:00426E33 push offset aAbortcompilerp_0 ; "_AbortCompilerPass@4"
.text:00426E38 push ebx ; hModule
.text:00426E39 call esi ; GetProcAddress(x,x) ; GetProcAddress(x,x).text:00426E1C mov ebx, eax (pollute _AbortCompilerPass)
.text:00426E1E test ebx, ebx
.text:00426E20 jz short loc_426E5A
.text:00426E22 push offset aInvokecompiler_0 ; "_InvokeCompilerPassW@16"
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!