进程通信——自定义消息

简介

对于 Windows 程序而言,其工作机制是基于消息基址实现的,而且系统会有一个系统消息队列用于接收所有进程的消息,通过窗口(控件)句柄分发给特定的进程。因此,我们可以通过消息机制,向特定进程发送消息,以实现进程间的通信。

但是,当我们通过句柄向特定进程发送系统定义的消息时, 目标进程中可能存在该消息的处理函数,其处理函数的逻辑必然与我们想要实现的不同,这同样无法达到我们的目的。

因此,我们可以通过自定义消息,这样就可以避免被目标进程按照其原本的逻辑处理。我们可以通过 Windows AIP 函数向目标进程中注入消息处理函数,以实现目标进程接收我们自定义的消息,并按照我们定义的消息处理函数进行消息处理。


通过自定义消息实现进程间的通信,我们就需要将自定义消息对应的消息处理函数注入到目标进程中。该函数就是 SetWindowsHookEx,该函数用于设置全局钩子,其中有一个参数是指定注入目标线程。当 threadID 为0时,表示向操作系统注入全局钩子;但是当该参数是一个特定进程的 threadID 时,就可以实现对该线程的进程空间注入消息处理函数。



DLL代码

#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>

struct SharedMemory
{
    
    
	DWORD dwBuffMax;
	DWORD dwBuffLen;
	LPSTR  lpszBuff;
}*sm;

extern HMODULE g_hModuleOfDll;
HHOOK g_hHook;
BYTE szBuff[100];
HANDLE hMapObject;					
LPVOID lpszSharedBuff;					
	
BOOL CreateSharedMemory()
{
    
    				
	//创建FileMapping对象					
	hMapObject = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x1000,TEXT("shared"));					
	if(!hMapObject)									
		return FALSE;				
	
	//将FileMapping对象映射到自己的进程					
	lpszSharedBuff = MapViewOfFile(hMapObject,FILE_MAP_WRITE,0,0,0);					
	if(!lpszSharedBuff)								
		return FALSE;
	
	sm = lpszSharedBuff;
	sm->dwBuffMax = 0x100;
	sm->lpszBuff = (LPSTR)((DWORD)lpszSharedBuff+12);
	return TRUE;
}

BOOL Write(LPSTR lpszBuff, DWORD dwBuffLen)
{
    
    
	if(sm->dwBuffMax < dwBuffLen)
		return FALSE;

	ZeroMemory(sm->lpszBuff, g_dwBuffMax);
	memcpy(sm->lpszBuff, lpszBuff, dwBuffLen);
	sm->dwBuffLen = dwBuffLen;
	return TRUE;
}

DWORD Read(LPSTR lpszBuff, DWORD dwBuffLen)
{
    
    
	if(dwBuffLen < sm->dwBuffLen)
		return 0;
	ZeroMemory(lpszBuff, dwBuffLen);
	memcpy(lpszBuff, sm->lpszBuff, sm->dwBuffLen);
	return sm->dwBuffLen;
}

DWORD GetWindowThreadID(LPSTR lpszWindowName)
{
    
    
	// 初始化
	HANDLE hProcess;
	HANDLE hThreadSnap = NULL;	// 模块快照
	DWORD th32ThreadID = 0;
	DWORD dwPid = 0x00;
	THREADENTRY32 thread32 = {
    
     0 };
	BOOL bMoreOfThread;

	//获取进程句柄
	HWND hwnd = FindWindow(NULL, lpszWindowName);
	if (!hwnd)
	{
    
    
		//printf("获取进程句柄失败!\n");
		return FALSE;
	}

	
	GetWindowThreadProcessId(hwnd, &dwPid);
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
	
	//获取线程ID
	thread32.dwSize = sizeof(thread32);

	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
	{
    
    
		//printf("获取线程信息失败!\n");
		return FALSE;
	}

	bMoreOfThread = Thread32First(hThreadSnap, &thread32);
	while (bMoreOfThread)
	{
    
    
		if (thread32.th32OwnerProcessID == dwPid)
		{
    
    
			th32ThreadID = thread32.th32ThreadID;
			break;
		}
		bMoreOfThread = Thread32Next(hThreadSnap, &thread32);
	}

	CloseHandle(hThreadSnap);

	return th32ThreadID;
}

// 钩子回调函数
LRESULT MessageProc(
	int nCode,
	WPARAM wParam,
	LPARAM lParam)
{
    
    
	if (nCode == HC_ACTION)
	{
    
    
		PCWPSTRUCT pcw = (PCWPSTRUCT)lParam;
		if (pcw->message == WM_USER + 0x1)
		{
    
    
			OutputDebugString("receive data: ");
			OutputDebugString(sm->lpszBuff);
			OutputDebugString("------\n");
			ZeroMemory(szBuff, sizeof(szBuff));
			sprintf(szBuff, "wParam: %d\nlParam: %d\nPID: %d\n", pcw->wParam, pcw->lParam,GetCurrentProcessId());
			OutputDebugString(szBuff);
		}
	}
	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}


