简介
我们可以在 Dll
中申请一个共享节,当进程加载该 Dll
文件后,不同进程都可以实现对该共享节内存的读写,以此实现进程间的数据共享。其中,共享节的申请方式如下:
#pragma data_seg(".shared")
/* 全局变量, 必须初始化 */
#pragma data_seg()
#pragma comment(linker,"/section:.shared,rws") // 声明该共享节的属性
//也可以使用以下方式定义全局变量, 必须初始化
//__declspec(allocate("Shared"))LPSTR lpszName = "walker";
/* 全局变量、函数的简便导出方法是在 *.def 文件中直接添加函数声明即可, 不必初始化。
在程序调用时, 和函数调用一样, 使用 GetProcAddress 函数得到变量地址。
*/
需要注意的是,一般我们会将 Dll
中的全局变量封装在函数中进行操作,而不会直接导出。
可以看到,此时.shared
段已经具有可读、可写、可执行的权限。
测试代码如下:
Dll代码
#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>
extern HMODULE g_hModuleOfDll;
#pragma data_seg("shared")
HHOOK g_hHook = NULL;
BYTE g_szBuff[100] = {
0};
DWORD g_dwBuffLen = 0;
DWORD g_dwBuffMax = sizeof(g_szBuff);
#pragma data_seg()
#pragma comment(linker,"/section:shared,rws")
BYTE szBuff[100];
// 提权函数:提升为DEBUG权限 (貌似没什么作用)
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
BOOL fOk = FALSE;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOk;
}
BOOL Write(LPSTR lpszBuff, DWORD dwBuffLen)
{
if(g_dwBuffMax < dwBuffLen)
return FALSE;
ZeroMemory(g_szBuff, g_dwBuffMax);
memcpy(g_szBuff, lpszBuff, dwBuffLen);
g_dwBuffLen = dwBuffLen;
return TRUE;
}
DWORD Read(LPSTR lpszBuff, DWORD dwBuffLen)
{
if(dwBuffLen < g_dwBuffLen)
return 0;
ZeroMemory(lpszBuff, dwBuffLen);
memcpy(lpszBuff, g_szBuff, g_dwBuffLen);
return g_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(g_szBuff);
OutputDebugString("------\n");
ZeroMemory(szBuff, sizeof(szBuff));
sprintf(szBuff, "wParam: %d\nlParam: %d\nPID: %d\n", pcw->wParam, pcw->lParam,GetCurrentProcessId());
//MessageBoxA(0, szBuff, "接收到自定义消息", 0);
OutputDebugString(szBuff);
}
}
//return TRUE;
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;
}
测试程序代码
#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 = "mfc";
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;
}