见过网上有很多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. 锐浪报表 Grid++Report 一维码无法固定条形码打印宽度

    使用过 锐浪报表的 程序员 都知道,功能很强大,确实带来了很多便利,但今天发现一个问题,关于一维码的条形码无法固定宽度: 打印相差了0.07毫米,居然差别这么大, 打印出来的条码,要么太宽,要么太窄 ...

  2. SpringDataRedis依赖

    <dependencies>        <dependency>            <groupId>junit</groupId>       ...

  3. 阿里云高磊:API网关加速能力聚合与生态集成

    导读:本文中,阿里云高级技术专家高磊(花名:埃兰)将聚焦API网关加速能力聚合与生态集成,讲述API如何实现系统间的衔接和API网关的产品升级进程,重点展示了一些新功能.新体验和新变化. 大家下午好, ...

  4. 【LeetCode 16】最接近的三数之和

    题目链接 [题解] 上一道题那个算法求三个数的和为0的时候,其实就是一个不断在逼近本题中x=0的情况. 那么就套用上面那道题的做法. 在逼近的时候,取个差值的最小值就好了. [代码] class So ...

  5. PXE预启动执行环境的搭建

    搭建DHCP地址服务器 DHCP地址分配的四次会话:(广播形式)[先到先得]    Discovery---->Offer---->Request---->Ack 一个局域网内不能同 ...

  6. [bzoj2839]集合计数 题解 (组合数+容斥)

    Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取法的方案数,答案模1000000007 ...

  7. Jeecg集成Swagger-ui

    <context:component-scan base-package="springfox"/> <bean class="org.jeecgfra ...

  8. 将某个Qt4项目升级到Qt5遇到的问题

    本文转载自http://hi.baidu.com/xchinux/item/9044d8ce986accbb0d0a7b87 一.将某个QT4项目改成QT5遇到的问题 该Qt4项目以前是使用Qt4.7 ...

  9. testNG官方文档翻译-1 简介

    官方文档链接http://testng.org/doc/documentation-main.html 简介 TestNG是一个被设计用来简化广泛的测试需求的测试框架,它既可应用于单元测试(测试一个独 ...

  10. centos7下利用nfs搭建wordpress

    拓扑环境 web1 192.168.198.110 web2 192.168.198.120 mysql 192.168.198.130 DNS 192.168.198.10 NFS 192.168. ...