见过网上有很多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

 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208

 #pragma once

 #ifndef __CAPIHOOK_H__
#define __CAPIHOOK_H__ #include <cstdio>
#include <windows.h> using namespace std; class CApiHook
{
private:
BOOL bStatus; // 当前钩子状态
BOOL bSuspend; // 当前钩子暂停状态
HMODULE hModule; // 目标函数所在的动态链接库的句柄
LPVOID lpProc; // 目标函数地址
LPVOID lpBaseAddr; // 目标函数基地址
LPVOID lpNewProc; // 新函数地址
BYTE bRawData[]; // 目标函数原数据
BYTE bJMPStmt[]; // JMP指令语句 BOOL WriteData(LPCVOID lpBuffer); // 将缓冲区内容写入目标函数地址 public:
CApiHook();
~CApiHook(); BOOL Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC pNewProc); // 初始化钩子
BOOL Suspend(); // 暂停钩子
BOOL Resume(); // 恢复钩子
BOOL Uninstall(); // 卸载钩子 BOOL GetHookStatus();
}; BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName); // 获取目标函数的钩子状态 #endif // __CAPIHOOK_H__

CApiHook.h

 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208

 #include "CApiHook.h"

 CApiHook::CApiHook()
{
memset(this, , sizeof(CApiHook));
} CApiHook::~CApiHook()
{
if (bStatus)
Uninstall();
} // 将缓冲区内容写入目标函数地址
BOOL CApiHook::WriteData(LPCVOID lpBuffer)
{
// 更改目标函数基地址的保护状态为可读写
DWORD dwOldProtect;
if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, , PAGE_READWRITE, &dwOldProtect))
return FALSE; // 将缓冲区内容写入目标函数地址
if (!WriteProcessMemory(GetCurrentProcess(), lpProc, lpBuffer, , NULL))
return FALSE; // 恢复目标函数基地址的保护状态
if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, , dwOldProtect, &dwOldProtect))
return FALSE; return TRUE;
} // 初始化钩子
BOOL CApiHook::Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC fpNewProc)
{
if (bStatus)
return FALSE; // 获取目标函数所在的动态链接库的句柄
hModule = GetModuleHandleA(szModuleName);
if (NULL == hModule)
hModule = LoadLibraryA(szModuleName);
if (NULL == hModule)
return FALSE; lpNewProc = (LPVOID)fpNewProc; // 获取新函数地址
lpProc = (LPVOID)GetProcAddress(hModule, szProcName); // 获取目标函数地址
if (NULL == lpNewProc || NULL == lpProc)
return FALSE; // 获取并保存目标函数地址的原数据
RtlMoveMemory(bRawData, lpProc, ); // 构造JMP指令语句
bJMPStmt[] = 0xE9; // JMP指令
*((PDWORD)(&(bJMPStmt[]))) = (DWORD)lpNewProc - (DWORD)lpProc - ; // 获取目标函数基地址
MEMORY_BASIC_INFORMATION mbi = {};
if (sizeof(mbi) != VirtualQueryEx(GetCurrentProcess(), lpProc, &mbi, sizeof(mbi)))
return FALSE;
lpBaseAddr = mbi.BaseAddress; // 将JMP指令语句写入目标函数地址
if (!WriteData(bJMPStmt))
return FALSE; bStatus = TRUE; return TRUE;
} // 暂停钩子
BOOL CApiHook::Suspend()
{
if (!bStatus || bSuspend)
return FALSE; // 将目标函数原数据写入目标函数地址
BOOL ret = WriteData(bRawData);
if (!ret)
return FALSE; bSuspend = TRUE; return TRUE;
} // 恢复钩子
BOOL CApiHook::Resume()
{
if (!bStatus || !bSuspend)
return FALSE; // 将JMP指令语句写入目标函数地址
BOOL ret = WriteData(bJMPStmt);
if (!ret)
return FALSE; bSuspend = FALSE; return TRUE;
} // 卸载钩子
BOOL CApiHook::Uninstall()
{
if (!bStatus)
return FALSE; // 将目标函数原数据写入目标函数地址
if (!WriteData(bRawData))
return FALSE; if (hModule != NULL)
FreeLibrary(hModule);
memset(this, , sizeof(*this)); return TRUE;
} BOOL CApiHook::GetHookStatus()
{
return bStatus;
} // 获取目标函数的钩子状态
// 该函数暂仅对在WinXPx86/Win7x86/Win7x64/Win8.1x64下的ntdll.dll/kernel32.dll/user32.dll负责
BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName)
{
// 获取目标函数所在的动态链接库的句柄
HMODULE hModule = GetModuleHandleA(lpModuleName);
if (hModule == NULL)
hModule = LoadLibraryA(lpModuleName);
if (hModule == NULL)
return ERROR; // 获取目标函数的地址
FARPROC fpProc = GetProcAddress(hModule, lpProcName);
if (fpProc == NULL)
return ERROR; // 获取目标函数地址的前7字节
BYTE buf[] = {};
if (!ReadProcessMemory(GetCurrentProcess(), fpProc, &buf, , NULL))
return ERROR; /*
E9
B8 XX XX XX XX FF E0 例外
E9 XX XX XX 00
E9 XX XX XX FA
E9 XX XX XX FC
E9 XX XX XX FF
E9 XX XX XX XX 90
*/ // 判断前7字节是否存在JMP/MOV指令语句并排除例外
if ((buf[] == 0xB8 && buf[] == 0xFF && buf[] == 0xE0) ||
(buf[] == 0xE9 && buf[] != 0x00 && buf[] != 0xFA && buf[] != 0xFC && buf[] != 0xFF && buf[] != 0x90))
return TRUE; return FALSE;
}

