• 注入(4)--消息钩子注入(SetWindowsHookEX)


    SetWindowsHookEx函数是微软提供给程序开发人员进行消息拦截的一个API。不过,他的功能不仅可以用作消息拦截,还可以进行DLL注入。
    SetWindowsHookEx原型声明如下:

    WINUSERAPI
    HHOOK
    WINAPI
    SetWindowsHookExW(
        _In_ int idHook,
        _In_ HOOKPROC lpfn,
        _In_opt_ HINSTANCE hmod,
        _In_ DWORD dwThreadId);


    idHook:指示将要安装的挂钩处理过程的类型。例如,idHook为“WH_CALLWNDPROC”时代表安装一个挂钩处理过程,在系统将消息发送至目标窗口处理过程之前对该消息进行监视。
    lpfn:指向相应的挂钩处理过程。
    hmod:指示了一个DLL句柄。该DLL包含参数lpfn所指向的挂钩处理过程
    dwThreadId:指示了一个线程标示符,挂钩处理过程与线程相关。若此参数值为0,则该挂钩处理过程与所有现存的线程相关。
    如果去掉消息钩子,可以用UnhookWindowsHookEx函数

    Windows消息处理流程:


    插入SetWindowsHookEx之后流程:


    下面来看代码:

    // MessageHook.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <Tlhelp32.h>
    
    BOOL SetWinHookInject(WCHAR * wzDllPath, WCHAR * wzProcessName);
    UINT32 GetTargetThreadIdFromProcessName(WCHAR *ProcessName);
    int main()
    {
    	WCHAR wzProcessName[0x20] = L"Target.exe";
    	WCHAR wzDllFullPath[0x20] = L"MessageHookDll.dll";
    	
    	if (!SetWinHookInject(wzDllFullPath, wzProcessName))
    	{
    		OutputDebugString(L"Set Hook Unsuccess!
    ");
    		return 0;
    	}
    	OutputDebugString(L"Inject Success!
    ");
        return 0;
    }
    
    //
    //利用Windows API SetWindowsHookEx实现注入DLL
    //
    BOOL SetWinHookInject(WCHAR * wzDllPath, WCHAR * wzProcessName)
    {
    	HMODULE ModuleHandle = NULL;
    	BOOL    bOk = FALSE;
    	DWORD   FunctionAddress = NULL;
    	UINT32  dwThreadId = 0;
    	HHOOK   g_hHook = NULL;
    	PVOID   pShareM = NULL;
    
    	OutputDebugString(L"[+] SetWinHKInject Enter!
    ");
    
    
    	ModuleHandle = LoadLibrary(wzDllPath);
    	if (!ModuleHandle)
    	{
    		OutputDebugString(L"[+] LoadLibrary error!
    ");
    		goto Exit;
    	}
    
    
    	FunctionAddress = (DWORD)GetProcAddress(ModuleHandle, "MyMessageProc");
    	if (!FunctionAddress)
    	{
    		OutputDebugString(L"[+] GetProcAddress error!
    ");
    		goto Exit;
    	}
    
    
    	dwThreadId = GetTargetThreadIdFromProcessName(wzProcessName);
    	if (!dwThreadId)
    		goto Exit;
    
    	//设消息钩子
    	g_hHook = SetWindowsHookEx(
    		WH_GETMESSAGE,//WH_KEYBOARD,//WH_CALLWNDPROC,
    		(HOOKPROC)FunctionAddress,
    		ModuleHandle,
    		dwThreadId
    	);
    
    	if (!g_hHook)
    	{
    		OutputDebugString(L"[-] SetWindowsHookEx error !
    ");
    		goto Exit;
    	}
    
    	OutputDebugString(L"[!] SetWinHKInject Exit!
    ");
    	bOk = TRUE;
    Exit:
    	if (ModuleHandle)
    		FreeLibrary(ModuleHandle);
    	return bOk;
    
    }
    
    //通过进程名获得线程ID
    UINT32 GetTargetThreadIdFromProcessName(WCHAR *ProcessName)
    {
    	PROCESSENTRY32 pe;
    	HANDLE SnapshotHandle = NULL;
    	HANDLE ProcessHandle = NULL;
    	BOOL Return, ProcessFound = FALSE;
    	UINT32 pTID, ThreadID;
    
    	SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    	if (SnapshotHandle == INVALID_HANDLE_VALUE)
    	{
    		MessageBox(NULL, L"Error: unable to create toolhelp snapshot", L"Loader", NULL);
    		return FALSE;
    	}
    
    	pe.dwSize = sizeof(PROCESSENTRY32);
    
    	Return = Process32First(SnapshotHandle, &pe);
    
    	while (Return)
    	{
    		if (_wcsicmp(pe.szExeFile, ProcessName) == 0)
    		{
    			ProcessFound = TRUE;
    			break;
    		}
    
    		Return = Process32Next(SnapshotHandle, &pe);
    		pe.dwSize = sizeof(PROCESSENTRY32);
    
    	}
    
    	CloseHandle(SnapshotHandle);
    	//通过fs寄存器获取TID
    	_asm 
    	{
    		mov eax, fs:[0x18]
    		add eax, 36
    		mov[pTID], eax
    	}
    
    	ProcessHandle = OpenProcess(PROCESS_VM_READ, FALSE, pe.th32ProcessID);
    	ReadProcessMemory(ProcessHandle,(LPCVOID)pTID, &ThreadID, 4, NULL);
    	CloseHandle(ProcessHandle);
    
    	return ThreadID;
    }
    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "stdafx.h"
    #include <Windows.h>
    
    #pragma data_seg(SHARD_SEG_NAME)
    static HHOOK g_hHook;
    #pragma data_seg()
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	{
    		//
    		//加入你想在目标进程空间HOOK的代码
    		//
    		MessageBox(NULL, L"Inject Success!", L"Message", 0);
    	}
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
    
    __declspec(dllexport)LRESULT MyMessageProcess(int Code, WPARAM wParam, LPARAM lParam)
    {
    	//
    	//你自己对消息的处理
    	//
    	return CallNextHookEx(g_hHook, Code, wParam, lParam);
    }
  • 相关阅读:
    设置datagrid的背影及对单元格进行设置
    利用结果集更新记录
    安装sql2000提示"以前的某个程序安装已在安装计算机上创建挂起的文件操作"解决办法
    xls.exe
    动态增加datagrid的行数
    Emergency Preparedness Resource Inventory(紧急预备资源列表系统)
    DataList中选择列的实现与数据的取得:
    Android中发送Http请求实例(包括文件上传、servlet接收)
    android文件上传到服务器
    C++获取程序执行时间
  • 原文地址:https://www.cnblogs.com/Toring/p/6628282.html
Copyright © 2020-2023  润新知