挂钩原理
Windows下的应用程序大部分都是基于消息机制的,它们都会有一个消息过程函数,根据不同的消息完成不同的功能。
Windows操作系统提供的钩子机制的作用就是用来截获和监视这些系统中的消息。Windows钩子琳琅满目,可以用来应对各种不同的消息。
按照钩子作用的范围不同,又可以分为局部钩子和全局钩子。局部钩子是针对某个线程的;
而全局钩子则是作用于整个系统中基于消息的应用。全局钩子需要使用DLL文件,在DLL中实现相应的钩子函数。
在操作系统中安装全局钩子后,只要进程接收到可以发出钩子的消息,全局钩子的DLL文件就会被操作系统自动或强行地加载到该进程中。
因此,设置消息钩子,也可以达到DLL注入的目的。
注入过程
- 根据进程名获取进程id
- 打开目标进程
- 根据进程id获得目标线程id
- 获取DLL基址
- 获得注入DLL中的函数地址(即触发消息后执行哪个函数)
- SetWindowHook 设置钩子
- UnhookWindowsHookEx 卸载钩子
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include<iostream>
using namespace std;
BOOL GetProcessIDByProcessImageName(WCHAR* ProcessImageName, ULONG32* TargetProcessID);
BOOL InjectDllBySetWindowsHook(ULONG32 TargetProcessID);
DWORD GetThreadID(ULONG32 TargetProcessID);
int main()
{
ULONG32 TargetProcessID = 0;
if (GetProcessIDByProcessImageName(L"sublime_text.exe", &TargetProcessID) == FALSE)
{
return 0;
}
if (InjectDllBySetWindowsHook(TargetProcessID) == FALSE)
{
return 0;
}
return 0;
}
BOOL GetProcessIDByProcessImageName(WCHAR* ProcessImageName, ULONG32* TargetProcessID)
{
ULONG32 i = 0;
BOOL IsOk = FALSE;
HANDLE ToolHelpHandle = NULL;
PROCESSENTRY32 ProcessEntry32 = { 0 };
ProcessEntry32.dwSize = sizeof(PROCESSENTRY32);
ToolHelpHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (ToolHelpHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
IsOk = Process32First(ToolHelpHandle, &ProcessEntry32);
do
{
if (IsOk)
{
if (wcsicmp(ProcessEntry32.szExeFile, ProcessImageName) == 0)
{
*TargetProcessID = ProcessEntry32.th32ProcessID;
CloseHandle(ToolHelpHandle);
ToolHelpHandle = INVALID_HANDLE_VALUE;
return TRUE;
}
}
else
{
break;
}
IsOk = Process32Next(ToolHelpHandle, &ProcessEntry32);
} while (1);
CloseHandle(ToolHelpHandle);
ToolHelpHandle = INVALID_HANDLE_VALUE;
return FALSE;
}
DWORD GetThreadID(ULONG32 TargetProcessID)
{
HANDLE Handle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (Handle != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(Handle, &te))
{
do
{
//线程是否可用
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
{
if (te.th32OwnerProcessID == TargetProcessID)
{
HANDLE hThread = OpenThread(READ_CONTROL, FALSE, te.th32ThreadID);
if (!hThread)
{
puts("Can't get thread handle");
}
else
{
return te.th32ThreadID;
}
}
}
} while (Thread32Next(Handle, &te));
}
}
CloseHandle(Handle);
return (DWORD)0;
}
BOOL InjectDllBySetWindowsHook(ULONG32 TargetProcessID)
{
HANDLE TargetProcessHandle = NULL;
TargetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, TargetProcessID);
if (NULL == TargetProcessHandle)
{
return FALSE;
}
HMODULE DllModule;
#ifdef _WIN64
DllModule = LoadLibrary(L"E:\\WindowsDll64.dll");
#else
DllModule = LoadLibrary(L"E:\\WindowsDll.dll");
#endif
if (DllModule == NULL)
{
printf("Can Not Find Dll");
return FALSE;
}
HOOKPROC Sub_1Address = NULL;
Sub_1Address = (HOOKPROC)GetProcAddress(DllModule, "Sub_1");
if (Sub_1Address == NULL)
{
printf("Sub_1 do not Exist!");
return FALSE;
}
DWORD ThreadID = GetThreadID(TargetProcessID);
HHOOK Handle = SetWindowsHookEx(WH_KEYBOARD,Sub_1Address, DllModule, ThreadID);
if (Handle == NULL)
{
printf("Hook Failed!");
return FALSE;
}
printf("Hook Success");
getchar();
UnhookWindowsHookEx(Handle);
FreeLibrary(DllModule);
return true;
}