基于VC++开发InlineHook网络数据发送接收函数
大家都懂,很多时候开发项目需要修改网络数据,代码如下,请柬代码分析
#include "stdafx.h" #include <stdio.h> #include <Windows.h> #include <Winsock2.h> #ifdef _MANAGED #pragma managed(push, off) #endif #define HOOK_API extern "C" _declspec(dllexport) //本dll的handle HANDLE g_hInstance = NULL; //修改API入口为 mov eax, 00400000;jmp eax是程序能跳转到自己的函数 BYTE g_btNewBytes[8] = { 0xB8, 0x0, 0x0, 0x40, 0x0, 0xFF, 0xE0, 0x0 }; //保存原API入口的8个字节 DWORD g_dwOldBytes[2][2] = { 0x0, 0x0, 0x0, 0x0 }; //钩子句柄 HHOOK g_hOldHook = NULL; //API中send函数的地址 DWORD g_pSend = 0; DWORD g_pRecv = 0; //事务,解决同步问题 HANDLE g_hSendEvent = NULL; HANDLE g_hRecvEvent = NULL; //自己的send函数地址,参数必须与API的send函数地址相同 int _stdcall hook_send( SOCKET s, const char *buf, int len, int flags ); int _stdcall hook_recv(IN SOCKET s,OUT char FAR * buf,IN int len,IN int flags ); //要Hook的进程和主线程ID号 DWORD g_dwProcessID = 0; DWORD g_dwThreadID = 0; // 如果是win9x,不能使用fopen函数 void WriteLog(char *fmt,...) { va_list args; char modname[200]; char temp[5000]; HANDLE hFile; SYSTEMTIME loaclTime; GetLocalTime(&loaclTime); GetModuleFileName(NULL, modname, sizeof(modname)); if((hFile =CreateFile("c:\\hookapi.log", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) <0) { return; } SetFilePointer(hFile, 0, NULL, FILE_END); wsprintf(temp, "%d:%d:%d mydll.dll:%s:", loaclTime.wHour,loaclTime.wMinute,loaclTime.wMilliseconds, modname); DWORD dw; WriteFile(hFile, temp, strlen(temp), &dw, NULL); va_start(args,fmt); vsprintf(temp, fmt, args); va_end(args); WriteFile(hFile, temp, strlen(temp), &dw, NULL); wsprintf(temp, "\r\n"); WriteFile(hFile, temp, strlen(temp), &dw, NULL); CloseHandle(hFile); } int _stdcall hook_recv(IN SOCKET s,OUT char FAR * buf,IN int len,IN int flags ) { int nRet; WaitForSingleObject( g_hRecvEvent, INFINITE ); //恢复API头8个字节 WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pRecv,( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL ); /* 这里可以添加想要进行的处理过程 */ //真正执行API函数 nRet = recv( s, buf, len, flags ); //写入跳转语句,继续Hook WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pRecv,( void* )g_btNewBytes, sizeof( DWORD )*2, NULL); WriteLog("%s",buf); SetEvent( g_hRecvEvent ); return nRet; } int _stdcall hook_send( SOCKET s, const char *buf, int len, int flags ) { int nRet; WaitForSingleObject( g_hSendEvent, INFINITE ); //恢复API头8个字节 WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend, ( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL ); /* 这里可以添加想要进行的处理过程 */ WriteLog("Send:%s",buf); //真正执行API函数 nRet = send( s, buf, len, flags ); //写入跳转语句,继续Hook WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend, ( void* )g_btNewBytes, sizeof( DWORD )*2, NULL ); SetEvent( g_hSendEvent ); return nRet; } static LRESULT WINAPI HookProc( int nCode, WPARAM wParam, LPARAM lParam ) { return CallNextHookEx( g_hOldHook, nCode, wParam, lParam ); } HOOK_API BOOL StartHook(HWND hWnd) { //通过传入的窗口句柄获取线程句柄 g_dwThreadID = GetWindowThreadProcessId( hWnd, &g_dwProcessID ); //WH_CALLWNDPROC类型的Hook g_hOldHook = SetWindowsHookEx( WH_CALLWNDPROC, HookProc,( HINSTANCE ) g_hInstance, g_dwThreadID ); if( g_hOldHook == NULL ) return FALSE; return TRUE; } HOOK_API void StopHook(void) { if(g_hOldHook != NULL) { WaitForSingleObject( g_hSendEvent, INFINITE ); HANDLE hProcess = NULL; hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_dwProcessID); DWORD dwOldProc; DWORD dwNewProc; //改变页面属性为读写 VirtualProtectEx( hProcess, ( void* )g_pSend, 8, PAGE_READWRITE, &dwOldProc ); //恢复API的首8个字节 WriteProcessMemory( hProcess, ( void* )g_pSend, ( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL ); //恢复页面文件的属性 VirtualProtectEx( hProcess, ( void* )g_pSend, 8, dwOldProc, &dwNewProc ); CloseHandle(g_hSendEvent); UnhookWindowsHookEx( g_hOldHook ); } } DWORD WINAPI ThreadFunc( LPVOID lpParam ) { char szMsg[80]; wsprintf( szMsg, "Parameter = %d.", *(DWORD*)lpParam ); MessageBox( NULL, szMsg, "ThreadFunc", MB_OK ); while(1) Sleep(1000); return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if(ul_reason_for_call == DLL_PROCESS_ATTACH) { WriteLog("Start HOOK"); //获取本dll句柄 g_hInstance = hModule; //创建事务 g_hSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL ); //重写API开头的8字节 HMODULE hWsock = LoadLibrary( "wsock32.dll" ); g_pSend = ( DWORD )GetProcAddress( hWsock, "send" ); g_pRecv = (DWORD)GetProcAddress( hWsock, "recv" ); //保存原始字节 ReadProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend,( void * )g_dwOldBytes[0], sizeof( DWORD )*2, NULL ); //将00400000改写为我们函数的地址 *( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )hook_send; WriteProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend,( void * )g_btNewBytes, sizeof( DWORD )*2, NULL ); // //保存原始字节 // ReadProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pRecv,( void * )g_dwOldBytes[0], sizeof( DWORD )*2, NULL ); // //将00400000改写为我们函数的地址 // *( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )hook_recv; // WriteProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pRecv,( void * )g_btNewBytes, sizeof( DWORD )*2, NULL ); DWORD dwThreadId, dwThrdParam = 1; HANDLE hThread; char szMsg[80]; hThread = CreateThread( NULL, // default security attributes 0, // use default stack size ThreadFunc, // thread function &dwThrdParam, // argument to thread function 0, // use default creation flags &dwThreadId); // returns the thread identifier // Check the return value for success. if (hThread == NULL) { wsprintf( szMsg, "CreateThread failed." ); MessageBox( NULL, szMsg, "main", MB_OK ); } else { CloseHandle( hThread ); } } return TRUE; } #ifdef _MANAGED #pragma managed(pop) #endif
#include <Winsock2.h> //#include <windows.h> #include <stdio.h> #include <Tlhelp32.h> //#pragma argsused //自定义APIHOOK结构 typedef struct { FARPROC funcaddr; BYTE olddata[5]; BYTE newdata[5]; }HOOKSTRUCT; HHOOK g_hHook; HINSTANCE g_hinstDll; HMODULE hModule ; HWND g_hForm; //接收信息窗口句柄 DWORD dwIdOld, dwIdNew; //------------------------------------------------------------------------ // 由于要截获两个库里面的函数,所以每个函数定义了两个HOOK结构 // 一个是wsock32.dll, 一个是ws2_32.dll //------------------------------------------------------------------------ HOOKSTRUCT recvapi; HOOKSTRUCT recvapi1; HOOKSTRUCT sendapi; HOOKSTRUCT sendapi1; HOOKSTRUCT sendtoapi; HOOKSTRUCT sendtoapi1; HOOKSTRUCT WSASendapi; HOOKSTRUCT connectapi; void HookOn(); void HookOff(); BOOL Init(); extern "C" __declspec(dllexport) BOOL __stdcall InstallHook(); extern "C" __declspec(dllexport) BOOL __stdcall UninstallHook(); BOOL hookapi(char *dllname, char *procname, DWORD myfuncaddr, HOOKSTRUCT *hookfunc); int WINAPI Myrecv(SOCKET s, char FAR *buf, int len, int flags); int WINAPI Myrecv1(SOCKET s, char FAR *buf, int len, int flags); int WINAPI Mysend(SOCKET s, char FAR *buf, int len, int flags); int WINAPI Mysend1(SOCKET s, char FAR *buf, int len, int flags); int WINAPI Mysendto(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen); int WINAPI Mysendto1(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen); int WINAPI MyWSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); int WINAPI Myconnect(SOCKET s,const struct sockaddr* name,int namelen); void sndmsg(char *buf); void WriteLog(char *fmt,...); //--------------------------------------------------------------------------- // 入口函数 // 在一载入库时就进行API截获 // 释放时还原 //--------------------------------------------------------------------------- int WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void* lpReserved) { //__asm int 3 switch (reason) { case DLL_PROCESS_ATTACH: g_hinstDll = hinst; g_hForm = FindWindow(NULL, "ZwelL"); InstallHook(); if(!Init()) { MessageBoxA(NULL,"Init","ERROR",MB_OK); return(false); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: UninstallHook(); break; } return TRUE; } //----------------------------------------------------------------------- BOOL Init() { hookapi("wsock32.dll", "recv", (DWORD)Myrecv, &recvapi); hookapi("ws2_32.dll", "recv", (DWORD)Myrecv1, &recvapi1); hookapi("wsock32.dll", "send", (DWORD)Mysend, &sendapi); hookapi("ws2_32.dll", "send", (DWORD)Mysend1, &sendapi1); hookapi("wsock32.dll", "sendto", (DWORD)Mysendto, &sendtoapi); hookapi("ws2_32.dll", "sendto", (DWORD)Mysendto1, &sendtoapi1); hookapi("wsock32.dll", "WSASend", (DWORD)MyWSASend, &WSASendapi); hookapi("ws2_32.dll", "connect", (DWORD)Myconnect, &connectapi); //hookapi("wsock32.dll", "connect", (DWORD)Myconnect, &connectapi); dwIdNew = GetCurrentProcessId(); // 得到所属进程的ID dwIdOld = dwIdNew; HookOn(); // 开始拦截 return(true); } //--------------------------------------------------------------------------- LRESULT WINAPI Hook(int nCode, WPARAM wParam, LPARAM lParam) { return(CallNextHookEx(g_hHook, nCode, wParam, lParam)); } //--------------------------------------------------------------------------- extern "C" __declspec(dllexport) BOOL __stdcall InstallHook() { g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)Hook, g_hinstDll, 0); if (!g_hHook) { MessageBoxA(NULL, "SET ERROR", "ERROR", MB_OK); return(false); } return(true); } //--------------------------------------------------------------------------- extern "C" __declspec(dllexport) BOOL __stdcall UninstallHook() { HookOff(); if(g_hHook == NULL) return true; return(UnhookWindowsHookEx(g_hHook)); } //--------------------------------------------------------------------------- // 根据输入结构截获API //--------------------------------------------------------------------------- BOOL hookapi(char *dllname, char *procname, DWORD myfuncaddr, HOOKSTRUCT *hookfunc) { hModule = LoadLibrary(dllname); hookfunc->funcaddr = GetProcAddress(hModule, procname); if(hookfunc->funcaddr == NULL) return false; memcpy(hookfunc->olddata, hookfunc->funcaddr, 6); hookfunc->newdata[0] = 0xe9; DWORD jmpaddr = myfuncaddr - (DWORD)hookfunc->funcaddr - 5; memcpy(&hookfunc->newdata[1], &jmpaddr, 5); return true; } //--------------------------------------------------------------------------- void HookOnOne(HOOKSTRUCT *hookfunc) { HANDLE hProc; dwIdOld = dwIdNew; hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwIdOld); VirtualProtectEx(hProc, hookfunc->funcaddr, 5, PAGE_READWRITE,&dwIdOld); WriteProcessMemory(hProc, hookfunc->funcaddr, hookfunc->newdata, 5, 0); VirtualProtectEx(hProc, hookfunc->funcaddr, 5, dwIdOld, &dwIdOld); } //--------------------------------------------------------------------------- void HookOn() { // HookOnOne(&recvapi); // HookOnOne(&sendapi); // HookOnOne(&sendtoapi); // HookOnOne(&recvapi1); // HookOnOne(&sendapi1); // HookOnOne(&sendtoapi1); // HookOnOne(&WSASendapi); HookOnOne(&connectapi); } //--------------------------------------------------------------------------- void HookOffOne(HOOKSTRUCT *hookfunc) { HANDLE hProc; dwIdOld = dwIdNew; hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwIdOld); VirtualProtectEx(hProc, hookfunc->funcaddr,5, PAGE_READWRITE, &dwIdOld); WriteProcessMemory(hProc, hookfunc->funcaddr, hookfunc->olddata, 5, 0); VirtualProtectEx(hProc, hookfunc->funcaddr, 5, dwIdOld, &dwIdOld); } //--------------------------------------------------------------------------- void HookOff() { // HookOffOne(&recvapi); // HookOffOne(&sendapi); // HookOffOne(&sendtoapi); // HookOffOne(&recvapi1); // HookOffOne(&sendapi1); // HookOffOne(&sendtoapi1); // HookOffOne(&WSASendapi); HookOffOne(&connectapi); } //--------------------------------------------------------------------------- int WINAPI Myrecv(SOCKET s, char FAR *buf, int len, int flags) { int nReturn; HookOffOne(&recvapi); nReturn = recv(s, buf, len, flags); HookOnOne(&recvapi); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "recv|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //--------------------------------------------------------------------------- int WINAPI Myrecv1(SOCKET s, char FAR *buf, int len, int flags) { int nReturn; HookOffOne(&recvapi1); nReturn = recv(s, buf, len, flags); HookOnOne(&recvapi1); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "recv1|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //--------------------------------------------------------------------------- int WINAPI Mysend(SOCKET s, char FAR *buf, int len, int flags) { int nReturn; HookOffOne(&sendapi); nReturn = send(s, buf, len, flags); HookOnOne(&sendapi); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "send|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //--------------------------------------------------------------------------- int WINAPI Mysend1(SOCKET s, char FAR *buf, int len, int flags) { int nReturn; HookOffOne(&sendapi1); nReturn = send(s, buf, len, flags); HookOnOne(&sendapi1); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "send1|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //-------------------------------------------------------------------------- int WINAPI Mysendto(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen) { int nReturn; HookOffOne(&sendtoapi); nReturn = sendto(s, buf, len, flags, to, tolen); HookOnOne(&sendtoapi); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "sendto|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //-------------------------------------------------------------------------- int WINAPI Mysendto1(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen) { int nReturn; HookOffOne(&sendtoapi1); nReturn = sendto(s, buf, len, flags, to, tolen); HookOnOne(&sendtoapi1); char *tmpbuf=new char[len+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "sendto1|%d|%d|%s", GetCurrentProcessId(), len, buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //---------------------------------------------------------------------------- int WINAPI MyWSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) { int nReturn; HookOffOne(&WSASendapi); nReturn = WSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); HookOnOne(&WSASendapi); char *tmpbuf=new char[*lpNumberOfBytesSent+100]; memset(tmpbuf, 0, sizeof(tmpbuf)); sprintf(tmpbuf, "WSASend|%d|%d|%s", GetCurrentProcessId(), lpNumberOfBytesSent, lpBuffers->buf); sndmsg(tmpbuf); delete tmpbuf; return(nReturn); } //---------显示进程的模块 bool GetListModules(DWORD dwPID,char* ModuleName,ULONG uAddress) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; BOOL bRet = FALSE; // Take a snapshot of all modules in the specified process. hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); if( hModuleSnap == INVALID_HANDLE_VALUE ) { //MessageBox(NULL,"CreateToolhelp32Snapshot error"),"提示",MB_OK); return FALSE; } // Set the size of the structure before using it. me32.dwSize = sizeof( MODULEENTRY32); // Retrieve information about the first module, // and exit if unsuccessful if( !Module32First( hModuleSnap, &me32 ) ) { //MessageBox(NULL,_T("Module32First error"),"提示",MB_OK); CloseHandle( hModuleSnap ); // Must clean up the snapshot object! return( FALSE ); } // Now walk the module list of the process, // and display information about each module //因为我只需要得到exe文件的路径,所以这个循环不要 do { //----下面这两个地方的显示结果是一样的,有中文字符就显示为 ? //MessageBox(NULL,me32.szExePath,"提示",MB_OK); //弹出窗口显示exe文件的路径 //m_edit.SetWindowText(me32.szExePath); //edit控件中显示exe文件的路径 // BYTE* pMem = new BYTE[me32.modBaseSize]; // if(GetProcessMem(dwPID,(DWORD)me32.modBaseAddr,me32.modBaseSize,pMem)) // { // if(GetProcessFunction(pMem) == 0) // printf("%s\n",me32.szExePath); // } // delete[] pMem; if( uAddress >= (ULONG)me32.modBaseAddr && (uAddress = (ULONG)me32.modBaseAddr + me32.modBaseSize)) { strcpy(ModuleName,me32.szExePath); bRet = TRUE; break; } } while( Module32Next( hModuleSnap, &me32 ) ); CloseHandle( hModuleSnap ); return bRet; } int WINAPI Myconnect( SOCKET s, const struct sockaddr* name, int namelen ) { ULONG rEbp; __asm { mov rEbp,ebp } ULONG uAddress = *(ULONG*)(rEbp + 4); //获取调用堆榨地址 char szMsg[MAX_PATH]={0}; if(GetListModules(GetCurrentProcessId(),szMsg,uAddress)) WriteLog(szMsg); SOCKADDR_IN* destSockAddr; destSockAddr = (SOCKADDR_IN *)name; sprintf(szMsg,"0x%x,%s:%d",destSockAddr->sin_family, inet_ntoa(destSockAddr->sin_addr),destSockAddr->sin_port); WriteLog(szMsg); int nReturn; HookOffOne(&connectapi); nReturn = connect(s,name,namelen); HookOnOne(&connectapi); return nReturn; } __declspec(naked) int WINAPI Myconnect1( SOCKET s, const struct sockaddr* name, int namelen ) { //int nReturn; //HookOffOne(&connectapi); __asm { mov edi,edi push ebp mov ebp,esp push 0x71a24a0c ret } // connect(s,name,namelen); // HookOnOne(&connectapi); // // char szMsg[MAX_PATH]; // sprintf(szMsg,"%x",name->sa_data); // WriteLog(szMsg); // return ; } //----------------------------------------------------------------- // 向窗口发送消息 // 考虑到简单性,用了COPYDATASTRUCT结构 // 用内存映射应该会快一点 //----------------------------------------------------------------- void sndmsg(char *buf) { COPYDATASTRUCT cds; cds.dwData=sizeof(COPYDATASTRUCT); cds.cbData=strlen(buf); cds.lpData=buf; SendMessage(g_hForm,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds); } static char s_szMessageBuf[5000]; void WriteLog(char *fmt,...) { va_list args; char modname[200]; HANDLE hFile; SYSTEMTIME loaclTime; GetLocalTime(&loaclTime); GetModuleFileName(NULL, modname, sizeof(modname)); if((hFile =CreateFile("c:\\hookConnect.log", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) <0) { return; } SetFilePointer(hFile, 0, NULL, FILE_END); wsprintf(s_szMessageBuf, "%d:%d:%d :%s:", loaclTime.wHour,loaclTime.wMinute,loaclTime.wMilliseconds, modname); DWORD dw; WriteFile(hFile, s_szMessageBuf, strlen(s_szMessageBuf), &dw, NULL); va_start(args,fmt); vsprintf(s_szMessageBuf, fmt, args); va_end(args); WriteFile(hFile, s_szMessageBuf, strlen(s_szMessageBuf), &dw, NULL); wsprintf(s_szMessageBuf, "\r\n"); WriteFile(hFile, s_szMessageBuf, strlen(s_szMessageBuf), &dw, NULL); CloseHandle(hFile); }