利用CreateRemoteThread向进程注入远程代码时,一般会有以下两种做法:
- 利用LoadLibrary在目标进程加载指定的DLL
- 将代码复制到目标进程,然后启动这段代码
上面的第二种方法其实在使用上更加灵活。因为借用该方法,我们可以灵活地自定义函数(以下简称为启动函数)的参数。其使用流程一般为:
- 利用VirtualAllocEx / WriteProcessMemory 将启动函数的代码复制到目标进程
- 利用VirtualAllocEx / WriteProcessMemory 将启动函数的参数复制到目标进程
- 调用CreateRemoteThread (..., 启动函数指针, 参数指针...)来注入远程线程
在这种注入方式下,由于是将CODE直接从本进程(主调进程)注入到目标进程,因此这个函数的处理需要十分小心才是。
你必须要防止在启动函数代码中引用本进程的内部资源,便如.rdata段(比如常量定义),.text段(比如内部的函数)。
如果你没有遵守以上规则,那么启动函数被复制到目标进程并开始执行后,崩溃是必然的结果,因为这个代码引用的额外资源并不在目标进程中。
我在实际使用过程中就遇到了以下导致崩溃的问题:
在目标进程中用OD查看启动函数代码时,发现代码中被插入了security_cookie功能,其中包括了两个额外引用:
- mov eax, [security_cookie]
- call security_check_cookie
第一个引用实际上是引用了本地进程的rdata段
第二个引用实际上是引用了本地进程的text段
如果解决这个问题呢,实际上微软在MSDN中已经给出了答案,那就是在工程的编译选项中添加以下开关:
/GS-
这样就完全禁止了编译器对启动函数的Guard Stack功能,关于该编译选项可以参考: