基于VC++开发InlineHook网络数据发送接收函数

来源:互联网 发布:linux获取网卡ip地址 编辑:程序博客网 时间:2024/06/05 10:06

大家都懂,很多时候开发项目需要修改网络数据,代码如下,请柬代码分析


#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);   }