Windows一大标志性技术就是消息循环,Windows 的窗口是由消息驱动的,windows在产生的各种事件、输入时通过将其信息封成一个个消息结构,随后放入消息队列,等待线程通过API的方式取出消息进行处理。
此次注入方式是一种针对于GUI线程的注入,也是频繁使用的一种注入技术,其原理是通过Windows 消息钩子机制进行的DLL注入。消息钩子可以在当前线程或全局模式下设置拦截消息的钩子,对拦截的消息进行处理、阻断或放行。
SetWindowsHookEx函数定义:
HHOOK
WINAPI
SetWindowsHookExW(
_In_ int idHook, //WH_* 取值范围
_In_ HOOKPROC lpfn, //Hook处理函数
_In_opt_ HINSTANCE hmod, //函数来自于的模块(NULL标识本进程程序)
_In_ DWORD dwThreadId //Hook的目标线程ID
);
idHook常用的取值:
有些类型的钩子仅仅支持全局,而不支持单个线程。
WH_CALLWNDPROC |
Thread or global |
WH_CALLWNDPROCRET |
Thread or global |
WH_CBT |
Thread or global |
WH_DEBUG |
Thread or global |
WH_FOREGROUNDIDLE |
Thread or global |
WH_GETMESSAGE |
Thread or global |
WH_JOURNALPLAYBACK |
Global only |
WH_JOURNALRECORD |
Global only |
WH_KEYBOARD |
Thread or global |
WH_KEYBOARD_LL |
Global only |
WH_MOUSE |
Thread or global |
WH_MOUSE_LL |
Global only |
WH_MSGFILTER |
Thread or global |
WH_SHELL |
Thread or global |
WH_SYSMSGFILTER |
Global only |
[摘自 微软官方文档]
这里使用WH_CBT针对指定线程进行Hook。
若指定线程不是当前进程中的,则会将DLL映射到对方进程中。
同样的如果需要拦截对方线程的消息只有两种可能,一种就是进入到对方进程,还有一种是在内核完成。这也就是为什么可以用来DLL注入。
注入流程:
1. 加载需要注入到对方进程中的DLL库
2. 从加载的库中获得对于拦截消息的处理函数
3. 通过SetWindowsHookEx向对方进程的线程挂接消息钩子
由于这里需要自己也加载注入的DLL库,但实际上我们并不想在本地也执行DLL注入后的功能。这里采用一个事件通知目标DLL是否要执行注入操作,或者只是简单的加载库。
DllMain中的DLL_PROCESS_ATTACH环境下添加部分代码:
HANDLE hLoadEvt = OpenEvent(EVENT_ALL_ACCESS, FALSE, GLOBAL_LOAD_EVENT); //是否驻留
if (hLoadEvt)
{
if (WaitForSingleObject(hLoadEvt, 0) == WAIT_OBJECT_0)
{
CloseHandle(hLoadEvt);
return TRUE; //驻留并且不触发注入操作
}
CloseHandle(hLoadEvt);
}
注入PROCEXP效果
完整代码:
int main()
{
BOOLEAN isSuccess = FALSE;
DWORD dwThreadId;
printf("输入线程ID:");
scanf_s("%d", &dwThreadId);
HHOOK hHook = NULL;
HANDLE hDll = NULL;
HANDLE hInjectEvt = NULL;
HANDLE hLoadEvent = NULL;
do {
hLoadEvent = CreateEvent(NULL, TRUE, FALSE, GLOBAL_LOAD_EVENT);
if (!hLoadEvent)
break;
SetEvent(hLoadEvent);
hDll = LoadLibrary(DLL_NAME);
if (!hDll)
{
printf("加载Dll失败!n");
break;
}
ResetEvent(hLoadEvent);
PVOID MsgCallback = GetProcAddress(hDll, "MsgCallback");
if (!MsgCallback)
{
printf("获得Dll回调函数失败!n");
break;
}
hInjectEvt = CreateEvent(NULL, FALSE, FALSE, GLOBAL_INJECT_EVENT);
if (!hInjectEvt)
{
printf("创建事件失败!n");
break;
}
hHook = SetWindowsHookEx(WH_CBT, MsgCallback, hDll, dwThreadId);
if (!hHook)
{
printf("创建消息构造!n");
break;
}
WaitForSingleObject(hInjectEvt, INFINITE);
printf("成功注入!n");
UnhookWindowsHookEx(hHook);
isSuccess = TRUE;
} while (FALSE);
if (!isSuccess)
printf("错误代码%dn", GetLastError());
if (hLoadEvent)
CloseHandle(hLoadEvent);
if (hHook)
UnhookWindowsHookEx(hHook);
if (hDll)
FreeLibrary(hDll);
return 0;
}
本文始发于微信公众号(锋刃科技):DLL注入--SetWindowsHookEx 注入
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论