当前位置 博文首页 > KOOKNUT的博客:SetWindowsHookEx实现对目标进程注入Dll
MSDN官方文档给出的定义:
HHOOK SetWindowsHookEx( int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier);
idHook:挂钩类型,即处理的消息类型;我此处测试的是WH_KEYBOARD
lpfn:挂钩函数的地址指针。如果是全局钩子,即dwThreadId为0或者Hook的进程不是当前进程,那么lpfn必须指向DLL中的挂钩函数。除此之外,lpfn可指向当前进程的一段挂钩函数代码。当钩到消息后,执行此函数。为适用性起见,我在代码中用的是从DLL中导出的函数地址。
hMod:应用程序的的实例句柄,指向包含lpfn指针的DLL。
dwThreadId:如果为0,则表示该钩子与所有线程相关联,为全局挂钩。
函数失败,返回NULL,成功返回钩子句柄。
实现思路:
#include"SetWindowsHookEx.h"
#include"Helper.h"
int _tmain(int argc, TCHAR* argv[], TCHAR *envp[])
{
//控制台识别中文
setlocale(LC_ALL, "Chinese-simplified");
TCHAR ProcessImageName[MAX_PATH] = { 0 };//保存进程名字
TCHAR CurrentFullPath[MAX_PATH] = { 0 }; //当前进程的完整路径
TCHAR TargetProcessFullPath[MAX_PATH] = { 0 };//目标进程的完整路径
ULONG_PTR TargetProcessPathLength = MAX_PATH;
ULONG ProcessId = 0;//目标进程Id
vector<HANDLE> ThreadId;//线程ID
HANDLE ProcessHandle = INVALID_HANDLE_VALUE;//进程句柄
HMODULE ModuleBase = NULL;//Dll模块句柄
FARPROC InjectFunction = NULL;//接导出函数的指针
HHOOK HookHandle = NULL;//SetWindowsHookEx返回值
BOOL IsOk = FALSE;
//注入的启动程序和目标程序的位数
BOOL SourceIsWow64 = FALSE;
BOOL TargetIsWow64 = FALSE;
_tprintf(_T("输入一个进程ImageName\r\n"));
TCHAR RcceiveChar = _gettchar();//接受字符串
int i = 0;//用来偏移ProcessName字符数组
while (RcceiveChar != '\n')
{
ProcessImageName[i++] = RcceiveChar;
RcceiveChar = _gettchar();
}
GetCurrentDirectory(MAX_PATH, CurrentFullPath);//保存当前进程的完整路径
IsWow64Process(GetCurrentProcess(), &SourceIsWow64);//得到当前进程位数
ProcessId = KtGetProcessIdentify(ProcessImageName);//通过进程名得到进程Id
if (ProcessId == 0)
{
return 0;
}
IsOk = KtGetProcessFullPath(TargetProcessFullPath,
&TargetProcessPathLength, ProcessId, FALSE);
if (IsOk == FALSE)
{
return 0;
}
//判断目标进程位数
KtIsWow64Process(TargetProcessFullPath, &TargetIsWow64);
if (SourceIsWow64 == TRUE && TargetIsWow64 == TRUE)
{
_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
}
else if (SourceIsWow64 == FALSE && TargetIsWow64 == FALSE)
{
_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
}
//_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));虚拟机测试
//KtGetThreadIdentify我自己封装的内部使用CreateToolhelp32Snapshot系列的函数处理的
if (KtGetThreadIdentify((HANDLE)ProcessId, ThreadId) == FALSE)
{
goto Exit;
}
//加载动态库
ModuleBase = LoadLibrary(CurrentFullPath);
if (ModuleBase == NULL)
{
goto Exit;
}
//获得导出函数指针
InjectFunction = GetProcAddress(ModuleBase, "InjectFunction");
if (InjectFunction == NULL)
{
goto Exit;
}
for (int i = 0; i < ThreadId.size(); ++i)
{
//对其中的某个线程实施注入
HookHandle = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)InjectFunction, ModuleBase, (DWORD)ThreadId[i]);
if (HookHandle != NULL)
{
//只要有一个线程注入成功,就退出
break;
}
}
_tprintf(_T("Input AnyKey To Exit"));
getchar();
Exit:
if (HookHandle != NULL)
{
//卸载钩子
UnhookWindowsHookEx(HookHandle);
HookHandle = NULL;
}
if (!!(ThreadId.size()))
{
vector<HANDLE>().swap(ThreadId);
}
if (ModuleBase != NULL)
{
FreeLibrary(ModuleBase);
ModuleBase = NULL;
}
}
注入成功截图:按键就会产生弹窗效果
64位测试截图:
卸载之后我也进行了键盘按键,不会弹出来了。
不忘初心,方得始终
cs