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
// 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钩子类的更多相关文章
- C# 键盘钩子类
键盘钩子类代码如下 class globalKeyboardHook { #region Constant, Structure and Delegate Definitions /// <su ...
- C# 封装一个钩子类
利用C#设置钩子函数,并封装成类.如果想要实现全局钩子的话,必须将实现的代码封装到类库里. using System; using System.Collections.Generic; using ...
- c# 钩子类
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...
- 基于TP框架的ThinkCMF,控制器display方法源码分析
昨天在写代码的时候,看见写了无数次的模版渲染方法:$this->display(),突然很想弄清楚它是如何实现的. 今天不忙,就分析了一下. class TestController exten ...
- dbcp基本配置和重连配置 -- mysql 8小时自动断开连接的问题
1. 引入dbcp (选择1.4) Java代码 com.alibaba.external jakarta.commons.dbcp 1.4 2. dbcp的基本配置 相关配置说明: initia ...
- windows 勾子简介
近段时间因朋友催促让试着写一个监控系统,主要是用来管理孩子使用电脑,帮助孩子合理使用电脑.在网上查询了相关内容发现没有这方面的资料,所以只有自已来试试,要用到钩子来对windows应用程序进行监控,也 ...
- 解读dbcp自动重连那些事---转载
http://agapple.iteye.com/blog/791943 可以后另一篇做对比:http://agapple.iteye.com/blog/772507 同样的内容,不同的描述方式,不一 ...
- Windows消息拦截技术的应用
Windows消息拦截技术的应用 民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做 ...
- Windows消息拦截技术的应用(作者博客里有许多相关文章)
民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做适当的处理.处理完此次消息后又回到 ...
随机推荐
- Shell基本正则表达式和扩展正则表达式
BRE和ERE的区别 基本正则表达式(BRE)和扩展正则表达式(ERE)的区别仅仅是元字符(meta charactor)的区别而已. BRE: 只有^$.*[]是元字符 ERE: ^$.[]*+() ...
- Android逆向之smali语法宝典
0x01.前言 Android采用的是java语言进行开发,但是Android系统有自己的虚拟机Dalvik,代码编译最终不是采用的java的class,而是使用的smali.我们反编译得到的代码,j ...
- POJ 3805 Separate Points (判断凸包相交)
题目链接:POJ 3805 Problem Description Numbers of black and white points are placed on a plane. Let's ima ...
- spring 中 isolation 和 propagation 详解
可以在XML文件中进行配置,下面的代码是个示意代码 <tx:advice id="txAdvice" transaction-manager="txManager& ...
- HBase启动错误提示别的机器60000已经存在
已经用cm 安装好了cdh,需要在上面添加HBase,并且做一个HBase故障转移功能,现在需要配置2个HMaster 在不同的机器上. 启动出现异常信息: 2015-12-23 14:44:38, ...
- C语言之文件包含
c = #include <stdio.h> #include "A.h" int main() { /******************************** ...
- spring mvc 配置后,web中的html页面报404,该怎么处理
问题描述: 在根目录webapp下的jsp页面可以通过url直接访问,而html页面就会报404错误. 解决方案1: 在spring-mvc.xml中添加如下配置: <!--将静态文件指定到某个 ...
- boost asio tcp 多线程异步读写,服务器与客户端。
// server.cpp #if 0 多个线程对同一个io_service 对象处理 用到第三方库:log4cplus, google::protobuf 用到C++11的特性,Windows 需要 ...
- Sublime Text3中MarkDown的使用
前言 当我们想要在Sublime文本编辑器中编辑markdown时,需要先安装markdown插件,因为Sublime里默认没有安装该插件,同时在编辑markdown文本时可以实时预览编辑效果. 具体 ...
- JVM配置参数理解,Cannot load this JVM TI agent twice
基本参数 -Xms128m JVM初始分配的堆内存 -Xmx512m JVM最大允许分配的堆内存,按需分配 -XX:PermSize=64M JVM初始分配的非堆内存 -XX:MaxPermSize= ...