DLL注入之WindowsHooks

来源:互联网 发布:noppoo choc mac 编辑:程序博客网 时间:2024/05/04 06:32

本文转载自DLL注入的几种姿势(一):Windows Hooks
DLL注入可以通过SetWindowsHookEx创建钩子来实现。首先我们需要理解Windows的hook机制和API函数SetWindowsHookEx。Hook机制允许应用程序截获处理窗口消息或特定事件,而钩子又可以分为多种,例如WH_KEYBOARD和WH_MOUSE这两种钩子可以分别用来监视键盘和鼠标的消息。要想理解Hook机制,必须要清楚的是每一个Hook事件的发生都有一个与之相关联的指针列表,称之为Hook链表。这个链表存在一系列的子进程,并且伴随着事件而执行。

idHook是Hook的类型,lpfn是Hook子程的地址指针,hMod是应用程序实例的句柄,最后dwThreadId标识当前进程创建的线程。首先通过LoadLibrary函数加载DLL文件至exe文件的地址空间中,然后通过GetProcessAddress获得所需函数的地址,最后调用SetWindowsHookEx等待我们设置好的事件发生。一旦事件发生,Windows将会加载DLL至目标进程的地址空间中。下面的程序执行DLL注入,被注入的DLL路径是D:\\DLLTest.dll,调用的其中的函数是test1。
#include <windows.h>#include <stdio.h>#include <tchar.h>#include <psapi.h>#include <tlhelp32.h>/*This method is used to get a thread id for a process.It loops through all of the threads and compares their pid with the desired pid*/DWORD getThreadID(DWORD pid){puts("Getting Thread ID");HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);if (h != INVALID_HANDLE_VALUE){THREADENTRY32 te;te.dwSize = sizeof(te);if (Thread32First(h, &te)){do{if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)){if (te.th32OwnerProcessID == pid){HANDLE hThread = OpenThread(READ_CONTROL, FALSE, te.th32ThreadID);if (!hThread){puts("Couldn't get thread handle");}else{return te.th32ThreadID;}}}} while (Thread32Next(h, &te));}}CloseHandle(h);return (DWORD)0;}/*This method performs the actual injection. It gets an appropriate thread id, loads the dll,gets the address of the inject method, then calls SetWindowsHookEx.*/int processInject(int pid){DWORD processID = (DWORD)pid;TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);if (NULL != hProcess){HMODULE hMod;DWORD cbNeeded;if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)){GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));}}_tprintf(TEXT("Injecting into process %s PID: %u\n"), szProcessName, processID);DWORD threadID = getThreadID(processID);printf("Using Thread ID %u\n", threadID);if (threadID == (DWORD)0){puts("Cannot find thread");return -1;}HMODULE dll = LoadLibrary("D:\\DLLTest.dll");if (dll == NULL){puts("Cannot find DLL");return -1;}HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "test1");if (addr == NULL){puts("Cannot find the function");return -1;}//Uses the threadID from getThreadID to inject into specific processHHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, threadID);if (handle == NULL){puts("Couldn't hook the keyboard");}getchar();getchar();getchar();UnhookWindowsHookEx(handle);return 0;}int main(int argc, char* argv){int pid;puts("Inject into which PID?");scanf_s("%u", &pid);printf("PID entered: %u\n", pid);int result = processInject(pid);if (result == -1){puts("Could not inject");}else{puts("Injected!");}getchar();system("pause");}

按照在VS2015中用C++编写可被其它语言调用的动态库DLL中的方法在VS2015中创建我们所需的DLL。

#include<stdio.h>#include<windows.h>int  test1(){char str[80];//Get's the current process id to display in the message boxint id = GetCurrentProcessId();sprintf_s(str, "Hello, process: %d", id);MessageBox(NULL, str, "Hello DLL!", MB_OK);return 0;}

任务管理器中看到WORD的PID是9076。


输入9076可以看到WORD的进程号是2608。


这时在WORD中按下键盘就会弹出DLL中编写的对话框。


打开Process Explorer可以看到DLL同时加载到WORD和Project中。


DLL、EXE和源代码在github:dll-injection-by-WindowsHooks

0 0