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

 

 

转载于:https://www.cnblogs.com/cgwolver/archive/2008/12/02/1345665.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,可以参考下面这段代码: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/unistd.h> #include <linux/syscalls.h> MODULE_LICENSE("GPL"); // 定义一个hook function,用于拦截open()系统调用 asmlinkage long (*original_open)(const char __user *filename, int flags, umode_t mode); asmlinkage long hooked_open(const char __user *filename, int flags, umode_t mode) { // 在这里添加你要执行的代码,比如打印日志等 printk(KERN_INFO "open() system call is hooked!\n"); // 调用原始的open()系统调用 return (*original_open)(filename, flags, mode); } // 在模块加载时进行hooking static int __init hook_init(void) { // 获取系统调用表 unsigned long *syscall_table = (unsigned long *)kallsyms_lookup_name("sys_call_table"); // 保存原始的open()系统调用,备用 original_open = (void *)syscall_table[__NR_open]; // 关闭写保护 write_cr0(read_cr0() & (~0x10000)); // 替换open()系统调用 syscall_table[__NR_open] = (unsigned long)hooked_open; // 开启写保护 write_cr0(read_cr0() | 0x10000); printk(KERN_INFO "Hooking open() system call...\n"); return 0; } // 在模块卸载时取消hooking static void __exit hook_cleanup(void) { // 获取系统调用表 unsigned long *syscall_table = (unsigned long *)kallsyms_lookup_name("sys_call_table"); // 关闭写保护 write_cr0(read_cr0() & (~0x10000)); // 恢复原始的open()系统调用 syscall_table[__NR_open] = (unsigned long)original_open; // 开启写保护 write_cr0(read_cr0() | 0x10000); printk(KERN_INFO "Unhooking open() system call...\n"); } module_init(hook_init); module_exit(hook_cleanup); ``` 这段代码实现了在用户空间定义一个hook function `hooked_open()`,用于拦截系统调用`open()`,并在内核空间进行调用,在模块加载时进行hooking,在模块卸载时取消hooking。需要注意的是,为了进行hooking,需要关闭写保护,即将CR0寄存器的第16位清零,使得可以修改系统调用表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值