• CApiHook__Api钩子类


    见过网上有很多ApiHook的类,但是都不尽入人意,要么就是写的不够好不够完善,要么就是跑不起来.

    用别人写的代码总是有种不安心,所以自己就花了一晚上写了CApiHook类.已经尽量确保自己写的类是非常完善的.

    //20151208稍微改变了一下ApiHook的逻辑,重写GetApiHookStatus函数并重命名为GetProcHookStatus,

      并且很认真负责的测试了WinXP x86/Win7 x86/Win7 x64/Win8.1 x64系统下的GetProcHookStatus有效性.

    //20150728稍微改进了一下ApiHook的稳定性,和增加了一个检测系统Api Hook状态的函数GetApiHookStatus

    //编写和测试环境: Microsoft Visual Studio 2015 Enterprise RC / Microsoft Windows 7 Ultimate x86

     1 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208
     2 
     3 #pragma once
     4 
     5 #ifndef __CAPIHOOK_H__
     6 #define __CAPIHOOK_H__
     7 
     8 #include <cstdio>
     9 #include <windows.h>
    10 
    11 using namespace std;
    12 
    13 class CApiHook
    14 {
    15 private:
    16     BOOL bStatus;        //    当前钩子状态
    17     BOOL bSuspend;        //    当前钩子暂停状态
    18     HMODULE hModule;    //    目标函数所在的动态链接库的句柄
    19     LPVOID lpProc;        //    目标函数地址
    20     LPVOID lpBaseAddr;    //    目标函数基地址
    21     LPVOID lpNewProc;    //    新函数地址
    22     BYTE bRawData[5];    //    目标函数原数据
    23     BYTE bJMPStmt[5];    //    JMP指令语句
    24     
    25     BOOL WriteData(LPCVOID lpBuffer);    //    将缓冲区内容写入目标函数地址
    26 
    27 public:
    28     CApiHook();
    29     ~CApiHook();
    30 
    31     BOOL Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC pNewProc);    //    初始化钩子
    32     BOOL Suspend();    //    暂停钩子
    33     BOOL Resume();    //    恢复钩子
    34     BOOL Uninstall();    //    卸载钩子
    35 
    36     BOOL GetHookStatus();
    37 };
    38 
    39 BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName);    //    获取目标函数的钩子状态
    40 
    41 #endif    //    __CAPIHOOK_H__
    CApiHook.h
      1 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208
      2 
      3 #include "CApiHook.h"
      4 
      5 CApiHook::CApiHook()
      6 {
      7     memset(this, 0, sizeof(CApiHook));
      8 }
      9 
     10 CApiHook::~CApiHook()
     11 {
     12     if (bStatus)
     13         Uninstall();
     14 }
     15 
     16 //    将缓冲区内容写入目标函数地址
     17 BOOL CApiHook::WriteData(LPCVOID lpBuffer)
     18 {
     19     //    更改目标函数基地址的保护状态为可读写
     20     DWORD dwOldProtect;
     21     if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, 5, PAGE_READWRITE, &dwOldProtect))
     22         return FALSE;
     23 
     24     //    将缓冲区内容写入目标函数地址
     25     if (!WriteProcessMemory(GetCurrentProcess(), lpProc, lpBuffer, 5, NULL))
     26         return FALSE;
     27 
     28     //    恢复目标函数基地址的保护状态
     29     if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, 5, dwOldProtect, &dwOldProtect))
     30         return FALSE;
     31 
     32     return TRUE;
     33 }
     34 
     35 //    初始化钩子
     36 BOOL CApiHook::Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC fpNewProc)
     37 {
     38     if (bStatus)
     39         return FALSE;
     40 
     41     //    获取目标函数所在的动态链接库的句柄
     42     hModule = GetModuleHandleA(szModuleName);
     43     if (NULL == hModule)
     44         hModule = LoadLibraryA(szModuleName);
     45     if (NULL == hModule)
     46         return FALSE;
     47 
     48     lpNewProc = (LPVOID)fpNewProc;    //    获取新函数地址
     49     lpProc = (LPVOID)GetProcAddress(hModule, szProcName);    //    获取目标函数地址
     50     if (NULL == lpNewProc || NULL == lpProc)
     51         return FALSE;
     52 
     53     //    获取并保存目标函数地址的原数据
     54     RtlMoveMemory(bRawData, lpProc, 5);
     55 
     56     //    构造JMP指令语句
     57     bJMPStmt[0] = 0xE9;    //    JMP指令
     58     *((PDWORD)(&(bJMPStmt[1]))) = (DWORD)lpNewProc - (DWORD)lpProc - 5;
     59 
     60     //    获取目标函数基地址
     61     MEMORY_BASIC_INFORMATION mbi = {};
     62     if (sizeof(mbi) != VirtualQueryEx(GetCurrentProcess(), lpProc, &mbi, sizeof(mbi)))
     63         return FALSE;
     64     lpBaseAddr = mbi.BaseAddress;
     65 
     66     //    将JMP指令语句写入目标函数地址
     67     if (!WriteData(bJMPStmt))
     68         return FALSE;
     69 
     70     bStatus = TRUE;
     71 
     72     return TRUE;
     73 }
     74 
     75 //    暂停钩子
     76 BOOL CApiHook::Suspend()
     77 {
     78     if (!bStatus || bSuspend)
     79         return FALSE;
     80 
     81     //    将目标函数原数据写入目标函数地址
     82     BOOL ret = WriteData(bRawData);
     83     if (!ret)
     84         return FALSE;
     85 
     86     bSuspend = TRUE;
     87 
     88     return TRUE;
     89 }
     90 
     91 //    恢复钩子
     92 BOOL CApiHook::Resume()
     93 {
     94     if (!bStatus || !bSuspend)
     95         return FALSE;
     96 
     97     //    将JMP指令语句写入目标函数地址
     98     BOOL ret = WriteData(bJMPStmt);
     99     if (!ret)
    100         return FALSE;
    101 
    102     bSuspend = FALSE;
    103 
    104     return TRUE;
    105 }
    106 
    107 //    卸载钩子
    108 BOOL CApiHook::Uninstall()
    109 {
    110     if (!bStatus)
    111         return FALSE;
    112 
    113     //    将目标函数原数据写入目标函数地址
    114     if (!WriteData(bRawData))
    115         return FALSE;
    116 
    117     if (hModule != NULL)
    118         FreeLibrary(hModule);
    119     memset(this, 0, sizeof(*this));
    120 
    121     return TRUE;
    122 }
    123 
    124 BOOL CApiHook::GetHookStatus()
    125 {
    126     return bStatus;
    127 }
    128 
    129 //    获取目标函数的钩子状态
    130 //    该函数暂仅对在WinXPx86/Win7x86/Win7x64/Win8.1x64下的ntdll.dll/kernel32.dll/user32.dll负责
    131 BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName)
    132 {
    133     //    获取目标函数所在的动态链接库的句柄
    134     HMODULE hModule = GetModuleHandleA(lpModuleName);
    135     if (hModule == NULL)
    136         hModule = LoadLibraryA(lpModuleName);
    137     if (hModule == NULL)
    138         return ERROR;
    139 
    140     //    获取目标函数的地址
    141     FARPROC fpProc = GetProcAddress(hModule, lpProcName);
    142     if (fpProc == NULL)
    143         return ERROR;
    144 
    145     //    获取目标函数地址的前7字节
    146     BYTE buf[7] = {};
    147     if (!ReadProcessMemory(GetCurrentProcess(), fpProc, &buf, 7, NULL))
    148         return ERROR;
    149 
    150     /*
    151     E9
    152     B8 XX XX XX XX FF E0
    153 
    154     例外
    155     E9 XX XX XX 00
    156     E9 XX XX XX FA
    157     E9 XX XX XX FC
    158     E9 XX XX XX FF
    159     E9 XX XX XX XX 90
    160     */
    161 
    162     //    判断前7字节是否存在JMP/MOV指令语句并排除例外
    163     if ((buf[0] == 0xB8 && buf[5] == 0xFF && buf[6] == 0xE0) ||
    164         (buf[0] == 0xE9 && buf[4] != 0x00 && buf[4] != 0xFA && buf[4] != 0xFC && buf[4] != 0xFF && buf[5] != 0x90))
    165         return TRUE;
    166 
    167     return FALSE;
    168 }
    CApiHook.cpp
     1 #include <cstdio>
     2 #include <windows.h>
     3 
     4 #include "CApiHook.h"
     5 
     6 CApiHook HookMessageBoxA;
     7 
     8 int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
     9 {
    10     printf("PAY ATTENTION!! FOUND CALLING : MessageBoxA(%d, \"%s\", \"%s\", %d)\n", hWnd, lpText, lpCaption, uType);
    11 
    12     char cText[MAX_PATH];
    13     strcpy(cText, lpText);
    14     strcat(cText, " [Hijack]");
    15 
    16     char cCaption[MAX_PATH];
    17     strcpy(cCaption, lpCaption);
    18     strcat(cCaption, " [Hijack]");
    19 
    20     HookMessageBoxA.Suspend();
    21 
    22     int ret = MessageBoxA(NULL, cText, cCaption, MB_ICONERROR);
    23 
    24     HookMessageBoxA.Resume();
    25 
    26     return ret;
    27 }
    28 
    29 int main()
    30 {
    31     MessageBoxA(NULL, "Text1", "Caption1", MB_ICONINFORMATION);
    32 
    33     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
    34     HookMessageBoxA.Install("User32.dll", "MessageBoxA", (FARPROC)NewMessageBoxA);
    35     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
    36 
    37     MessageBoxA(NULL, "Text2", "Caption2", MB_ICONINFORMATION);
    38 
    39     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
    40     HookMessageBoxA.Uninstall();
    41     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
    42 
    43     MessageBoxA(NULL, "Text3", "Caption3", MB_ICONINFORMATION);
    44 
    45     system("pause > nul");
    46     return 0;
    47 }
    main.cpp
  • 相关阅读:
    webpack前端构建工具学习总结(一)之webpack安装、创建项目
    当执行 import vue from 'vue' 时发生了什么?
    WEBSTORM新建VUE类型文件设置
    基于vue-cli搭建HelloWorld项目
    vue-cli脚手架安装
    浏览器的重绘和回流
    strcpy和strncpy用法和区别
    &与&&有什么区别?
    状态机实践入门
    12864点阵液晶显示模块的原理和实例程序(HJ12864M-1)
  • 原文地址:https://www.cnblogs.com/gwsbhqt/p/4612233.html
Copyright © 2020-2023  润新知