C++语法提高B-hook机制

Hook 机制

Hook 机制 是一种用于拦截和处理系统事件或函数调用的方法。通过 Hook 机制,程序可以在特定的事件发生时或函数调用之前、之后进行自定义操作。Hook 机制广泛应用于调试、性能监控、安全审计、功能扩展等领域。

Hook 机制的类型及实现方法

1. 消息 Hook

  • 主要用于拦截和处理操作系统的消息或事件。例如,在 Windows 操作系统中,应用程序可以通过设置消息 Hook 来截获窗口消息,以实现自定义的消息处理逻辑。

  • 在Windows 操作系统中,可以使用 SetWindowsHookEx 函数设置消息 Hook。下面是一个简单的示例:

#include <windows.h>HHOOK hHook;LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) {if (nCode >= 0) {// 处理钩住的消息if (wParam == WM_KEYDOWN) {KBDLLHOOKSTRUCT *kbd = (KBDLLHOOKSTRUCT *)lParam;printf("Key pressed: %d\n", kbd->vkCode);}}return CallNextHookEx(hHook, nCode, wParam, lParam);
}int main() {hHook = SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, NULL, 0);if (!hHook) {printf("Failed to install hook!\n");return 1;}MSG msg;while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);}UnhookWindowsHookEx(hHook);return 0;
}

2. API Hook(函数钩子)

  • 通过拦截和替换特定的 API 调用,实现自定义的功能。例如,拦截文件操作 API,实现文件操作监控和控制。

  • 以下是一个使用 dlsymdlfcn.h 库实现的示例,用于拦截 open 系统调用:

