赞
踩
从前面的《Windows内存体系》系列文章中我们可以知道,在Windows系统中,每个进程都有自己私有的地址空间。当我们用指针来引用内存的时候,指针的值表示的是进程自己的地址空间的一个虚拟的内存地址。进程不能通过指针来引用其他进程地址空间的内存。因此,如果一个进程有缺陷会导致其引用和覆盖随机地址处的内存,那么这个缺陷的影响就会不会扩散到其他的进程。
独立的地址空间有利于系统的稳定性。但很多时候我们还是需要跨越进程的边界来访问另一个进程地址空间,比如:
为了满足上面的这些需求,我们可以使用DLL注入的技术,将我们自己开发的dll注入到另一个进程的地址空间中,让dll中的代码在该进程的地址空间中执行,那么我们就可以在那个中进程为所欲为了。
理论上任何DLL都可以被注入到其他进程之中,但是大多数情况下,我们注入到其他进程之中是为了实现某些功能、做某些事情的,所以我们需要在我们的DLL被注入之后,DLL中的功能代码能够被调用执行。
我们知道DLL被首次载入到进程中时,会收到DLL_PROCESS_ATTACH
的通知,即调用DllMain
函数,并且参数fdwReason
的值被设为DLL_PROCESS_ATTACH
。我们可以在收到DLL_PROCESS_ATTACH
通知时开始我们的业务逻辑。
下面是一个最简单的dll的源码,在被注入成功后(即收到DLL_PROCESS_ATTACH
通知时)弹出消息提示框:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved ) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, TEXT("我已经被注入啦"), TEXT("信息"), MB_ICONINFORMATION);
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
}
return TRUE;
}
但是,如果DLL_PROCESS_ATTACH
通知处理过程中的操作被挂起(如消息提示框)或者被阻塞(如用户创建了一个消息循环),这样就会导致目标进程中的LoadLibrary(Ex)
函数一直无法返回(dll都是通过LoadLibrary(Ex)
函数来加载的),所以我们一般会在DLL_PROCESS_ATTACH
通知处理过程中创建一个子线程,将业务逻辑放置到该子线程中执行,代码如下:
#include <windows.h>
#include <tchar.h>
#include <process.h>
unsigned int __stdcall PluginProc(LPVOID pArg) {
MessageBox(NULL, TEXT("我已经被注入啦"), TEXT("信息"), MB_OK | MB_ICONASTERISK);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved) {
HANDLE hThread = NULL;
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
{
hThread = (HANDLE)_beginthreadex(NULL, 0, PluginProc, NULL, 0, NULL);
if (hThread) {
CloseHandle(hThread); // 关闭句柄,防止句柄泄漏
}
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
}
return TRUE;
}
另外,当DLL被从目标进程卸载时,DLL会收到DLL_PROCESS_DETACH
通知,我们需要在该通知的处理过程中做好最后的善后工作,防止资源泄漏、程序崩溃等问题出现。
本文介绍了“什么样的DLL可以被用来注入”,后面的文章会着重介绍如何通过不同的方式将DLL注入到目标进程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。