0%

DLL注入

Hook钩子

首先是一个比较简单的DLL,可以钩取用户从键盘上输入的信息。

这一节的主要目的应该还是后面调试应用程序那一部分。

那着重说一下调试部分:

​ 本次调试重点在于,能够钩取键盘输入的DLL是如何载入到程序当中的。按书中操作,在调试设置中勾选当DLL载入时暂停的选项。通过主函数体可知,主函数体中存在LoadLibrary这一能将DLL文件导入到应用程序中的关键函数。(该函数的作用:将指定的模块加载到调用进程的地址空间中。指定的模块可能会导致其他模块被加载。)

DLL注入

首先是注入的三个方法:

  1. 创建远程线程
  2. 使用注册表
  3. 消息钩取

创建远程线程注入

涉及关键应用InjectDLL.exe,该应用程序的源码在书中已有详细的逐行介绍,此处不再赘述。(这几章的关键都在实现对应功能的程序的代码,理解其代码是重点和难点,实际操作反而容易。)

说一下句柄的意义—-句柄实际是一个指针,他指向一块包含具体信息数据的内存,可以当做索引 ,所以进程句柄是当你要访问该进程时取得的,使用完毕必须释放。

总的过程就是:

先将要注入的DLL路径写入内存(在此之前会先调用函数分配缓冲区,大小为DLL文件路径字符串的长度)—然后获得加载DLL函数的地址—在要被注入DLL的进程中创建远程线程—调用加载DLL文件的函数来加载(注入)DLL

有一处值得注意:

image-20220105162354191

使用注册表注入

image-20220105162917205

修改AppInit_DLLs表项的值,将其值改为待注入DLL文件的路径(最后以该文件命结尾的完整路径),再将LoadAppInit_DLLs的值改为1.最后重启系统,及完成该修改。

消息钩取暂不做讨论。

DLL卸载

还是一样,先读懂相应程序的源代码。其实跟注入差不多的,只是是卸载罢了。亲自看一遍会有更深的印象。

另外,PE文件直接导入的DLL文件是无法被卸载的,该方法仅适用于自己强行注入的DLL文件。

通过修改PE加载DLL

先贴一篇关于HWND,HANDLE,HMODLE,HINSTANCE的区别的博客,有个基础了解即可。

在这一章停了一段时间,说一下我遇到的问题。

首先就是IID整体大小,14为IID结构体大小,5为IID结构体个数

image-20220105182929724image-20220105183003195

此处因为union结构体的缘故,故只有5个IID结构体。

简单说一下union结构体:(union)共用体占用的内存应足够存储共用体中最大的成员。

然后注意在创建新IDT时是设计了RVA to RAW的转换的,此处也就就不再赘述了。

另外,移动到可用的空白区域即可,不是非要移动到RVA为8C80处。

image-20220105185215395

然后一个点,bit OR是位操作 ( | 这个符号),虽然说结果跟异或(bit XOR)一样。4|8==12==4^8,4|0==4==4^0。

代码注入DLL

本章关键在于读懂InjectCode()函数的代码。
其实使用的关键API就那么几个

OpenProcess()
VirtualAllocEx()相对的有VirtualFreeEx()
WriteProcessMemory()相对的有ReadProcessMemory()
CreateRemoteThread()

多加理解,对着敲一遍也不错。

使用汇编语言编写注入代码

前面编写汇编语言部分可以看看,能大致理解就行(本章后面是由逐行解析的)

关键在于后面的CodeInjection2.cpp的代码。

其实看看代码内容,核心的API确实就上面那几个。不过是加入了要注入的代码的十六进制数据。

总结

纸上得来终觉浅,绝知此事要躬行。还是要多动手实践,这部分很注重实操。如果看不太懂,不妨试着结合网络写笔记,写的过程中逐一突破。

image-20220105220107191

最后再上一碗鸡汤,多是一件美事。

image-20220105220319771