VC++兑现全局钩子勾住textout金山快译的原理实现

VC++实现全局钩子勾住textout金山快译的原理实现

大家都对金山快译可以讲英文软件翻译成中文软件感到惊奇

其实就是全局钩子勾住textout函数

钩子头文件如下

void __declspec(dllexport) WINAPI InstallHook(BOOL,DWORD); 
BOOL WINAPI UnInstallHook(); 
LRESULT CALLBACK GetMsgProC(int code,WPARAM wParam,LPARAM lParam); 
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress, 
        PROC pfnDummyFuncAddress,HMODULE hModCallerModule); 
BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress, 
        PROC pfnDummyFuncAddress,HMODULE hModCallerModule); 
BOOL WINAPI UnhookAllAPIHooks(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress, 
         PROC pfnDummyFuncAddress,HMODULE hModCallerModule); 
BOOL WINAPI H_TextOutA(HDC, int, int, LPCSTR, int); 
BOOL WINAPI H_TextOutW(HDC, int, int, LPCWSTR, int); 
BOOL WINAPI H_ExtTextOutA(HDC, int, int, UINT, CONST RECT *,LPCSTR, UINT, CONST INT *); 
BOOL WINAPI H_ExtTextOutW(HDC, int, int, UINT, CONST RECT *,LPCWSTR, UINT, CONST INT *); 


钩子源文件如下

