今天学习了使用SetWindowsHookEx方式注入DLL。
DLL注入的方式主要有两种:1)远程线程注入;2)使用SetWindowsHookEx方式注入。
假设A.exe要将 val.dll注入到B.exe,主要的流程如下:
①编写val.dll,其中val.dll必须至少导出一个函数,因为后面要传给SetWindowsHookEx作为回调函数。
②A加载val.dll,获取回调函数地址f.
③调用SetWindowsHookEx设置全局钩子,钩子的类型由自己决定。学习中使用的是WH_KEYBOARD。传入回调函数地址,dll的句柄,线程ID,设置为0表示对全局有效。如果函数返回非NULL,则说明设置成功。
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
/*
* Load library in which we'll be hooking our functions.
*/
HMODULE dll = LoadLibrary(L"test_dll.dll");
if(dll == NULL) {
DWORD err = GetLastError();
printf("The DLL could not be found.\n");
getchar();
return -1;
}
//__asm int 3;
/*
* Get the address of the function inside the DLL.
*/
HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "meconnect");
if(addr == NULL) {
printf("The function was not found.\n");
getchar();
return -1;
}
/*
* Hook the function.
*/
HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, 0);
if(handle == NULL) {
printf("The KEYBOARD could not be hooked.\n");
}
/*
* Unhook the function.
*/
printf("Program successfully hooked.\nPress enter to unhook the function and stop the program.\n");
getchar();
UnhookWindowsHookEx(handle);
return 0;
}
④B运行起来后,如果触发了和钩子对应的消息,则会去运行f,但f在val.dll中,并不在进程空间里,因此B会去加载val.dll。这样,dll就被注入到目标进程中了。
注意:B必须先运行,安装钩子必须在目标进程运行之后,否则钩子会失效。我猜想是安装全局钩子时,会将钩子和当前系统的所有线程关联起来。后面建立的线程当然就不在其列了。
编程的一点经验:
A用LoadLibrary加载val.dll时,两者必须是同一种版本,即同为Debug版或Release版,否则会出现找不到目标文件错误。
LoadLibrary参数里的路径不需要将‘\’转义,而fopen_s却需要将路径里的反斜杠转义。