Hook.cpp
上传用户:yitai_qhd
上传日期:2008-04-24
资源大小:31k
文件大小:3k
开发平台:

Visual C++

  1. #include <windows.h>
  2. #include <winnt.h>
  3. #include "hook.h"
  4. unsigned long SAVECR0 = 0;
  5. // 禁用Windows NT/2000的内存保护,使只读内存区可写
  6. //
  7. void DisableProtection() 
  8. {
  9.     __asm
  10.     {
  11.         mov eax,cr0 
  12.         mov SAVECR0,eax 
  13.         and eax,0fffeffffh 
  14.         mov cr0,eax 
  15.     }
  16. }
  17. //
  18. // 启用Windows NT/2000的内存保护
  19. //
  20. void EnableProtection()
  21. {
  22.     __asm
  23.     {
  24.         mov eax,SAVECR0 
  25.         mov cr0,eax 
  26.     }
  27. }
  28. //
  29. // Hook 一个系统函数
  30. // 参数:
  31. //     pBaseAddress: 要Hook函数所在文件在内存映象的基地址,比如NDIS.SYS的基地址
  32. //     Name: 要Hook的函数名
  33. //     InFunc: 自己的函数地址
  34. //     OutFunc: Hook后保存系统的函数地址
  35. // 返回值:
  36. //     NULL: Hook失败
  37. //     Not NULL: 返回系统函数地址,与*OutFunc相同
  38. //
  39. //
  40. PVOID HookFun(PVOID pBaseAddress, PCSTR Name, PVOID InFunc, ULONG* OutFunc)
  41. {
  42. //以下是PE文件中的结构
  43.     PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS EXE文件头结构
  44.     PIMAGE_NT_HEADERS pNtHeader = NULL;//PE文件头结构
  45.     PIMAGE_DATA_DIRECTORY pDirectory = NULL;//
  46.     PIMAGE_EXPORT_DIRECTORY pExports = NULL;//导出表结构
  47.     ULONG nSize, Address, i;
  48.     PULONG pFunctions = NULL;
  49.     PSHORT pOrdinals = NULL;
  50.     PULONG pNames = NULL;
  51.     PVOID pFunction = NULL;
  52.     ULONG Ordinal = 0;
  53.     if(pBaseAddress == NULL)
  54.         return NULL;
  55.     pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
  56.     pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pBaseAddress + pDosHeader->e_lfanew);//定位到PE文件头开始地址
  57.     pDirectory = pNtHeader->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;// 指向IMAGE_DIRECTORY_ENTRY_EXPORT开始处
  58.     nSize = pDirectory->Size;
  59.     Address = pDirectory->VirtualAddress;
  60.     pExports = (PIMAGE_EXPORT_DIRECTORY)((PCHAR)pBaseAddress + Address);//定位到导出表开始处
  61.     pFunctions = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfFunctions);//得到导出函数地址
  62.     pOrdinals = (PSHORT)((PCHAR)pBaseAddress + pExports->AddressOfNameOrdinals);//得到AddressOfNameOrdinals(RVA)
  63.     pNames = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfNames);//得到函数名
  64.     for(i = 0; i < pExports->NumberOfNames; i++)//开始查找
  65.     {
  66.         Ordinal = pOrdinals[i];
  67.         if(pFunctions[Ordinal] < Address || pFunctions[Ordinal] >= Address + nSize)
  68.         {
  69.             if(strcmp((PSTR)((PCHAR)pBaseAddress + pNames[i]), Name) == 0)
  70.             {
  71.                 //
  72.                 // 得到系统函数的地址
  73.                 //
  74.                 pFunction = (PCHAR)pBaseAddress + pFunctions[Ordinal];
  75.                 *OutFunc = (ULONG)pFunction;
  76.                 // 去除Windows内存保护
  77.                 //
  78.                 DisableProtection();
  79.                 // 这里需要修改系统内存数据。
  80.                 // 计算出自己函数地址的偏移量,并替换导出表中的偏移量
  81.                 //
  82.                 pFunctions[Ordinal] = (ULONG)((ULONG)InFunc - (ULONG)pBaseAddress);
  83.                 // 恢复Windows内存保护
  84.                 //
  85.                 EnableProtection();
  86.                 break;
  87.             }
  88.         }
  89.     }
  90.     return pFunction;
  91. }