欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]金山快译的原理实现--全局钩子勾住textout

[分享]金山快译的原理实现--全局钩子勾住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;   

}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功