#include <dlfcn.h>	//用于动态链接库函数‘dlsym’
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>//定义一个函数指针类型‘open_pfn_t’,表示指向‘open’函数的指针
typedef int (*open_pfn_t)(const char *pathname, int flags);//定义一个全局变量存储系统函数指针
open_pfn_t g_sys_open_func = NULL;//这个宏用于动态获取系统函数的地址,并存储在相应的全局变量中
#define HOOK_SYS_FUNC(name) \
if( !g_sys_##name##_func ) { \g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT, #name); \
}//使用宏钩取 open 函数的地址
void hook_open_func() {HOOK_SYS_FUNC(open)if (g_sys_open_func) {printf("Successfully hooked open function.\n");} else {printf("Failed to hook open function.\n");}
}int main() {hook_open_func();//调用hook_open_func来钩取open函数// 使用钩取的函数来打开文件if (g_sys_open_func) {int fd = g_sys_open_func("test.txt", O_RDONLY);if (fd != -1) {printf("File descriptor: %d\n", fd);close(fd);} else {printf("Failed to open file.\n");}}return 0;
}
HOOK_SYS_FUNC解析
#define HOOK_SYS_FUNC(name) \		
if( !g_sys_##name##_func ) { \g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT, #name); \
}
  1. 宏参数name

    • 代表的是系统函数的名称,如openreadwrite
  2. 全局变量g_sys_##name##_func

    • 这是一个函数指针类型的全局变量,用于存储系统函数的地址。

    • ## 是预处理器连接符,用于将 name 与 g_sys_ 连接在一起形成变量名。

  3. 条件判断if( !g_sys_##name##_func )

    • 这部分代码检查全局变量 g_sys_##name##_func 是否为 NULL,即是否已经获取了函数地址。

    • 如果未获取(即变量为 NULL),则继续执行下面的代码。

  4. dlsym(RTLD_NEXT, #name)

    • dlsym是动态链接库的函数,用于在运行时获取符号(如函数或变量)的地址。

    • RTLD_NEXT 是一个特殊标志,表示从下一个共享对象中查找符号。

    • #name 将宏参数 name 转换为字符串,即函数的名称。

  5. 类型转换 (name##_pfn_t)

    • 将获取的地址转换为合适的函数指针类型。这里假设我们定义了 name##_pfn_t 作为函数指针类型。

3. 库 Hook

  • 通过拦截和替换动态链接库(DLL)中的函数调用,实现特定功能的扩展和定制。

  • 以下是一个使用 LD_PRELOAD 环境变量实现的示例,用于拦截和替换 malloc 函数:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>void *(*original_malloc)(size_t size) = NULL;void *malloc(size_t size) {if (!original_malloc) {original_malloc = dlsym(RTLD_NEXT, "malloc");}printf("malloc called with size: %zu\n", size);return original_malloc(size);
}__attribute__((constructor)) void init() {printf("Custom malloc hook initialized.\n");
}__attribute__((destructor)) void cleanup() {printf("Custom malloc hook cleaned up.\n");
}

Hook 机制的应用场景及示例

1. 调试和诊断

  • 无需修改源代码: 可以在不修改原始代码的情况下拦截并记录函数调用,方便调试和诊断问题。

  • 灵活性: 可以在运行时添加调试信息,查看函数调用的参数和返回值,了解程序的运行状况。

//调试文件系统操作,跟踪所有对‘open’函数的调用
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>typedef int (*open_pfn_t)(const char *pathname, int flags);
open_pfn_t g_sys_open_func = NULL;#define HOOK_SYS_FUNC(name) \
if( !g_sys_##name##_func ) { \g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT, #name); \
}int open(const char *pathname, int flags) {HOOK_SYS_FUNC(open)printf("Open called with pathname: %s\n", pathname);return g_sys_open_func(pathname, flags);
}int main() {int fd = open("test.txt", O_RDONLY);if (fd != -1) {printf("File descriptor: %d\n", fd);close(fd);} else {printf("Failed to open file.\n");}return 0;
}

2. 性能监控

  • 精细化监控: 可以监控特定函数的执行时间,找到性能瓶颈。

  • 运行时分析: 可以在生产环境中监控应用的性能,而无需停机或重新编译。

//监控函数执行时间
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>typedef int (*open_pfn_t)(const char *pathname, int flags);
open_pfn_t g_sys_open_func = NULL;#define HOOK_SYS_FUNC(name) \
if( !g_sys_##name##_func ) { \g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT, #name); \
}int open(const char *pathname, int flags) {HOOK_SYS_FUNC(open)clock_t start = clock();int result = g_sys_open_func(pathname, flags);clock_t end = clock();printf("Open called with pathname: %s, duration: %ld\n", pathname, end - start);return result;
}int main() {int fd = open("test.txt", O_RDONLY);if (fd != -1) {printf("File descriptor: %d\n", fd);close(fd);} else {printf("Failed to open file.\n");}return 0;
}

3. 安全监控

  • 安全审计: 可以在敏感操作(如文件操作、网络通信)前后添加安全检查,记录和防止非法访问。

  • 增强安全性: 可以在运行时动态拦截和修改不安全的函数调用,增强应用的安全性。

//在文件操作前后添加安全检查
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>typedef int (*open_pfn_t)(const char *pathname, int flags);
open_pfn_t g_sys_open_func = NULL;#define HOOK_SYS_FUNC(name) \
if( !g_sys_##name##_func ) { \g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT, #name); \
}int open(const char *pathname, int flags) {HOOK_SYS_FUNC(open)if (strcmp(pathname, "restricted.txt") == 0) {printf("Access to restricted file denied: %s\n", pathname);return -1;}return g_sys_open_func(pathname, flags);
}int main() {int fd = open("restricted.txt", O_RDONLY);if (fd != -1) {printf("File descriptor: %d\n", fd);close(fd);} else {printf("Failed to open file.\n");}return 0;
}

4. 动态行为定制

  • 热插拔功能: 可以在不停止应用的情况下添加或修改功能。例如,动态加载插件,实现可扩展的应用程序。

  • 库替换: 可以在运行时替换底层库,适应不同的实现需求。

5. 跨平台适配

  • 平台兼容性: 可以在运行时根据平台动态加载适配的系统函数,简化跨平台开发。

  • 版本兼容性: 可以在新版本软件中提供旧版本函数的兼容实现,确保旧版软件正常运行。

6. 插件系统

  • 模块化开发: 可以将功能划分为多个模块,在运行时动态加载和调用,实现模块化开发。

  • 灵活扩展: 可以通过插件系统扩展应用功能,提供更灵活的解决方案。

7. 错误恢复

  • 健壮性: 可以在函数调用失败时执行备用操作,提高程序的健壮性和容错能力。

优点和缺点

优点:

灵活性:可以在运行时动态拦截和修改函数调用,实现灵活的功能扩展和定制。

无侵入性:无需修改源代码,降低了修改现有代码的风险。

调试和诊断:有助于调试和诊断复杂问题,尤其是在生产环境中。

缺点:

复杂性:实现 Hook 机制需要较高的编程技巧和理解。

性能开销:可能会引入额外的性能开销,尤其是在高频率调用的函数上。

兼容性问题:在不同平台或不同版本的系统库上可能会有兼容性问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/45367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【启明智显分享】乐鑫HMI方案4.3寸触摸串口屏应用于称重测力控制仪表

称重测力控制仪表是将称重传感器信号&#xff08;或再通过重量变送器&#xff09;转换为重量数字显示&#xff0c;并可对重量数据进行传输、储存、统计、打印的电子设备&#xff0c;常用于工农业生产中的自动化配料&#xff0c;称重&#xff0c;以提高生产效率。随着工业化的发…

STM32F103RC使用HAL库对FLASH的擦除与写入

目录 STM32F103RC使用HAL库对FLASH的擦除与写入&#xff08;代码模块&#xff09; 一、芯片FLASH简介 二、FALSH的擦除 三、FALSH的写入 STM32F103RC使用HAL库对FLASH的擦除与写入&#xff08;代码模块&#xff09; 一、芯片FLASH简介 stm32f103rc芯片的flash大小为256KB&…

TC4056A 1A线性锂离子电池充电器芯片IC

产品描述 TC4056A是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器。其底部带有散热片的ESOP8/DIP8封装与较少的外部元件数目使得TC4056A成为便携式应用的理想选择TC4056A可以适合USB电源和适配器电源工作。 由于采用了内部PMOSFET架构&#xff0c;加…

《ElementUI/Plus 基础知识》el-tree 之修改可拖拽节点的高亮背景和线

前言 收到需求&#xff0c;PM 觉得可拖拽节点的高亮背景和线样式不明显&#xff01;CSS 样式得改&#xff01; 注意&#xff1a;下述方式适用于ElementUI el-tree 和 ElementPlus el-tree&#xff01; 修改 拖拽被叠加节点的背景色和文字 关键类名 is-drop-inner .el-tree…

从机器语言到现代编程语言的飞跃

在人类追求自动化与智能化的道路上&#xff0c;编程语言作为连接人类思维与计算机执行能力的桥梁&#xff0c;经历了从原始到现代的巨大飞跃。本文将带您穿越时间的长河&#xff0c;探索编程语言从最初的机器语言到如今多样化、高级化的演变历程。 机器语言与汇编语言&#xf…

C++语法提高A-字节对齐

字节对齐 字节对齐&#xff08;Byte Alignment&#xff09; 是计算机内存管理中的一个重要概念&#xff0c;指的是数据在内存中存储时&#xff0c;其地址应该是某个特定字节数的整数倍。不同的处理器和操作系统可能要求不同的对齐方式&#xff0c;以提高数据访问效率和保证正确…

Day02-ES集群常见术语,索引管理,文档管理,IK分词器,数据类型映射及kibana环境安装

Day02-ES集群常见术语&#xff0c;索引管理&#xff0c;文档管理&#xff0c;IK分词器&#xff0c;数据类型映射及kibana环境安装 1、昨日内容回顾2、今日内容预告3、ES的常见术语4、索引管理4.1 查看索引4.2 创建索引4.3 修改索引4.4 删除索引4.5 索引别名4.6 关闭索引4.7 打开…

C# AGV小车通讯开发的方法

AGV (Automated Guided Vehicle) 小车的通讯开发通常涉及与AGV控制系统或调度系统的数据交换。在C#中实现AGV小车通讯&#xff0c;可以采用多种方法&#xff0c;具体取决于AGV的通信协议和硬件接口。以下是一些常用的开发方法&#xff1a; 1. 串行通讯 (Serial Communication)…

FakeNewsGPT4:通过知识增强的大规模视觉语言模型推进多模态假新闻检测

FakeNewsGPT4: Advancing Multimodal Fake News Detection through Knowledge-Augmented LVLMs 1.概述 当前,多模态假新闻的大量涌现导致了显著的分布差异,这一现状亟需我们开发具备广泛适用性的检测器。然而,现有假新闻检测器因特定领域内的训练方式,难以有效获取开放世…

<数据集>Udacity交通目标识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;13239张&#xff08;实际有15000张&#xff0c;但其中1761张无标签的图片被我去除掉&#xff09; 标注数量(xml文件个数)&#xff1a;13239 标注数量(txt文件个数)&#xff1a;13239 标注类别数&#xff1a;11 标注…

护网--1

实验要求&#xff1a; 实现过程&#xff1a; &#xff08;一&#xff09;配置防火墙接口&#xff1a; 在防火墙上创建两个子接口&#xff1a;1/0/1.1 1/0/1.2 在浏览器上用视图界面配置接口&#xff1a; 到服务器&#xff1a; 到生产区&#xff1a; 到办公区&#xff1a; 到…

离线下载linux mysql和mysql基本库

下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 选择数据库版本&#xff0c;系统&#xff0c;系统版本信息 下载需要的rpm包&#xff0c;传入服务器&#xff0c;使用yum install xxx.rpm安装即可 mysql-community下载地址 https://dev.mysql.com/downloads/my…

专业无线麦克风品牌排行榜,无线麦克风哪个品牌音质最好

在数字化的浪潮中&#xff0c;个人创作与表达的舞台日益宽广。无论是专业的影像工匠、热情四溢的播客主播&#xff0c;亦或是生活点滴的记录者——Vlogger&#xff0c;一套卓越的音频装备是确保声音纯净、无瑕传递给观众的基石。无线领夹麦克风凭借其携带方便、操作简便以及卓越…

ai写作软件哪个好?亲测好用的5款工具分享

一眨眼&#xff0c;初伏就要到来了~办公室内的高温仿佛连空气都凝固了&#xff0c;键盘敲击声似乎都变得沉重而迟缓。在这样的天气下&#xff0c;创意与灵感似乎也躲进了阴凉处&#xff0c;办公效率显然大打折扣。 幸运的是&#xff0c;被我找到了新的应对之策&#xff0c;那便…

LINUX高级编程part2

var 123&#xff1b; echo &var 》 终端会自动打印出var的赋值即 123&#xff1b; shell变量&#xff1a; 环境变量 // 位置变量 //自定义变量 环境变量&#xff1a;&#xff08;env&#xff09; 环境指的是操作系统的环境。 env 会打印当前操作系统的所有环…

顺序表的应用之通讯录专题

顺序表的应用 1.基于动态顺序表实现通讯录&#xff1a; C语言基础要求&#xff1a; 结构体&#xff0c;动态内存管理&#xff0c;顺序表&#xff0c;文件操作 1.功能要求 1)至少能够存储100个人的通讯信息2)能够保存用户信息:名字、性别、年龄、电话、地址等3)增加联系人…

FastAPI 学习之路(四十七)WebSockets(三)登录后才可以聊天

之前我们是通过前端自动生成的token信息&#xff0c;这次我们通过注册登录&#xff0c;保存到本地去实现。首先&#xff0c;我们实现一个登录页面&#xff0c;放在templates目录下。 <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…

PHP单商户微店b2c商城微信小程序系统源码

打造专属线上购物空间&#x1f6cd;️ &#x1f680;【开篇&#xff1a;解锁新零售时代新风尚】&#x1f680; 在这个数字化飞速发展的时代&#xff0c;线上购物已成为我们日常生活不可或缺的一部分。对于单商户而言&#xff0c;拥有一个专属的B2C商城微信小程序&#xff0c;…

SHAP(SHapley Additive exPlanations)算法

SHAP&#xff08;SHapley Additive exPlanations&#xff09;算法是一种用于解释机器学习模型的方法&#xff0c;它基于博弈论中的 Shapley 值。 Shapley 值原本用于解决合作博弈中参与者对总收益贡献的分配问题。SHAP 算法将每个特征值对模型输出的贡献视为一种“公平”的分配…

【番外】Springboot集成推荐配置及十问RocketMQ

文章目录 Springboot推荐配置方式十问1. 为什么springboot系统集成只有一个producer&#xff0c;并集成到RocketMQTemplate里面&#xff1f;2. 为什么consumer必须要再额外使用一个MessageListener来处理消息&#xff1f;3. 一个系统只用一个producer和consumer可不可行&#x…