CApiHook.cpp

 #include <cstdio>
#include <windows.h> #include "CApiHook.h" CApiHook HookMessageBoxA; int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
printf("PAY ATTENTION!! FOUND CALLING : MessageBoxA(%d, \"%s\", \"%s\", %d)\n", hWnd, lpText, lpCaption, uType); char cText[MAX_PATH];
strcpy(cText, lpText);
strcat(cText, " [Hijack]"); char cCaption[MAX_PATH];
strcpy(cCaption, lpCaption);
strcat(cCaption, " [Hijack]"); HookMessageBoxA.Suspend(); int ret = MessageBoxA(NULL, cText, cCaption, MB_ICONERROR); HookMessageBoxA.Resume(); return ret;
} int main()
{
MessageBoxA(NULL, "Text1", "Caption1", MB_ICONINFORMATION); printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
HookMessageBoxA.Install("User32.dll", "MessageBoxA", (FARPROC)NewMessageBoxA);
printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO"); MessageBoxA(NULL, "Text2", "Caption2", MB_ICONINFORMATION); printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
HookMessageBoxA.Uninstall();
printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO"); MessageBoxA(NULL, "Text3", "Caption3", MB_ICONINFORMATION); system("pause > nul");
return ;
}

main.cpp

CApiHook__Api钩子类的更多相关文章

  1. C# 键盘钩子类

    键盘钩子类代码如下 class globalKeyboardHook { #region Constant, Structure and Delegate Definitions /// <su ...

  2. C# 封装一个钩子类

    利用C#设置钩子函数,并封装成类.如果想要实现全局钩子的话,必须将实现的代码封装到类库里. using System; using System.Collections.Generic; using ...

  3. c# 钩子类

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  4. 基于TP框架的ThinkCMF,控制器display方法源码分析

    昨天在写代码的时候,看见写了无数次的模版渲染方法:$this->display(),突然很想弄清楚它是如何实现的. 今天不忙,就分析了一下. class TestController exten ...

  5. dbcp基本配置和重连配置 -- mysql 8小时自动断开连接的问题

    1. 引入dbcp (选择1.4) Java代码   com.alibaba.external jakarta.commons.dbcp 1.4 2. dbcp的基本配置 相关配置说明: initia ...

  6. windows 勾子简介

    近段时间因朋友催促让试着写一个监控系统,主要是用来管理孩子使用电脑,帮助孩子合理使用电脑.在网上查询了相关内容发现没有这方面的资料,所以只有自已来试试,要用到钩子来对windows应用程序进行监控,也 ...

  7. 解读dbcp自动重连那些事---转载

    http://agapple.iteye.com/blog/791943 可以后另一篇做对比:http://agapple.iteye.com/blog/772507 同样的内容,不同的描述方式,不一 ...

  8. Windows消息拦截技术的应用

    Windows消息拦截技术的应用 民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做 ...

  9. Windows消息拦截技术的应用(作者博客里有许多相关文章)

    民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做适当的处理.处理完此次消息后又回到 ...

随机推荐

  1. cmake build

    { //cmake CMakeLists.txt -G "Visual Studio 15 2017" }

  2. C#中的类型相等与恒等(Equality & Identity)

    l  Equality:如果两个对象是相同的类型,并且它们各自带有相同和等值的属性.(They are instances of the same type and if each of the fi ...

  3. PHP ftp_cdup() 函数

    定义和用法 ftp_cdup() 函数把当前目录改变为 FTP 服务器上的父目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_cdup(ftp_connection ...

  4. error C2872: “ACCESS_MASK”: 不明确的符号

    原因:opencv3.0或者3.1的using namespace cv和windows.h中ACCESS_MASK定义冲突. 解决方案:注释掉所有的using namespace cv,然后在需要的 ...

  5. Springboot Excle导入导出

    Springboot Excle导入导出 导入操作:Excle批量导入 导出操作:下载模版 开发笔记 pom.xml <!-- Excle相关jar --> <dependency& ...

  6. 2019 ACM/ICPC Asia Regional shanxia D Miku and Generals (二分图黑白染色+01背包)

    Miku is matchless in the world!” As everyone knows, Nakano Miku is interested in Japanese generals, ...

  7. Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

    题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l, ...

  8. mac下nginx

    配置文件位置 /usr/local/etc/nginx/nginx.conf 简单命令 nginx -s quit 退出 nginx -s reload 重新加载 nginx -t 测试nginx.c ...

  9. ASP.NET CORE-Info:TechEmpower最新一轮的性能测试出炉,ASP.NET Core依旧表现不俗

    ylbtech-ASP.NET CORE-Info:TechEmpower最新一轮的性能测试出炉,ASP.NET Core依旧表现不俗 1.返回顶部 1. TechEmpower在10月30发布最新一 ...

  10. XML 扩展部分

    引入命名空间 xmlns DTD缺点 1.不支持命名空间 2.支持的数据类型很少 3.DTD不可扩展 4.DTD不遵循XML规范 DTD的优点 简洁 schema 通过schema来解决DTD的不足 ...