您的位置:首页 > 其它

DLL注入之WindowsHooks

2016-09-30 11:53 267 查看
本文转载自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 process
HHOOK 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 box
int 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: