当前位置 博文首页 > KOOKNUT的博客:SetWindowsHookEx实现对目标进程注入Dll

    KOOKNUT的博客:SetWindowsHookEx实现对目标进程注入Dll

    作者:[db:作者] 时间:2021-07-02 18:37

    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,成功返回钩子句柄。
    实现思路:

    • 从控制台得到想要实施注入的目标进程名字
    • 得到当前进程所在的目录(GetCurrentDirectory),并保存
    • 得到当前进程的位数 (IsWow64Process)
    • 根据进程名字得到当前进程的Id
    • 根据进程Id得到当前进程的完整路径
    • 通过进程完整路径对PE文件解析得到目标进程位数
    • 目标与当前进程的位数进行匹配,决定加载哪一个dll(x86 or x64)
    • 根据当前进程目录,得到dll完整路径
    • 通过目标进程Id返回目标进程中所有线程的Id
    • 通过LoadLibrary加载目标动态库,得动态库模块句柄
    • GetProcAddress得到导出函数的函数指针
    • SetWindowsHookEx实施对某个线程的注入
    • 收尾工作,卸载钩子
    #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
    下一篇:没有了