Hook Function... 貌似Hacker/Cracker做的事情,不过我既不是Hacker,也不是Cracker,而是Game Programer...Game Programer,不仅要通晓图形图像,数学物理,貌似十八般武器,左道旁门都要耍一耍。今天,我也根据自己的实验过程,写一些Hook 方法,请各位大牛多批评指正。。。

本次Hook Function 的研究动因来自于对Memroy Alloction Function接管的需求;

[第一种方法]:(Override IAT),就是通常所说的Hook API,只得是对DLL中的导出函数进行Hook,Hook的方法就是重写IAT(Import Address Table)中的相应条目;

下面代码我忘记抄的哪一位的了,自己认领吧..详细解释网上很多,自己google吧,我对这个函数稍作了改进,可以挂接dll中引入的api,比如mscvr80.dll中引用的kernel32 中的API。

这种方法只适用于挂接dll中的可导出函数(如果你能找到dll对应的def文件,或者dumpbin 它就知道哪些函数是导出函数了 ),挂接msvcrt 中的函数,不能对msvcrt.dll操作(早期版本也许可以);而是对新版本crt dll,比如vc8 的 msvcr80.dll;如何有效的找到对应版本的crt dll?这个问题我还不清楚。跟踪crt source,发现_CRT_DLL_INIT是ntdll中的函数控制的...

另外,如果要注入其他进程,需要放到dll。。。

这种方法的缺点是无法挂接静态连接的函数。

void WINAPI HookOneAPI( HMODULE hInstance,LPCTSTR ModuleName,LPCTSTR ApiName,PROC NewFuction,PROC* OldFuction)
 {
      DWORD size;     HMODULE hModule = GetModuleHandle(ModuleName);
      PROC HookAPIAddr = GetProcAddress( hModule,ApiName);
      *OldFuction = HookAPIAddr;
      PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)   ImageDirectoryEntryToData (hInstance,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
      PIMAGE_IMPORT_DESCRIPTOR pImportDesc1 = pImportDesc;   
      if(pImportDesc == NULL)
           return;
     
      for (;pImportDesc1->Name;pImportDesc1++)
      {
           LPSTR pszDllName = (LPSTR)((PBYTE)hInstance + pImportDesc1->Name);
           if(lstrcmpiA(pszDllName,ModuleName) == 0)
           {
                //break;
                pImportDesc = pImportDesc1;
           }
           else
           {
                HMODULE hModule1 = GetModuleHandle(pszDllName);
                HookOneAPI( hModule1,ModuleName,ApiName,NewFuction,OldFuction );
           }
      }     if(pImportDesc->Name == NULL)
           return;
     
      PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hInstance + pImportDesc->FirstThunk);//IAT
    
      for(;pThunk->u1.Function;pThunk++)
      {
           PROC * ppfn= (PROC *)&pThunk->u1.Function;
           if (*ppfn == HookAPIAddr)
           {
                MEMORY_BASIC_INFORMATION mbi;
                ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
                VirtualQuery(ppfn,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
                VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect);
                *ppfn = NewFuction;
                DWORD dwOldProtect;
                VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
                return;
           }
      }
 }

[第二种方法]:改写函数起始指令

这种方法可以有效地处理静态连接的函数,包括exe代码中的函数和exe所连接静态lib中的函数;但是对于dll所链接的静态lib函数的hook,如果没有source比较困难;除非把分析代码段多有的call指令,然后改写。

以下代码参考多任务下的数据结构与算法改编( 周伟明 著 华中科技大学出版社 ),vc8 编译测试通过。

对于静态链接的函数


void HookFunction( void* pfunc,void* pfun_new_var ) 
  
 { 
  
       DWORD lpSrcFunc = (DWORD)pfunc; 
  
 
      HANDLE hProcess = ::GetCurrentProcess();
       unsigned char buff[256];
       buff[0] = 0xff;
       buff[1] = 0x25;
       *(DWORD*)(buff+2) = (DWORD)pfun_new_var;
       DWORD write_bytes = 0;
       ::WriteProcessMemory( hProcess,(PROC*)lpSrcFunc,buff,6,&write_bytes );
 }//new handler for malloc
void* __cdecl malloc_new( __in size_t _Size )
{
     ...
}
//test code:
      HMODULE handle = ::GetModuleHandle(NULL);
 #ifdef _MT
 #    ifdef _DLL // for crt dll
      HookOneAPI(handle,"msvcr80d.dll","malloc",(PROC)malloc_new,(PROC*)&malloc_old);
 #else // for static crt lib
      static DWORD dwNewFunc1 = (DWORD)malloc_new;
      HookFunction( malloc,&dwNewFunc1 ); // don‘t use direct function addr malloc_new!
 #    endif
 #endif
      malloc(10);

如果还要恢复原函数的运行,就需要预先储存前面6个字节;在新的函数执行完以后,将修改的前6个字节恢复原样。