// 设置全局钩子
BOOL SetGlobalHook(int idHook, LPSTR lpszWindowName)
{
    
    
	DWORD threadID = GetWindowThreadID(lpszWindowName);
	if(!threadID)
	{
    
    
		MessageBox(NULL, "获取目标进程PID失败!", "note", MB_OK);
		return FALSE;
	}

	g_hHook = SetWindowsHookEx(idHook, (HOOKPROC)MessageProc, g_hModuleOfDll, threadID);
	if (NULL == g_hHook)
	{
    
    
		return FALSE;
	}
	return TRUE;
}


// 卸载钩子
BOOL UnsetGlobalHook()
{
    
    
	if (g_hHook)
	{
    
    
		UnhookWindowsHookEx(g_hHook);
		return TRUE;
	}
	else
		return FALSE;
}

## 测试程序![在这里插入图片描述](https://img-blog.csdnimg.cn/20210301103619278.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg5MDk1OQ==,size_16,color_FFFFFF,t_70#pic_center)
#include <Windows.h>
#include <stdio.h>

int main(int argc, CHAR* argv[])
{
    
    
	typedef BOOL(*typedef_SetGlobalHook)(int idHook, LPSTR lpszWindowName);
	typedef BOOL(*typedef_UnsetGlobalHook)();
	typedef BOOL(*typedef_Write)(LPSTR lpszBuff, DWORD dwBuffLen);
	typedef DWORD(*typedef_Read)(LPSTR lpszBuff, DWORD dwBuffLen);
	typedef BOOL(*typedef_CreateSharedMemory)();
	HMODULE hDll = NULL;
	typedef_SetGlobalHook SetGlobalHook = NULL;
	typedef_UnsetGlobalHook UnsetGlobalHook = NULL;
	typedef_CreateSharedMemory CreateSharedMemory;
	typedef_Write Write;
	typedef_Read Read;
	DWORD dwBuffLen;
	BYTE szBuff[100] = {
    
    0};
	BOOL bRet = FALSE;
	LPSTR lpszWindowName = "Win32App";

	do
	{
    
    
		hDll = ::LoadLibrary("C:\\vc6++\\MyProjects\\GlobalHook\\Debug\\GlobalHook.dll");
		if (NULL == hDll)
		{
    
    
			printf("LoadLibrary Error[%d]\n", ::GetLastError());
			break;
		}
		SetGlobalHook = (typedef_SetGlobalHook)::GetProcAddress(hDll, "SetGlobalHook");
		if (NULL == SetGlobalHook)
		{
    
    
			printf("GetProcAddress Error[%d]\n", ::GetLastError());
			break;
		}
		bRet = SetGlobalHook(WH_CALLWNDPROC, lpszWindowName);
		if (bRet)
		{
    
    
			printf("SetGlobalHook OK.\n");
		}
		else
		{
    
    
			printf("SetGlobalHook ERROR.\n");
		}
	
		//write buff
		Write = (typedef_Write)GetProcAddress(hDll, "Write");
		if (NULL == Write)
		{
    
    
			printf("GetProcAddress Error[%d]\n", GetLastError());
			break;
		}
		
		bRet = Write("haha,walker!", 0x20);
		if (bRet)
		{
    
    
			printf("write success.\n");
		}
		else
		{
    
    
			printf("write error.\n");
		}
/*
		// read buff
		Read = (typedef_Read)GetProcAddress(hDll, "Read");
		if (NULL == Read)
		{
			printf("GetProcAddress Error[%d]\n", GetLastError());
			break;
		}
		
		dwBuffLen = sizeof(szBuff);
		dwBuffLen = Read((LPSTR)szBuff, dwBuffLen);
		if (dwBuffLen)
		{
			printf("Read data: %s\n", szBuff);
		}
		else
		{
			printf("Read error.\n");
		}
*/
		//获取进程句柄
		HWND hwnd = FindWindow(NULL, lpszWindowName);
		if (!hwnd)
		{
    
    
			//printf("获取进程句柄失败!\n");
			return FALSE;
		}
		SendMessage(hwnd, WM_USER + 0x1, 0x1234, 0x5678);

		UnsetGlobalHook = (typedef_UnsetGlobalHook)::GetProcAddress(hDll, "UnsetGlobalHook");
		if (NULL == UnsetGlobalHook)
		{
    
    
			printf("GetProcAddress Error[%d]\n", ::GetLastError());
			break;
		}
		bRet = UnsetGlobalHook();
		if(bRet)
			printf("UnsetGlobalHook OK.\n");
		else
			printf("UnsetGlobalHook falied.\n");
		SendMessage(hwnd, WM_USER + 0x1, 0x1234, 0x5678);
	}while(FALSE);
	FreeLibrary(hDll);
	return 0;
}

测试图如下:
在这里插入图片描述

存在的问题

DLL 中无法使用 MessageBox ,否则会引发被注入的进程崩溃。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43890959/article/details/114255481