Hook Function

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个字节恢复原样。

 

 

posted on 2008-12-02 12:41  cgwolver  阅读(2574)  评论(1编辑  收藏  举报

导航