转载请注明来源:http://www.cnblogs.com/xuesongshu/
本程序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\r\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) ) { _tprintf("LookupPrivilegeValue error: %u\r\n", 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\r\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { _tprintf("The token does not have the specified privilege. \r\n"); 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\r\n",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\r\n",sizeWritten,pRemoteBuf); } else { printf("InjectCreate()-->WriteProcessMemory() Error:%ld\r\n",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\r\n",hThreadHandle,dwThreadId); //} //else //{ // printf("CreateRemoteThread Error:%ld\r\n",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.\r\n"); for (int i=0;i<30;i++) { Sleep(1000); printf("."); } printf("\r\n"); 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\r\n",sizeWritten,pRemoteBuf); } else { printf("InjectCreate()-->WriteProcessMemory() Error:%ld\r\n",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\r\n",hThreadHandle,dwThreadId); //} //else //{ // printf("CreateRemoteThread Error:%ld\r\n",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\r\n",GetLastError()); return FALSE; } ((PFNTCREATETHREADEX)pFunc)(&hThread, 0x1FFFFF, NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL); if( hThread == NULL ) { printf("InjectCreateThread()-->NtCreateThreadEx() Error: %d\r\n", GetLastError()); return FALSE; } else { printf("InjectCreateThread()-->NtCreateThreadEx() Success,Thread Id:%ld\r\n",hThread); } } else // 2000, XP, Server2003 { hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); if( hThread == NULL ) { printf("InjectCreateThread()-->CreateRemoteThread() Error: %d\r\n", GetLastError()); return FALSE; } else { printf("InjectCreateThread()-->CreateRemoteThread() Success,Thread Id:%ld\r\n",hThread); } } if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) { printf("InjectCreateThread() : WaitForSingleObject() Error: %d\r\n", 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\r\n",dwThreadId); } else { printf("MsicCreateRemoteThread()-->CreateRemoteThread() Error:%ld\r\n",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\r\n",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\r\n",pMisc); //Patch *pMisc=1; //xx hNewThread=CreateRemoteThread(hProcess,NULL,0,lpStartAddress,lpParameter,0,&dwThreadId); if (dwThreadId) { printf("MsicCreateRemoteThread()-->CreateRemoteThread() Success,Thread Id:%08X\r\n",dwThreadId); } else { printf("MsicCreateRemoteThread()-->CreateRemoteThread() Error:%ld\r\n",GetLastError()); } //UnPatch *pMisc=0; } while(FALSE); if(NULL!=hKernelBase) { printf("MsicCreateRemoteThread()-->hKernelBase:%08X\r\n",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_)
5、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\r\n",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\r\n",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\r\n"; 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\r\n"; 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\r\n"; 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; }
最后,记得修改所有项目的生成目录,令所有项目生成到一个目录。我设置的方法是直接在默认生成目录前加“..\”。祝你成功。