Hook钩子
首先是一个比较简单的DLL,可以钩取用户从键盘上输入的信息。
这一节的主要目的应该还是后面调试应用程序那一部分。
那着重说一下调试部分:
本次调试重点在于,能够钩取键盘输入的DLL是如何载入到程序当中的。按书中操作,在调试设置中勾选当DLL载入时暂停的选项。通过主函数体可知,主函数体中存在LoadLibrary这一能将DLL文件导入到应用程序中的关键函数。(该函数的作用:将指定的模块加载到调用进程的地址空间中。指定的模块可能会导致其他模块被加载。)
DLL注入
首先是注入的三个方法:
- 创建远程线程
- 使用注册表
- 消息钩取
创建远程线程注入
涉及关键应用InjectDLL.exe,该应用程序的源码在书中已有详细的逐行介绍,此处不再赘述。(这几章的关键都在实现对应功能的程序的代码,理解其代码是重点和难点,实际操作反而容易。)
说一下句柄的意义—-句柄实际是一个指针,他指向一块包含具体信息数据的内存,可以当做索引 ,所以进程句柄是当你要访问该进程时取得的,使用完毕必须释放。
总的过程就是:
先将要注入的DLL路径写入内存(在此之前会先调用函数分配缓冲区,大小为DLL文件路径字符串的长度)—然后获得加载DLL函数的地址—在要被注入DLL的进程中创建远程线程—调用加载DLL文件的函数来加载(注入)DLL
有一处值得注意:
使用注册表注入
修改AppInit_DLLs表项的值,将其值改为待注入DLL文件的路径(最后以该文件命结尾的完整路径),再将LoadAppInit_DLLs的值改为1.最后重启系统,及完成该修改。
消息钩取暂不做讨论。
DLL卸载
还是一样,先读懂相应程序的源代码。其实跟注入差不多的,只是是卸载罢了。亲自看一遍会有更深的印象。
另外,PE文件直接导入的DLL文件是无法被卸载的,该方法仅适用于自己强行注入的DLL文件。
通过修改PE加载DLL
先贴一篇关于HWND,HANDLE,HMODLE,HINSTANCE的区别的博客,有个基础了解即可。
在这一章停了一段时间,说一下我遇到的问题。
首先就是IID整体大小,14为IID结构体大小,5为IID结构体个数
此处因为union结构体的缘故,故只有5个IID结构体。
简单说一下union结构体:(union)共用体占用的内存应足够存储共用体中最大的成员。
然后注意在创建新IDT时是设计了RVA to RAW的转换的,此处也就就不再赘述了。
另外,移动到可用的空白区域即可,不是非要移动到RVA为8C80处。
然后一个点,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确实就上面那几个。不过是加入了要注入的代码的十六进制数据。
总结
纸上得来终觉浅,绝知此事要躬行。还是要多动手实践,这部分很注重实操。如果看不太懂,不妨试着结合网络写笔记,写的过程中逐一突破。
最后再上一碗鸡汤,多是一件美事。