#include "stdafx.h"   
#include "APIHook_Dll.h"   
#include <ImageHlp.h>   
#include <tlhelp32.h>   
#pragma comment(lib,"ImageHlp") //定义全局共享数据段   
#pragma data_seg("Shared")   
HMODULE hmodDll=NULL;   
HHOOK hHook=NULL;   
#pragma data_seg()   
#pragma comment(linker,"/Section:Shared,rws") //设置全局共享数据段的属性   
///////////////////////////////////// DllMain 函数 /////////////////////////////////////////   
//dll的入口点   
BOOL APIENTRY DllMain( HMODULE hModule,    
                       DWORD  ul_reason_for_call,    
                       LPVOID lpReserved   
      )   
{   
 switch(ul_reason_for_call)   
 {   
 case DLL_PROCESS_ATTACH:   
  //if(sHook)     
     
 case DLL_PROCESS_DETACH:   
  UnInstallHook();   
  break;   
 }   
 hmodDll=hModule;   
    return TRUE;   
}   
///////////////////////////////////// HookOneAPI 函数 /////////////////////////////////////////   
//进行IAT转换的关键函数,其参数含义:   
//pszCalleeModuleName:需要hook的模块名   
//pfnOriginApiAddress:要替换的自己API函数的地址   
//pfnDummyFuncAddress:需要hook的模块名的地址   
//hModCallerModule:我们要查找的模块名称,如果没有被赋值,   
//     将会被赋值为枚举的程序所有调用的模块   
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,    
        PROC pfnDummyFuncAddress,HMODULE hModCallerModule)   
{   
 ULONG size;   
 //获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针   
 PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)   
  ImageDirectoryEntryToData(hModCallerModule,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);   
 if (pImportDesc == NULL)   
  return;   
 //查找记录,看看有没有我们想要的DLL   
 for (;pImportDesc->Name;pImportDesc++)   
 {   
  LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);   
  if (lstrcmpiA(pszDllName,pszCalleeModuleName) == 0)   
   break;   
 }   
 if (pImportDesc->Name == NULL)   
 {   
  return;   
 }   
 //寻找我们想要的函数   
 PIMAGE_THUNK_DATA pThunk =    
  (PIMAGE_THUNK_DATA)((PBYTE)hModCallerModule+pImportDesc->FirstThunk);//IAT   
 for (;pThunk->u1.Function;pThunk++)   
 {   
  //ppfn记录了与IAT表项相应的函数的地址   
  PROC * ppfn= (PROC *)&pThunk->u1.Function;     
  if (*ppfn == pfnOriginApiAddress)    
  {   
   //如果地址相同,也就是找到了我们想要的函数,进行改写,将其指向我们所定义的函数   
   WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),   
    sizeof(pfnDummyFuncAddress),NULL);   
   return;   
  }   
 }   
}   
//查找所挂钩的进程所应用的dll模块的   
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 = {sizeof(MODULEENTRY32)};   
  //MODULEENTRY32:描述了一个被指定进程所应用的模块的struct   
  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;//赋值   
    //me.hModule:指向当前被挂钩进程的每一个模块    
    HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,   
     pfnDummyFuncAddress,hModCallerModule);   
   }   
   bOk = Module32Next(hSnapshot,&me);   
  }   
  return TRUE;     
 }   
 //如果传进来了,进行查找   
 else   
 {   
  HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,   
    pfnDummyFuncAddress,hModCallerModule);   
  return TRUE;   
 }   
 return FALSE;   
}   
//////////////////////////////////// UnhookAllAPIHooks 函数 /////////////////////////////////////   
//通过使pfnDummyFuncAddress与pfnOriginApiAddress相等的方法,取消对IAT的修改   
BOOL WINAPI UnhookAllAPIHooks(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,   
         PROC pfnDummyFuncAddress,HMODULE hModCallerModule)   
{   
 PROC temp;   
 temp = pfnOriginApiAddress;   
 pfnOriginApiAddress = pfnDummyFuncAddress;   
 pfnDummyFuncAddress = temp;   
 return HookAllAPI(pszCalleeModuleName,pfnOriginApiAddress,   
  pfnDummyFuncAddress,hModCallerModule);   
}   
////////////////////////////////// GetMsgProc 函数 ////////////////////////////////////////   
//钩子子程。与其它钩子子程不大相同,没做什么有意义的事情,继续调用下一个钩子子程,形成循环   
LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam)   
{   
 return CallNextHookEx(hHook,code,wParam,lParam);   
}   
//////////////////////////////////// InstallHook 函数 /////////////////////////////////////   
//安装或卸载钩子,BOOL IsHook参数是标志位   
//对要钩哪个API函数进行初始化   
//我们这里装的钩子类型是WH_GETMESSAGE   
void __declspec(dllexport) WINAPI InstallHook(BOOL IsHook,DWORD dwThreadId)   
{   
 if(IsHook)   
 {   
 hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,dwThreadId);   
    
 //GetProcAddress(GetModuleHandle("GDI32.dll"),"ExtTextOutA"):取得要钩的函数在所在dll中的地址   
    
 HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),   
  "TextOutW"),(PROC)&H_TextOutW,NULL);   
 HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),   
  "TextOutA"),(PROC)&H_TextOutA,NULL);   
 }   
 else   
 {   
  UnInstallHook();   
  UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),   
   "TextOutW"),(PROC)&H_TextOutW,NULL);   
  UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),   
   "TextOutA"),(PROC)&H_TextOutA,NULL);   
 }   
}   
///////////////////////////////////// UnInstallHook 函数 ////////////////////////////////////   
//卸载钩子   
BOOL WINAPI UnInstallHook()   
{   
 UnhookWindowsHookEx(hHook);   
 return TRUE;   
}   
///////////////////////////////////// H_TextOutA 函数 /////////////////////////////////////////   
//我们的替换函数,可以在里面实现我们所要做的功能   
//这里我做的是显示一个对话框,指明是替换了哪个函数   
BOOL WINAPI H_TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpString,int cbString)   
{   
//  FILE *stream=fopen("logfile.txt","a+t");   
 MessageBox(NULL,"TextOutA","APIHook_Dll ---rivershan",MB_OK);   
 TextOutA(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符   
// fprintf(stream,lpString);   
// fclose(stream);   
 return TRUE;   
}   
///////////////////////////////////// H_TextOutW 函数 /////////////////////////////////////////   
//同上   
BOOL WINAPI H_TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpString,int cbString)   
{    
 MessageBox(NULL,"TextOutW","APIHook_Dll ---rivershan",MB_OK);   
 TextOutW(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符   
 return TRUE;   



设置全局钩子如下


  InstallHook(TRUE,0);