见过网上有很多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. 分布式项目中Spring security自定义权限类

    package cn.lijun.core.service; import cn.lijun.core.pojo.seller.Seller;import org.springframework.se ...

  2. django 工具类配置

    好久没发新博客,凑个数... django-debug-toolbar 介绍 django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面 ...

  3. 赋能时空云计算,阿里云数据库时空引擎Ganos上线

    随着移动互联网.位置感知技术.对地观测技术的快速发展,时空信息已从传统GIS行业渗透到大众应用及各行各业.从静态POI(兴趣点)到APP位置信息,从导航电子地图到车辆行驶轨迹,从卫星影像到三维城市建模 ...

  4. Java习题10.24

    Java习题10.24 1. 1,3.connect()与accept():这两个系统调用用于完成一个完整相关的建立,其中connect()用于建立连接.accept()用于使服务器等待来自某客户进程 ...

  5. robotframework悬浮菜单定位问题

      有些菜单是悬浮菜单,鼠标点上去下级元素才会显示.比如在第一个菜单中选择后会触发二级菜单的某事件,触发二级菜单又去点三级菜单.. 最开始就用click element去点击了,可是菜单会缩回去,就有 ...

  6. 10、TestNG 的 FixTrue用法一

    Fixture 是指一个测试运行所需的固定环境,通俗来说 ,为测试用例所准备的环境. 以下是TestNG中可用的注释及其属性的简要概述. 我们先演示@BeforeClass.@AfterClass.@ ...

  7. Linux文件映射的反思

    1. 思考 多个进程可以加载相同的共享链接库,比如C语言的运行库,加载运行库采用内存映射文件的方式,可以延迟对于文件内容的读入操作. 共享链接库文件,是一个elf格式的库文件,里面会包含多个不同的se ...

  8. C# WinForm 访问webService天气预报

    1.直接添加服务引用 右键引用 -->添加服务引用 这样的好处是可以直接当成类用 简单 麻烦的地方就是地址是死的 代码如下: private void button1_Click(object ...

  9. java-day20

    注解:说明程序的,给计算机看的 注释:用文字描述程序的,给程序员看的 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性.与类.接口.枚举是在 ...

  10. 防止DDOS攻击有效方法:隐藏服务器真实IP

    如今,网站服务器的安全受到越来越多的重视,但是难免会遇到黑客使用DDoS攻击网站,为了网站的安全通常都会做好防御,其中防止DDoS攻击有效方法:隐藏服务器真实IP ,该技术能够有效地保护网站的安全. ...