我做了一个api hook,想在系统范围内钩住所有进程对ws2_32里面的wsaSend函数的调用。dll插入没问题,问题出在api hook的安装上面,代码如下:
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress, 
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
   ULONG size;      
   PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
                    ImageDirectoryEntryToData(hModCallerModule,TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
   if (pImportDesc == NULL)
      return;
   for (;pImportDesc->Name;pImportDesc++)
   {
      LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);   
      if (!lstrcmpiA(pszDllName,pszCalleeModuleName))
  {   
  break;
  }         
   } 
   if (pImportDesc->Name == NULL)
   {
      return;
   }
   PIMAGE_THUNK_DATA pThunk =(PIMAGE_THUNK_DATA) 
                           ((PBYTE)hModCallerModule+pImportDesc->FirstThunk);   
   for (;pThunk->u1.Function;pThunk++)
   {
       PROC * ppfn= (PROC *)&pThunk->u1.Function;     
       if (*ppfn==pfnOriginApiAddress)
   {
  DWORD dwOldProtect;   
  VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),PAGE_READWRITE,&dwOldProtect);   
          WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnDummyFuncAddress,
                             sizeof(pfnDummyFuncAddress),NULL);
  VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),dwOldProtect,0);
          return;
   }      
   }
}
BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
    if (pszCalleeModuleName == NULL)
{
       return FALSE;
}
    if (pfnOriginApiAddress == NULL)
{
       return FALSE;
}    
    if (hModCallerModule == NULL)
{
        MEMORY_BASIC_INFORMATION mInfo;
        HMODULE hModHookDLL;
        HANDLE hSnapshot;
        MODULEENTRY32 me;
me.dwSize=sizeof(MODULEENTRY32);  
        VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));
        hModHookDLL=(HMODULE)mInfo.AllocationBase;
        hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
        BOOL bOk = Module32First(hSnapshot,&me);
        while (bOk)
{
            if (me.hModule != hModHookDLL)
{
                hModCallerModule = me.hModule;                
                HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
                pfnDummyFuncAddress,hModCallerModule);
}
            bOk = Module32Next(hSnapshot,&me);
}
        return TRUE; 
}    
    else
{
        HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
                   pfnDummyFuncAddress,hModCallerModule);
        return TRUE;
}
    return FALSE;
}
void InstallApiHooks(BOOL IsHook)
{
if (IsHook)
{
HookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
                        "WSASend"),(PROC)&NewWsaSend,NULL);
}
else
{
UnhookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
                        "WSASend"),(PROC)&NewWsaSend,NULL);
}
}int NewWsaSend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE)
{
char szFileName[64];
GetModuleFileName(GetModuleHandle(NULL),szFileName,64);
int ret=100;
ret=WSASend(s,lpBuffers,dwBufferCount,lpNumberOfBytesSent,
            dwFlags,lpOverlapped,lpCompletionROUTINE);
char szBytesOfSend[20];
wsprintf(szBytesOfSend,"Send %d Bytes",ret);
MessageBox(NULL,lpBuffers->buf,szFileName,MB_OK);
return ret;        //问题出在这里,能够显示出调用者传递给它的  lpBuffers ,但返回时目标进程报错,原因是某个内存地址为只读。    
}

解决方案 »

  1.   

    if(*ppfn==pfnOriginApiAddress)
       {
      DWORD dwOldProtect;   
      VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),PAGE_READWRITE,&dwOldProtect);   
              WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnDummyFuncAddress,
                                 sizeof(pfnDummyFuncAddress),NULL);
      VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),dwOldProtect,0);
              return;
       }  这里的问题?内存访问违规~~
      

  2.   

    to rivershan:
    好象不是,因为执行的时候在这里并没有报错,而是在我自己的函数里面返回的时候报错。
      

  3.   

    好像Hook Socket函数比较特殊~
    我也没玩过~