DLL隐藏初探
DLL隐藏
属于是看着别人的文章,用着别人的工具在这儿玩儿得不亦乐乎了。
1.何为DLL?
1 | 动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库。例如,在 Windows 操作系统中,Comdlg32.dll 执行与对话框有关的常见函数。因此,每个程序都可以使用该 DLL 中包含的功能来实现“打开”对话框。这有助于避免代码重用和促进内存的有效使用。 |
总而言之就是DLL这种技术可以使得程序模块化,同时让程序加载速度更快。
详细解释见下面的链接:
https://encyclopedia.thefreedictionary.com/Dynamic-link+library
2.为啥要隐藏DLL?
一句话总结:没做啥坏事,干嘛隐藏自己呢?所以隐藏了自己,那有很大的可能性是要做坏事:
1.木马以DLL形式注入进正常进程并隐藏自己,导致无法追踪溯源,如键盘记录木马,感染型木马
2.游戏外挂通过该种方式躲避游戏自身的“模块检测”,如DXF的第三方木马检测
除了坏事儿之外,在一些常见的攻防对抗中,如若用到windows木马,不仅要注意免杀工作,有时也需要通过该技术实现持久性隐藏攻击。
3.DLL隐藏常见手法
一.手动载入
所谓手动载入就是自己去实现LoadLibrary函数,从理论上讲,这种方法隐藏效果是最棒的,但是实现一个基本的PEloader并不是一件容易的事情,如果还要考虑兼容性完美,就必须还得妥善处理TLS,资源,线程等问题。(不太易上手)
二.痕迹消除
这个就比较好说了,我们在注入DLL的时候,通常要选择去调用 LoadLibrary函数,然后再擦除痕迹,这样不用去处理那些TLS,资源,线程等为了解决兼容性产生的问题。但是Windows大家都清楚,表面风平浪静,背地里风起云涌,说不准现在你电脑的XXX安全卫士正在对你的电脑做些什么呢,这些都是你不通过技术手段看不到的东西,实际上没有什么好的方法把痕迹真正的消除。
以DLL擦除痕迹为例,网上大多数的方法都是通过PEB双向断链,需要很多的硬编码,麻烦不说,通过内存暴力搜索还是会露出尾巴来
攻防无绝对,攻防本身就是一个提升本身技术的过程,只要能够通过一个比较合适的方法,实现相应的功能,便具有可行性。
4.DLL编写与注入测试
一.DLL编写:
①.于vs中创建一个空的项目。
②.添加C语言代码如下:
1 |
|
③.同时在项目属性中设置:
④.而后对文件进行编译生成即可。
二.DLL注入测试:
见演示。
由图可见进程中已经注入进入了我们的DLL,且内存地址为0x78EB0000
三.手写代码实现注入
谈完DLL编写和利用工具注入测试,我们来大致了解一下代码实现注入,方法有很多,但原理大致相同,我在这里以线程注入dll为例:
代码编写:
1 |
|
代码解析:
首先,通过调用OpenProcess
函数获取目标进程的句柄(hProcess
)。OpenProcess
函数使用了PROCESS_ALL_ACCESS
参数,表示打开进程时拥有最高权限。然后,通过VirtualAllocEx
函数在目标进程中申请一块内存(pReturnAddress
),用于存储DLL文件路径。接着,使用WriteProcessMemory
函数将DLL文件路径写入到刚才申请的内存空间中。
之后,通过调用LoadLibrary
函数加载KERNEL32.DLL
库,并使用GetProcAddress
函数获取LoadLibraryA
函数的地址(lpStartAddress
)。
接下来,使用CreateRemoteThread
函数在目标进程中创建一个远程线程,该线程将在目标进程的上下文中执行lpStartAddress
函数,并将pReturnAddress
作为参数传递给它。这样,目标进程就会执行LoadLibraryA
函数,将DLL文件路径作为参数加载到自己的地址空间中。
最后,通过调用WaitForSingleObject
函数等待远程线程事件的发生,直到线程执行完毕或超时。
整个过程完成后,关闭线程和进程句柄,释放相关资源,避免内存泄漏。
根据传入参数,记录我们要传入的数据:
进程ID:xxxx
路径:xxxxxx
而后将两个参数写入到程序对应的位置当中去,生成exe后丢到虚拟机中即可实现dll注入(此步还未复现)
成功注入之后,应该会弹出信息框,通过分析源代码,我们总结了一下注入流程:
1.在别人的程序里开辟内存空间A
2.将 LoadLibrary 函数参数写入A
3.获取LoadLibrary函数地址
4.在别人的程序里远程执行 LoadLibrary实现加载外部DLL
由此可见 LoadLibrary很重要,这个玩意竟然实现了注入!