见过网上有很多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. 用记事本和Eclipse编写Java程序

    JRE(Java Runtime Environment    Java运行环境) 包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一 ...

  2. 11、for和range的用法

    // 27_range的使用 package main import ( "fmt" ) func main() { str := "abc" //通过for打 ...

  3. 【Web】Spring WebFlux

    阅读目录 一.关于WebFlux 二.SpringMVC与SpringWebFlux 三.Reactive Spring Web 四.实现WebFlux示例 SpringWebflux是SpringF ...

  4. Delphi 虚拟桌面

    Delphi创建虚拟桌面实现后台调用外部程序 核心提示:最近在做的一个软件,其中有一部分功能需要调用其它的软件来完成,而那个软件只有可执行文件,根本没有源代码,幸好,我要做的事不难,只需要在我的程序启 ...

  5. AcWing 286. 选课 (树形依赖分组背包)打卡

    有依赖的背包 首先依赖的概念,就是一个东西依附与一个东西之上,我们想买附品的话必须要把主品先买下来,这个可以先做下这道题 https://www.cnblogs.com/Lis-/p/11047466 ...

  6. php编译安装增加pdo扩展

    首先查看mysql版本和位置 mysql --version whereis mysql 去php安装目录安装扩展 cd /usr/local/src/php-5.4.25/ext/pdo_mysql ...

  7. 如何扫描统计全国Telnet默认口令

    如何扫描统计全国Telnet默认口令 zrools2016-01-21共339474人围观 ,发现 23 个不明物体系统安全终端安全 本文原创作者:zrools 本文中介绍的工具.技术带有一定的攻击性 ...

  8. HTTPS 加密原理探究

    由于之前项目中IOS系统建议将http协议换成https协议所以查看相关资料在此记录 HTTPS 通讯过程的基本原理 问:Https是什么? 答: HTTP 协议定义了一套规范,让客户端或浏览器可以和 ...

  9. 动态栈-------C语言

    使用带头结点的单链表实现 主要使用链表中的头插来实现栈的先进后出的特点 /***************************************************** Author:Si ...

  10. Ibatis sql语句1

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE sqlMap PUBLIC "-/ ...