HideNimMain-Hide NimMain in DLL

相信很多使用nim做过开发或者免杀的师傅都遇到过这种情况,使用nim编译的dll会默认导出一个NimMain函数,即使你没有定义该函数

对于正常开发来说,这也无可厚非。但对于使用nim来做免杀或者其他红队相关的工作,要尽可能的减少文件的特征。

注: 此工具并非新技术,仅仅是笔者对原始文章的重构与扩展

编译过程

首先nim编译器在编译时会对所有参与编译的nim源文件生成对应的c语言中间文件(取决你使用的编译标志),默认情况下如果没有使用--nimcache编译标志指定中间文件生成位置,那么编译器会默认在%USERPROFILE%\\nimcache\\project生成对应缓存文件,linux默认会在$HOME/.cache/nim/project
其中project会根据编译标志-d参数的不同有所变化,如指定-d:debug则会生成project_d-d:release则会是project_r

其中<project>会根据编译标志-d参数的不同有所变化,如指定-d:debug则会生成<project>_d-d:release则会是<project>_r

image-20240309165327783

image-20240309165631266

以此项目为例,在生成的众多文件中需要重点关注的就是@<project>.nim.c此文件为项目主文件经由nim编译器生成的对应C语言文件

image-20240309170104559

<project>.json则保存了所有编译及链接所需的命令

image-20240309170316038

修补NimMain

首先使用nim c --noLinking:on -d=mingw --app=lib --nomain demo.nim来生成demo对应的C文件

image-20240309172242514

在生成的文件中,nim编译器自动为NimMain使用了N_LIB_EXPORT

N_LIB_EXPORT通常用于标记需要被导出的函数或变量,这意味着使用 N_LIB_EXPORT 标记的函数或变量可以被其他模块或外部程序引用和调用。

那么我们只需要修改这个默认的宏就可以阻止NimMain函数导出,如将其修改为N_LIB_PRIVATE

image-20240309173408702

注意在修改完后,不能再使用nim编译器进行编译,这样会覆盖掉修改的宏。我们需要手动执行<project>.json中编译和链接的操作

在参考文章中作者给出了一个修改的工具compFiddler,但此仓库已被作者删除

image-20240309174940676

根据此原理笔者重写此工具,并加入了对x86和x64的支持

image-20240309180919317

运行后会在out目录下生成两个dll,<project>.dll为原始dll,<project>-nomain.dll为patch后的dll

代码已上传至Github

总结

此方法仅仅作为最基础的处理手段,要想运用在实际场景中还需结合其他规避手段

除了使用patch源文件的方法还可以使用加载def文件来达到相同的目的,原理类似此处不再进行赘述。

参考