DLL注入--SetWindowsHookEx 注入

  • A+
所属分类:逆向工程


Windows一大标志性技术就是消息循环,Windows 的窗口是由消息驱动的,windows在产生的各种事件、输入时通过将其信息封成一个个消息结构,随后放入消息队列,等待线程通过API的方式取出消息进行处理。

此次注入方式是一种针对于GUI线程的注入,也是频繁使用的一种注入技术,其原理是通过Windows 消息钩子机制进行的DLL注入。消息钩子可以在当前线程或全局模式下设置拦截消息的钩子,对拦截的消息进行处理、阻断或放行。

SetWindowsHookEx函数定义:

HHOOKWINAPISetWindowsHookExW(    _In_ int idHook, //WH_* 取值范围    _In_ HOOKPROC lpfn, //Hook处理函数    _In_opt_ HINSTANCE hmod, //函数来自于的模块(NULL标识本进程程序)_In_ DWORD dwThreadId //Hook的目标线程ID);

 

idHook常用的取值:

#define WH_KEYBOARD         2 //键盘消息#define WH_GETMESSAGE       3 //监视发布到消息队列的消息#define WH_CBT              5 //激活,创建,销毁,最小化,最大化,移动或调整窗口大小之前调用此函数#define WH_MOUSE            7 //鼠标消息#define WH_KEYBOARD_LL     13 //低级键盘消息#define WH_MOUSE_LL        14 //低级鼠标消息

有些类型的钩子仅仅支持全局,而不支持单个线程。

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效果

DLL注入--SetWindowsHookEx 注入


完整代码:

#include <stdio.h>#include <tchar.h>#include <windows.h>
#define DLL_NAME _T("X:\XXX\XXX\DllInject.dll")
#define GLOBAL_INJECT_EVENT _T("Global\Inject")#define GLOBAL_LOAD_EVENT _T("Global\Load")
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 注入

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: