本程序HOOK的API是DispatchMessageA和DispatchMessageW。在HOOK的方法内会还原ESP,调用user32.DispathMessage(A或W)之后再修改ESP,实现的功能是记录消息的详细日志,记录哪个窗口处理过哪些消息。
	
	1、新建一个win32 console项目,取名为DoInjection,新建一个DoInjectionMain.h,代码如下:
	BOOL SetPrivilege(LPCTSTR lPSzPrivilege, BOOL bEnablePrivilege);
	BOOL IsVistaOrLater();
	BOOL InjectProcess();
	BOOL InjectCreateProcess();
	void HookGetMessage();
	BOOL InjectCreateThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf);
	HANDLE MsicCreateRemoteThread(HANDLE hProcess,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter);
	
	typedef void*(__stdcall*LPFN_KernelBaseGetGlobalData)(void);
	typedef DWORD (WINAPI *PFNTCREATETHREADEX)
	(
	PHANDLE ThreadHandle,
	ACCESS_MASK DesiredAccess,
	LPVOID ObjectAttributes,
	HANDLE ProcessHandle,
	LPTHREAD_START_ROUTINE lpStartAddress,
	LPVOID lpParameter,
	BOOL CreateSuspended,
	DWORD dwStackSize,
	DWORD dw1,
	DWORD dw2,
	LPVOID Unknown
	); 
	2、新建一个DoInjectionMain.c(不是CPP),代码如下:
	#include <windows.h>
	#include <stdio.h>
	#include <tlhelp32.h>
	#include <tchar.h>
	#include "DoInjection.h"
	
	#pragma comment(lib,"th32.lib")
	#pragma comment(lib,"Advapi32.lib")
	
	//这个路径很有意思,这个路径是相对于目标进程的,而不是自身进程。
	//所以要嘛写成绝对路径,要嘛写成相对于目标进程的相对路径。
	//如果写成相对于自身的路径就要麻烦了,本程序就找不到dll文件了。
	const char *pcDllName="MfcHookApi.dll"; //DLL文件的路径
	HANDLE hSnap=0,hThreadHandle=0,hRemoteProcess32=0,hTokenHandle=0;
	PROCESSENTRY32 procEntry32;
	BOOL bNext=FALSE,bWrittenResult=FALSE;
	TOKEN_PRIVILEGES tokenPower;
	LUID luidPower;
	LPVOID pRemoteBuf=NULL;
	FARPROC fnDllKernel32;
	size_t sizeWritten=0;
	DWORD dwThreadId=0;
	
	char* pcProsessName="DoWin32test.exe"; //要注入的进程名(目标进程名)
	
	int main()
	{
	IsVistaOrLater();
	SetPrivilege(SE_DEBUG_NAME,TRUE);
	//InjectProcess();
	InjectCreateProcess();
	getchar();
	return 0;
	}
	
	BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
	{
	TOKEN_PRIVILEGES tp;
	HANDLE hToken;
	LUID luid;
	if( !OpenProcessToken(GetCurrentProcess(),
	TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
	&hToken) )
	{
	_tprintf("OpenProcessToken error: %u
", GetLastError());
	return FALSE;
	}
	if( !LookupPrivilegeValue(NULL,
	lpszPrivilege,
	&luid) )
	{
	_tprintf("LookupPrivilegeValue error: %u
", GetLastError() );
	return FALSE;
	}
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if( bEnablePrivilege )
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	else
	tp.Privileges[0].Attributes = 0;
	if( !AdjustTokenPrivileges(hToken,
	FALSE,
	&tp,
	sizeof(TOKEN_PRIVILEGES),
	(PTOKEN_PRIVILEGES) NULL,
	(PDWORD) NULL) )
	{
	_tprintf("AdjustTokenPrivileges error: %u
", GetLastError() );
	return FALSE;
	}
	if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
	{
	_tprintf("The token does not have the specified privilege. 
");
	return FALSE;
	}
	return TRUE;
	}
	
	BOOL IsVistaOrLater()
	{
	
	OSVERSIONINFO osvi;
	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	//OSVERSIONINFOEX osvix;
	//ZeroMemory(&osvix,sizeof(OSVERSIONINFOEX));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osvi);
	printf("network terminal v%ld.%ld,%s,platform:%ld,build number:%ld
",osvi.dwMajorVersion,osvi.dwMinorVersion,osvi.szCSDVersion,osvi.dwPlatformId,osvi.dwBuildNumber);
	if( osvi.dwMajorVersion >= 6 )
	return TRUE;
	return FALSE;
	}
	
	BOOL InjectProcess()
	{
	procEntry32.dwSize = sizeof(PROCESSENTRY32);
	hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	bNext=Process32First(hSnap, &procEntry32);
	while(bNext)
	{
	if(!stricmp(procEntry32.szExeFile,pcProsessName)) //--->>
	{
	hRemoteProcess32=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,1,procEntry32.th32ProcessID);
	break;
	}
	bNext=Process32Next(hSnap, &procEntry32);
	}
	CloseHandle(hSnap);
	pRemoteBuf=VirtualAllocEx(hRemoteProcess32,NULL,strlen(pcDllName),MEM_COMMIT,PAGE_READWRITE);
	bWrittenResult=WriteProcessMemory(hRemoteProcess32,pRemoteBuf,pcDllName,strlen(pcDllName),(ULONG*)&sizeWritten);
	if (bWrittenResult)
	{
	printf("InjectCreate()-->WriteProcessMemory() Success,written size:%ld,buffer address:%16X
",sizeWritten,pRemoteBuf);
	}
	else
	{
	printf("InjectCreate()-->WriteProcessMemory() Error:%ld
",GetLastError());
	}
	fnDllKernel32=GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");
	
	//hThreadHandle=CreateRemoteThread(hRemoteProcess32,NULL,0,(LPTHREAD_START_ROUTINE)fnDllKernel32,pAllocMemory,0,&dwThreadId);
	//if (hThreadHandle&&dwThreadId)
	//{
	// printf("CreateRemoteThread Success,Handle:%ld,Thread Id:%ld
",hThreadHandle,dwThreadId);
	//}
	//else
	//{
	// printf("CreateRemoteThread Error:%ld
",GetLastError());
	//}
	InjectCreateThread(hRemoteProcess32, (LPTHREAD_START_ROUTINE)fnDllKernel32, pRemoteBuf);
	//MsicCreateRemoteThread(hRemoteProcess32,(LPTHREAD_START_ROUTINE)fnDllKernel32,pRemoteBuf);
	VirtualFreeEx(hRemoteProcess32, pRemoteBuf, 0, MEM_RELEASE);;
	CloseHandle(hRemoteProcess32);
	return TRUE;
	}
	
	BOOL InjectCreateProcess()
	{
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	procEntry32.dwSize = sizeof(PROCESSENTRY32);
	ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
	ZeroMemory(&si,sizeof(STARTUPINFO));
	si.cb=sizeof(STARTUPINFO);
	
	CreateProcess(NULL,pcProsessName,NULL,NULL,false,0,NULL,NULL,&si,&pi);
	hRemoteProcess32=pi.hProcess;
	printf("waiting for 30 seconds please.
");
	for (int i=0;i<30;i++)
	{
	Sleep(1000);
	printf(".");
	}
	printf("
");
	pRemoteBuf=VirtualAllocEx(hRemoteProcess32,NULL,strlen(pcDllName),MEM_COMMIT,PAGE_READWRITE);
	bWrittenResult=WriteProcessMemory(hRemoteProcess32,pRemoteBuf,pcDllName,strlen(pcDllName),(ULONG*)&sizeWritten);
	if (bWrittenResult)
	{
	printf("InjectCreate()-->WriteProcessMemory() Success,written size:%ld,buffer address:%16X
",sizeWritten,pRemoteBuf);
	}
	else
	{
	printf("InjectCreate()-->WriteProcessMemory() Error:%ld
",GetLastError());
	}
	fnDllKernel32=GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");
	
	//hThreadHandle=CreateRemoteThread(hRemoteProcess32,NULL,0,(LPTHREAD_START_ROUTINE)fnDllKernel32,pAllocMemory,0,&dwThreadId);
	//if (hThreadHandle&&dwThreadId)
	//{
	// printf("CreateRemoteThread Success,Handle:%ld,Thread Id:%ld
",hThreadHandle,dwThreadId);
	//}
	//else
	//{
	// printf("CreateRemoteThread Error:%ld
",GetLastError());
	//}
	//InjectCreateThread(hRemoteProcess32, (LPTHREAD_START_ROUTINE)fnDllKernel32, pRemoteBuf);
	MsicCreateRemoteThread(hRemoteProcess32,(LPTHREAD_START_ROUTINE)fnDllKernel32,pRemoteBuf);
	//VirtualFreeEx(hRemoteProcess32, pRemoteBuf, 0, MEM_RELEASE);;
	//CloseHandle(hRemoteProcess32);
	return TRUE;
	}
	
	BOOL InjectCreateThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
	{
	HANDLE hThread = NULL;
	FARPROC pFunc = NULL;
	if( IsVistaOrLater() ) // Vista, 7, Server2008
	{
	pFunc = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCreateThreadEx");
	if( pFunc == NULL )
	{
	printf("InjectCreateThread()-->GetProcAddress("NtCreateThreadEx") Error %d
",GetLastError());
	return FALSE;
	}
	((PFNTCREATETHREADEX)pFunc)(&hThread,
	0x1FFFFF,
	NULL,
	hProcess,
	pThreadProc,
	pRemoteBuf,
	FALSE,
	NULL,
	NULL,
	NULL,
	NULL);
	if( hThread == NULL )
	{
	printf("InjectCreateThread()-->NtCreateThreadEx() Error: %d
", GetLastError());
	return FALSE;
	}
	else
	{
	printf("InjectCreateThread()-->NtCreateThreadEx() Success,Thread Id:%ld
",hThread);
	}
	}
	else // 2000, XP, Server2003
	{
	hThread = CreateRemoteThread(hProcess,
	NULL,
	0,
	pThreadProc,
	pRemoteBuf,
	0,
	NULL);
	if( hThread == NULL )
	{
	printf("InjectCreateThread()-->CreateRemoteThread() Error: %d
", GetLastError());
	return FALSE;
	}
	else
	{
	printf("InjectCreateThread()-->CreateRemoteThread() Success,Thread Id:%ld
",hThread);
	}
	}
	if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
	{
	printf("InjectCreateThread() : WaitForSingleObject() Error: %d
", GetLastError());
	return FALSE;
	}
	return TRUE;
	}
	
	typedef void*(__stdcall*LPFN_KernelBaseGetGlobalData)(void);
	HANDLE MsicCreateRemoteThread(HANDLE hProcess,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter)
	{
	OSVERSIONINFOEX stOSVersionInfoEx= {0};
	FARPROC pCreateRemoteThreadEx=NULL;
	LPFN_KernelBaseGetGlobalData pKernelBaseGetGlobalData=NULL;
	UCHAR *pCreateRemoteThread=NULL;
	UCHAR *pGlobalData=NULL;
	UCHAR *pMisc=NULL;
	HMODULE hKernelBase=NULL;
	HMODULE hKernel32=NULL;
	HANDLE hNewThread=NULL;
	ULONG ulIndex=0;
	WORD wCode=0;
	do
	{
	stOSVersionInfoEx.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX);
	if(!GetVersionEx((OSVERSIONINFO*)&stOSVersionInfoEx))
	{
	break;
	}
	//vista以前的系统不存在这个问题
	if((stOSVersionInfoEx.dwMajorVersion<6)||(GetCurrentProcess()==hProcess))
	{
	hNewThread=CreateRemoteThread(hProcess,NULL,0,lpStartAddress,lpParameter,0,&dwThreadId);
	if (dwThreadId)
	{
	printf("MsicCreateRemoteThread()-->CreateRemoteThread() Success,Thread Id:%08X
",dwThreadId);
	}
	else
	{
	printf("MsicCreateRemoteThread()-->CreateRemoteThread() Error:%ld
",GetLastError());
	}
	
	break;
	}
	if((stOSVersionInfoEx.dwMajorVersion==6)&&(0==stOSVersionInfoEx.dwMinorVersion))
	{
	//vista
	hKernel32=LoadLibraryA("Kernel32.dll");
	pCreateRemoteThread=(UCHAR*)GetProcAddress(hKernel32,"CreateRemoteThread");
	for(ulIndex=0; ulIndex<0x300; ulIndex+=1)
	{
	wCode=*((USHORT*)(pCreateRemoteThread+ulIndex));
	#ifdef _WIN64
	if(0x3D80==wCode)
	{
	pMisc=(*((ULONG*)(pCreateRemoteThread+ulIndex+2)))+(pCreateRemoteThread+ulIndex+7);
	break;
	}
	#else
	if(0x1D38==wCode)
	{
	pMisc=(UCHAR*)(*((ULONG*)(pCreateRemoteThread+ulIndex+2)));
	break;
	}
	#endif
	}
	}
	else if((stOSVersionInfoEx.dwMajorVersion==6)&&(1==stOSVersionInfoEx.dwMinorVersion))
	{
	//win7
	hKernelBase=LoadLibraryW(L"KernelBase.dll");
	if(NULL==hKernelBase)
	{
	break;
	}
	pKernelBaseGetGlobalData=(LPFN_KernelBaseGetGlobalData)GetProcAddress(hKernelBase,"KernelBaseGetGlobalData");
	printf("MsicCreateRemoteThread()-->KernelBaseGetGlobalData:%08X
",pKernelBaseGetGlobalData);
	if(NULL==pKernelBaseGetGlobalData)
	{
	break;
	}
	pGlobalData=(UCHAR*)pKernelBaseGetGlobalData();
	if(NULL==pGlobalData)
	{
	break;
	}
	#ifdef _WIN64
	pMisc=pGlobalData+0x5C;
	#else
	pMisc=pGlobalData+0x30;
	#endif
	}
	else
	{
	//手上的win8 Build 8250 没有session 隔离
	}
	//////////////////////////////////////////////////////////////////////////
	if(NULL==pMisc)
	{
	break;
	}
	printf("MsicCreateRemoteThread()-->pMisc: %08X
",pMisc);
	//Patch
	*pMisc=1;
	//xx
	hNewThread=CreateRemoteThread(hProcess,NULL,0,lpStartAddress,lpParameter,0,&dwThreadId);
	if (dwThreadId)
	{
	printf("MsicCreateRemoteThread()-->CreateRemoteThread() Success,Thread Id:%08X
",dwThreadId);
	}
	else
	{
	printf("MsicCreateRemoteThread()-->CreateRemoteThread() Error:%ld
",GetLastError());
	}
	//UnPatch
	*pMisc=0;
	}
	while(FALSE);
	if(NULL!=hKernelBase)
	{
	printf("MsicCreateRemoteThread()-->hKernelBase:%08X
",hKernelBase);
	FreeLibrary(hKernelBase);
	hKernelBase=NULL;
	}
	return hNewThread;
	}
	
	void HookGetMessage()
	{
	HOOKPROC hp;
	//SetWindowsHookEx(WH_GETMESSAGE,hp,)
	}
	3、新建一个mfc的DLL项目,命名为 MfcHookApi.dll,MfcHookApi.h的代码如下:
	
	// MfcHookApi.h : main header file for the MFCHOOKAPI DLL
	//
	
	#if !defined(AFX_MFCHOOKAPI_H__6A8FC5E5_0E77_4B74_8344_CB9CA22141E5__INCLUDED_)
	#define AFX_MFCHOOKAPI_H__6A8FC5E5_0E77_4B74_8344_CB9CA22141E5__INCLUDED_
	
	#if _MSC_VER > 1000
	#pragma once
	#endif // _MSC_VER > 1000
	
	#ifndef __AFXWIN_H__
	#error include 'stdafx.h' before including this file for PCH
	#endif
	
	#include "resource.h" // main symbols
	
	/////////////////////////////////////////////////////////////////////////////
	// CMfcHookApiApp
	// See MfcHookApi.cpp for the implementation of this class
	//
	
	class CMfcHookApiApp : public CWinApp
	{
	public:
	CMfcHookApiApp();
	
	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMfcHookApiApp)
	public:
	virtual BOOL InitInstance();
	//}}AFX_VIRTUAL
	
	//{{AFX_MSG(CMfcHookApiApp)
	// NOTE - the ClassWizard will add and remove member functions here.
	// DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
	};
	
	extern "C" __declspec(dllexport) void ActiveHook();
	extern "C" __declspec(dllexport) void InstallHook4Api(HWND hwnd);
	
	int* addrMsgBoxA=(int*)MessageBoxA;
	int* addrMsgBoxW=(int*)MessageBoxW;
	int WINAPI HookMessageBoxA(HWND hWnd, LPCSTR lpText,LPCSTR lpCaption, UINT uType);
	int WINAPI HookMessageBoxW(HWND hWnd, LPCWSTR lpText,LPCWSTR lpCaption, UINT uType);
	void SetHookMessageBox(HMODULE hModule);
	
	typedef int(WINAPI* PfnMessageBox)(HWND,LPCSTR,LPCSTR,UINT);
	
	int* addrDispatchA=(int*)DispatchMessageA;
	int* addrDispatchW=(int*)DispatchMessageW;
	LRESULT WINAPI HookDispatchMessageA(MSG* msg);
	LRESULT WINAPI HookDispatchMessageW(MSG* msg);
	void SetHookDispatchMessage(HMODULE hModule);
	
	typedef LRESULT (WINAPI* DLLDISPATCHMESSAGE)(MSG* msg);
	/////////////////////////////////////////////////////////////////////////////
	
	//{{AFX_INSERT_LOCATION}}
	// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
	
	#endif // !defined(AFX_MFCHOOKAPI_H__6A8FC5E5_0E77_4B74_8344_CB9CA22141E5__INCLUDED_)
	4、MfcHookApi.cpp代码如下:
	// MfcHookApi.cpp : Defines the initialization routines for the DLL.
	//
	
	#include "stdafx.h"
	#include "MfcHookApi.h"
	#include <TlHelp32.h>
	#include <stdio.h>
	#include <Shlwapi.h>
	
	#pragma comment(lib,"shlwapi.lib")
	#pragma comment(lib,"th32.lib")
	
	#ifdef _DEBUG
	#define new DEBUG_NEW
	#undef THIS_FILE
	static char THIS_FILE[]=__FILE__;
	#endif
	
	//
	// Note!
	//
	// If this DLL is dynamically linked against the MFC
	// DLLs,any functions exported from this DLL which
	// call into MFC must have the AFX_MANAGE_STATE macro
	// added at the very beginning of the function.
	//
	// For example:
	//
	// extern "C" BOOL PASCAL EXPORT ExportedFunction()
	// {
	// AFX_MANAGE_STATE(AfxGetStaticModuleState());
	// // normal function body here
	// }
	//
	// It is very important that this macro appear in each
	// function,prior to any calls into MFC. This means that
	// it must appear as the first statement within the
	// function,even before any object variable declarations
	// as their constructors may generate calls into the MFC
	// DLL.
	//
	// Please see MFC Technical Notes 33 and 58 for additional
	// details.
	//
	
	/////////////////////////////////////////////////////////////////////////////
	// CMfcHookApiApp
	
	BEGIN_MESSAGE_MAP(CMfcHookApiApp,CWinApp)
	//{{AFX_MSG_MAP(CMfcHookApiApp)
	// NOTE - the ClassWizard will add and remove mapping macros here.
	// DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	END_MESSAGE_MAP()
	
	/////////////////////////////////////////////////////////////////////////////
	// CMfcHookApiApp construction
	
	CMfcHookApiApp::CMfcHookApiApp()
	{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
	}
	
	/////////////////////////////////////////////////////////////////////////////
	// The one and only CMfcHookApiApp object
	
	CMfcHookApiApp theApp;
	
	HHOOK hHook=0;
	HINSTANCE hinstDll=0;
	DWORD dwCurrentPid=0;
	DWORD TargetPid=0;
	BOOL bApiHook=false;
	FARPROC fpApiAddrA=NULL,fpApiAddrW=NULL;
	BYTE btOldCodeA[5]={0,0,0,0,0};
	BYTE btNewCodeA[5]={0,0,0,0,0};
	BYTE btOldCodeW[5]={0,0,0,0,0};
	BYTE btNewCodeW[5]={0,0,0,0,0};
	DWORD dwProtect=0;
	HANDLE hRemoteProcess32=0,hSnap=0;
	//#pragma data_seg()
	//#pragma comment(linker,"/SECTION:YuKai,rws")
	int nHookCount=0;
	
	char* pcProsessName="DoWin32Test.exe";
	
	//---------------------------------------------------------------------------
	// 空的钩子函数
	LRESULT WINAPI HookProc(int nCode,WPARAM wParam,LPARAM lParam)
	{
	return CallNextHookEx(hHook,nCode,wParam,lParam);
	}
	
	extern "C" __declspec(dllexport) void ActiveHook()
	{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	}
	
	//---------------------------------------------------------------------------
	//本函数一定要用WINAPI(即__stdcall),表示本函数自己平衡堆栈(和win32 API一致)
	int WINAPI HookMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
	{
	nHookCount++;
	printf("HookMessageBoxA hook Success......%d
",nHookCount);
	return 1;
	//return ((PfnMessageBox)(addrMsgBoxA))(NULL,"HOOK成功","HOOK成功",MB_ICONINFORMATION);
	}
	
	//---------------------------------------------------------------------------
	//本函数一定要用WINAPI(即__stdcall),表示本函数自己平衡堆栈(和win32 API一致)
	int WINAPI HookMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
	{
	
	nHookCount++;
	printf("HookMessageBoxW hook Success......%d
",nHookCount);
	return 1;
	//return ((PfnMessageBox)(addrMsgBoxW))(NULL,"HOOK成功","HOOK成功",MB_ICONINFORMATION);
	}
	
	
	//---------------------------------------------------------------------------
	// 安装卸载空钩子(ProcessID=NULL:卸载)
	extern "C" __declspec(dllexport) void InstallHook4Api(HWND hwnd)
	{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	//GetWindowThreadProcessId(hwnd,&TargetPid);
	//只hook窗口句柄为hwnd的线程
	if(hwnd)
	hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)HookProc,hinstDll,GetWindowThreadProcessId(hwnd,&TargetPid));
	else
	{
	if(hHook)
	UnhookWindowsHookEx(hHook);
	}
	}
	
	void SetHookMessageBox(HMODULE hModule)
	{
	HMODULE hModuleUser32=0;
	char cArrDllName[256];
	hinstDll=(HINSTANCE)hModule;
	BOOL bNext=FALSE;
	PROCESSENTRY32 procEntry32;
	//获取目标进程句柄。
	procEntry32.dwSize=sizeof(PROCESSENTRY32);
	hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	bNext=Process32First(hSnap,&procEntry32);
	while(bNext)
	{
	if(!stricmp(procEntry32.szExeFile,pcProsessName)) //--->>
	{
	hRemoteProcess32=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,1,procEntry32.th32ProcessID);
	break;
	}
	bNext=Process32Next(hSnap,&procEntry32);
	}
	CloseHandle(hSnap);
	dwCurrentPid=procEntry32.th32ProcessID;
	//载入需要HOOK的DLL并保存原始ESP
	hModuleUser32=LoadLibrary("user32.dll");
	fpApiAddrA=GetProcAddress(hModuleUser32,"MessageBoxA");
	if(fpApiAddrA==NULL)
	return;
	/*MessageBoxA原前5字节存至OldCode[5]*/
	_asm
	{
	pushad
	lea edi,btOldCodeA
	mov esi,fpApiAddrA
	cld
	movsd
	movsb
	popad
	}
	/*MessageBoxA新前5字节存至 NewCode[5]*/
	btNewCodeA[0]=0xe9;
	_asm
	{
	lea eax,HookMessageBoxA
	mov ebx,fpApiAddrA
	sub eax,ebx
	sub eax,5
	mov dword ptr [btNewCodeA+1],eax
	}
	//修改ESP
	/*改写MessageBoxA()的前5个字节*/
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrA,btNewCodeA,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,dwProtect,&dwProtect);
	//载入需要HOOK的DLL并保存原始ESP
	fpApiAddrW=GetProcAddress(hModuleUser32,"MessageBoxW");
	if(fpApiAddrW==NULL)
	return;
	/*MessageBoxA原前5字节存至OldCode[5]*/
	_asm
	{
	pushad
	lea edi,btOldCodeW
	mov esi,fpApiAddrW
	cld
	movsd
	movsb
	popad
	}
	/*MessageBoxW新前5字节存至 NewCode[5]*/
	btNewCodeW[0]=0xe9;
	_asm
	{
	lea eax,HookMessageBoxW
	mov ebx,fpApiAddrW
	sub eax,ebx
	sub eax,5
	mov dword ptr [btNewCodeW+1],eax
	}
	/*改写MessageBoxA()的前5个字节*/
	//修改ESP
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrW,btNewCodeW,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,dwProtect,&dwProtect);
	
	bApiHook=true;
	//增加引用次数后立即卸钩(目的:卸钩后保留该dll存在于目标进程中)
	GetModuleFileName((HINSTANCE)hModule,cArrDllName,256);
	LoadLibrary(cArrDllName);
	//只能由目标程序卸钩,否则目标程序有可能来不及加载Hook进来的dll
	if(hHook && (dwCurrentPid==TargetPid))
	UnhookWindowsHookEx(hHook);
	
	}
	
	void SetHookDispatchMessage(HMODULE hModule)
	{
	HMODULE hModuleUser32=0;
	char cArrDllName[256];
	hinstDll=(HINSTANCE)hModule;
	BOOL bNext=FALSE;
	PROCESSENTRY32 procEntry32;
	//获取目标进程句柄。
	procEntry32.dwSize=sizeof(PROCESSENTRY32);
	hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	bNext=Process32First(hSnap,&procEntry32);
	while(bNext)
	{
	if(!stricmp(procEntry32.szExeFile,pcProsessName))
	{
	hRemoteProcess32=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,1,procEntry32.th32ProcessID);
	break;
	}
	bNext=Process32Next(hSnap,&procEntry32);
	}
	CloseHandle(hSnap);
	dwCurrentPid=procEntry32.th32ProcessID;
	//载入需要HOOK的DLL并保存原始ESP
	hModuleUser32=LoadLibrary("user32.dll");
	fpApiAddrA=GetProcAddress(hModuleUser32,"DispatchMessageA");
	if(fpApiAddrA==NULL)
	return;
	/*MessageBoxA原前5字节存至OldCode[5]*/
	_asm
	{
	pushad
	lea edi,btOldCodeA
	mov esi,fpApiAddrA
	cld
	movsd
	movsb
	popad
	}
	/*MessageBoxA新前5字节存至 NewCode[5]*/
	btNewCodeA[0]=0xe9;
	_asm
	{
	lea eax,HookDispatchMessageA
	mov ebx,fpApiAddrA
	sub eax,ebx
	sub eax,5
	mov dword ptr [btNewCodeA+1],eax
	}
	//修改ESP
	/*改写MessageBoxA()的前5个字节*/
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrA,btNewCodeA,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,dwProtect,&dwProtect);
	
	//载入需要HOOK的DLL并保存原始ESP
	fpApiAddrW=GetProcAddress(hModuleUser32,"DispatchMessageW");
	if(fpApiAddrA==NULL)
	return;
	/*MessageBoxA原前5字节存至OldCode[5]*/
	_asm
	{
	pushad
	lea edi,btOldCodeW
	mov esi,fpApiAddrW
	cld
	movsd
	movsb
	popad
	}
	/*MessageBoxW新前5字节存至 NewCode[5]*/
	btNewCodeW[0]=0xe9;
	_asm
	{
	lea eax,HookDispatchMessageW
	mov ebx,fpApiAddrW
	sub eax,ebx
	sub eax,5
	mov dword ptr [btNewCodeW+1],eax
	}
	/*改写MessageBoxA()的前5个字节*/
	//修改ESP
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrW,btNewCodeW,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,dwProtect,&dwProtect);
	
	bApiHook=true;
	//增加引用次数后立即卸钩(目的:卸钩后保留该dll存在于目标进程中)
	GetModuleFileName((HINSTANCE)hModule,cArrDllName,256);
	LoadLibrary(cArrDllName);
	//只能由目标程序卸钩,否则目标程序有可能来不及加载Hook进来的dll
	if(hHook && (dwCurrentPid==TargetPid))
	UnhookWindowsHookEx(hHook);
	
	}
	
	LRESULT WINAPI HookDispatchMessageA(MSG* msg)
	{
	CString szFormat="";
	CString szLog="";
	CTime time;
	CString szFileName="";
	DWORD dwFlag=0;
	
	RECT rc;
	TCHAR szCaption[128];
	//HMODULE hDll=0;
	//DLLDISPATCHMESSAGE dispatch;
	LRESULT lr=0;
	//hDll=LoadLibrary("user32.dll");
	//if (hDll)
	//{
	// dispatch=(DLLDISPATCHMESSAGE)GetProcAddress(hDll,"DispatchMessageA");
	// if (dispatch)
	// {
	// lr=(dispatch)(msg);
	// }
	//}
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrA,btOldCodeA,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,dwProtect,&dwProtect);
	lr=DispatchMessageA(msg);
	
	//写日志
	szFormat="%-16X%-16X%-16X%-16X%-16d%-16d%-16X%-16d%-16d%-128s
";
	memset(szCaption,0,128);
	if (IsWindow(msg->hwnd))
	{
	GetWindowRect(msg->hwnd,&rc);
	GetWindowText(msg->hwnd,szCaption,128);
	szLog.Format(szFormat,msg->hwnd,msg->message,msg->wParam,msg->wParam,msg->pt.x,msg->pt.y,msg->time,rc.right,rc.bottom,szCaption);
	}
	else
	{
	szLog.Format(szFormat,msg->hwnd,msg->message,msg->wParam,msg->wParam,msg->pt.x,msg->pt.y,msg->time,-1,-1,szCaption);
	}
	
	time=CTime::GetCurrentTime();
	szFileName=time.Format("%Y%m%d%H");
	szFileName.Insert(0,"C:DM");
	szFileName+=".log";
	dwFlag=CFile::modeReadWrite|CFile::shareDenyRead;
	if (!PathFileExists(szFileName))
	{
	dwFlag|=CFile::modeCreate;
	}
	CFile fileLog(szFileName,dwFlag);
	fileLog.SeekToEnd();
	fileLog.Write(szLog,szLog.GetLength());
	fileLog.Flush();
	fileLog.Close();
	
	//重新HOOK以便写日志
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrA,btNewCodeA, 5, 0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrA,5,dwProtect,&dwProtect);
	return lr;
	}
	
	LRESULT WINAPI HookDispatchMessageW(MSG* msg)
	{
	CString szFormat="";
	CString szLog="";
	CTime time;
	CString szFileName="";
	DWORD dwFlag=0;
	
	RECT rc;
	DWORD dwThreadId=0;
	TCHAR szCaption[128];
	//HMODULE hDll=0;
	//DLLDISPATCHMESSAGE dispatch;
	LRESULT lr=0;
	//hDll=LoadLibrary("user32.dll");
	//if (hDll)
	//{
	// dispatch=(DLLDISPATCHMESSAGE)GetProcAddress(hDll,"DispatchMessageW");
	// if (dispatch)
	// {
	// lr=(dispatch)(msg);
	// }
	//}
	//恢复HOOK
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrW,btOldCodeW,5,0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,dwProtect,&dwProtect);
	lr=DispatchMessageW(msg);
	
	szFormat="%-16X%-16X%-16X%-16X%-16d%-16d%-16X%-16d%-16d%-16d%-128s
";
	memset(szCaption,0,128);
	dwThreadId=GetCurrentThreadId();
	if (IsWindow(msg->hwnd))
	{
	GetWindowRect(msg->hwnd,&rc);
	GetWindowText(msg->hwnd,szCaption,128);
	szLog.Format(szFormat,msg->hwnd,msg->message,msg->wParam,msg->wParam,msg->pt.x,msg->pt.y,msg->time,rc.right,rc.bottom,dwThreadId,szCaption);
	}
	else
	{
	szLog.Format(szFormat,msg->hwnd,msg->message,msg->wParam,msg->wParam,msg->pt.x,msg->pt.y,msg->time,-1,-1,dwThreadId,szCaption);
	}
	
	time=CTime::GetCurrentTime();
	szFileName=time.Format("%Y%m%d%H");
	szFileName.Insert(0,"C:DM");
	szFileName+=".log";
	dwFlag=CFile::modeReadWrite|CFile::shareDenyRead;
	if (!PathFileExists(szFileName))
	{
	dwFlag|=CFile::modeCreate;
	}
	CFile fileLog(szFileName,dwFlag);
	fileLog.SeekToEnd();
	fileLog.Write(szLog,szLog.GetLength());
	fileLog.Flush();
	fileLog.Close();
	
	//重新HOOK以便写日志
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,PAGE_READWRITE,&dwProtect);
	WriteProcessMemory(hRemoteProcess32,fpApiAddrW,btNewCodeW, 5, 0);
	VirtualProtectEx(hRemoteProcess32,fpApiAddrW,5,dwProtect,&dwProtect);
	return lr;
	}
	
	BOOL CMfcHookApiApp::InitInstance()
	{
	// TODO: Add your specialized code here and/or call the base class
	SetHookDispatchMessage(GetModuleHandle(NULL));
	//SetHookMessageBox(GetModuleHandle(NULL));
	
	CString szFormat="";
	CString szLog="";
	CTime time;
	CString szFileName="";
	DWORD dwFlag=0;
	
	szFormat="%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-128s
";
	szLog.Format(szFormat,"hwnd","message","wparam","lparam","mouse.x","mouse.y","message.time","client.width","client.height","thread id","window.caption");
	time=CTime::GetCurrentTime();
	szFileName=time.Format("%Y%m%d%H");
	szFileName.Insert(0,"C:DM");
	szFileName+=".log";
	dwFlag=CFile::modeReadWrite|CFile::shareDenyRead;
	if (!PathFileExists(szFileName))
	{
	dwFlag|=CFile::modeCreate;
	}
	CFile fileLog(szFileName,dwFlag);
	fileLog.SeekToEnd();
	fileLog.Write(szLog,szLog.GetLength());
	fileLog.Flush();
	fileLog.Close();
	
	return CWinApp::InitInstance();
	}
	5、新建一个测试程序:WIN32项目,取名为:DoWin32Test,代码如下:
	
	// DoWin32Test.cpp : Defines the entry point for the application.
	//
	
	#include "stdafx.h"
	#include "resource.h"
	
	#define MAX_LOADSTRING 100
	
	// Global Variables:
	HINSTANCE hInst; // current instance
	TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
	TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
	
	// Foward declarations of functions included in this code module:
	ATOM MyRegisterClass(HINSTANCE hInstance);
	BOOL InitInstance(HINSTANCE, int);
	LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
	LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
	
	int APIENTRY WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
	{
	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;
	
	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_DOWIN32TEST, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);
	
	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
	return FALSE;
	}
	
	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DOWIN32TEST);
	
	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
	if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
	{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
	}
	}
	
	return msg.wParam;
	}
	
	
	
	//
	// FUNCTION: MyRegisterClass()
	//
	// PURPOSE: Registers the window class.
	//
	// COMMENTS:
	//
	// This function and its usage is only necessary if you want this code
	// to be compatible with Win32 systems prior to the 'RegisterClassEx'
	// function that was added to Windows 95. It is important to call this function
	// so that the application will get 'well formed' small icons associated
	// with it.
	//
	ATOM MyRegisterClass(HINSTANCE hInstance)
	{
	WNDCLASSEX wcex;
	
	wcex.cbSize = sizeof(WNDCLASSEX);
	
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = (WNDPROC)WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DOWIN32TEST);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName = (LPCSTR)IDC_DOWIN32TEST;
	wcex.lpszClassName = szWindowClass;
	wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
	
	return RegisterClassEx(&wcex);
	}
	
	//
	// FUNCTION: InitInstance(HANDLE, int)
	//
	// PURPOSE: Saves instance handle and creates main window
	//
	// COMMENTS:
	//
	// In this function, we save the instance handle in a global variable and
	// create and display the main program window.
	//
	BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
	{
	HWND hWnd;
	
	hInst = hInstance; // Store instance handle in our global variable
	
	hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
	CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	
	if (!hWnd)
	{
	return FALSE;
	}
	
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	
	return TRUE;
	}
	
	//
	// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
	//
	// PURPOSE: Processes messages for the main window.
	//
	// WM_COMMAND - process the application menu
	// WM_PAINT - Paint the main window
	// WM_DESTROY - post a quit message and return
	//
	//
	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR szHello[MAX_LOADSTRING];
	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
	
	switch (message)
	{
	case WM_COMMAND:
	wmId = LOWORD(wParam);
	wmEvent = HIWORD(wParam);
	// Parse the menu selections:
	switch (wmId)
	{
	case IDM_ABOUT:
	DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
	break;
	case IDM_EXIT:
	DestroyWindow(hWnd);
	break;
	default:
	return DefWindowProc(hWnd, message, wParam, lParam);
	}
	break;
	case WM_PAINT:
	hdc = BeginPaint(hWnd, &ps);
	// TODO: Add any drawing code here...
	RECT rt;
	GetClientRect(hWnd, &rt);
	DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
	EndPaint(hWnd, &ps);
	break;
	case WM_DESTROY:
	PostQuitMessage(0);
	break;
	default:
	return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
	}
	
	// Mesage handler for about box.
	LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
	{
	switch (message)
	{
	case WM_INITDIALOG:
	return TRUE;
	
	case WM_COMMAND:
	if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
	{
	EndDialog(hDlg, LOWORD(wParam));
	return TRUE;
	}
	break;
	}
	return FALSE;
	}
	最后,记得修改所有项目的生成目录,令所有项目生成到一个目录。我设置的方法是直接在默认生成目录前加“..”。祝你成功。