当前位置: 首页 > news >正文

实战分享:用Kprobe和Jprobe在Ubuntu 22.04上安全地Hook内核函数(附完整代码)

实战分享用Kprobe和Jprobe在Ubuntu 22.04上安全地Hook内核函数附完整代码在Linux内核开发和安全分析领域动态追踪技术正逐渐取代传统的直接修改内存方式。本文将带你探索如何利用Kprobe和Jprobe这两种内核官方支持的机制在Ubuntu 22.04上实现安全、可靠的内核函数Hook。1. 为什么选择Kprobe/Jprobe而非传统Hook方式传统的内核Hook方法通常涉及直接修改系统调用表(sys_call_table)或函数指针这种方式虽然直观但存在诸多隐患稳定性风险直接内存修改可能导致内核崩溃安全限制现代内核的写保护机制(CR0.WP)会阻止此类操作维护困难不同内核版本需要不同的补丁方法相比之下Kprobe/Jprobe提供了以下优势特性传统HookKprobe/Jprobe安全性低高稳定性低高内核版本兼容性差优秀调试支持有限完善性能开销低中等提示Kprobe允许在任意内核指令处设置断点而Jprobe专门用于捕获函数调用和参数2. 环境准备与依赖安装在Ubuntu 22.04上使用Kprobe需要以下准备工作安装必要的开发工具和内核头文件sudo apt update sudo apt install build-essential linux-headers-$(uname -r)验证内核配置支持Kprobegrep CONFIG_KPROBES /boot/config-$(uname -r)输出应为CONFIG_KPROBESy准备示例工作目录mkdir kprobe_example cd kprobe_example touch kprobe_example.c Makefile3. 编写Kprobe模块完整代码下面是一个监控do_fork函数的完整示例适用于5.x内核#include linux/kernel.h #include linux/module.h #include linux/kprobes.h static struct kprobe kp { .symbol_name do_fork, }; static int handler_pre(struct kprobe *p, struct pt_regs *regs) { printk(KERN_INFO do_fork called by process %d\n, current-pid); return 0; } static void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { printk(KERN_INFO do_fork execution completed\n); } static int __init kprobe_init(void) { int ret; kp.pre_handler handler_pre; kp.post_handler handler_post; ret register_kprobe(kp); if (ret 0) { printk(KERN_INFO register_kprobe failed, returned %d\n, ret); return ret; } printk(KERN_INFO Planted kprobe at %p\n, kp.addr); return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(kp); printk(KERN_INFO kprobe at %p unregistered\n, kp.addr); } module_init(kprobe_init); module_exit(kprobe_exit); MODULE_LICENSE(GPL);配套的Makefile内容obj-m : kprobe_example.o KDIR : /lib/modules/$(shell uname -r)/build PWD : $(shell pwd) all: $(MAKE) -C $(KDIR) M$(PWD) modules clean: $(MAKE) -C $(KDIR) M$(PWD) clean4. Jprobe实战捕获系统调用参数Jprobe更适合需要获取函数参数的场景。以下示例监控open系统调用#include linux/kernel.h #include linux/module.h #include linux/kprobes.h #include linux/fs.h static long jdo_open(const char __user *filename, int flags, umode_t mode) { char fname[256]; long copied strncpy_from_user(fname, filename, sizeof(fname)-1); if (copied 0) { fname[copied] 0; printk(KERN_INFO process %d opening file: %s\n, current-pid, fname); } jprobe_return(); return 0; } static struct jprobe jp { .entry jdo_open, .kp { .symbol_name do_sys_open, }, }; static int __init jprobe_init(void) { int ret register_jprobe(jp); if (ret 0) { printk(KERN_INFO register_jprobe failed, returned %d\n, ret); return ret; } printk(KERN_INFO Planted jprobe at %p\n, jp.kp.addr); return 0; } static void __exit jprobe_exit(void) { unregister_jprobe(jp); printk(KERN_INFO jprobe at %p unregistered\n, jp.kp.addr); } module_init(jprobe_init); module_exit(jprobe_exit); MODULE_LICENSE(GPL);注意从Linux 4.17开始Jprobe已被废弃建议使用Kprobe结合pt_regs获取参数5. 编译、加载与测试编译模块make加载模块并查看输出sudo insmod kprobe_example.ko dmesg | tail -n 10测试Jprobe示例时可以尝试打开文件touch testfile cat testfile卸载模块sudo rmmod kprobe_example6. 高级技巧与性能优化在实际生产环境中使用Kprobe时需要考虑以下优化策略减少打印频率频繁的printk会影响性能使用静态缓冲区避免在探测处理程序中动态分配内存选择性监控通过PID过滤目标进程批量注册使用register_kprobes一次注册多个探测点性能对比测试方法perf stat -e probe:do_fork -a sleep 107. 常见问题排查问题1register_kprobe返回-2(ENOENT)解决方案检查符号名是否正确使用sudo cat /proc/kallsyms | grep 函数名验证问题2模块导致系统不稳定解决方案确保处理程序中没有阻塞操作简化处理逻辑问题3无法捕获预期函数可能原因函数被内联优化尝试禁用编译器优化EXTRA_CFLAGS -O08. 安全注意事项虽然Kprobe/Jprobe比传统Hook安全但仍需注意避免在生产环境关键路径上设置过多探测点探测处理程序应尽可能简单快速卸载模块前确保所有探测点已注销使用权限控制限制模块加载
http://www.gsyq.cn/news/1360613.html

相关文章:

  • 别再死记硬背了!从AMBA总线到实际芯片,深入理解Verilog仲裁器的设计哲学
  • 从加密狗激活到平台注册:dSPACE MicroAutoBOX II 与 MATLAB 2016b 联调实战记录
  • Win11高分辨率下C# WinForm字体发虚?别慌,这份DPI感知配置清单请收好
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan集成保姆级流程
  • 2026年不锈钢拉丝原色精工字优质工厂厂家,选前必看这些细节 - GrowthUME
  • 独立开发者如何借助 Taotoken 低成本实验多种大模型
  • 5.16全模块功能优化+局部联调
  • 别再烧MOS管了!用STM32驱动电机,H桥自举电路设计保姆级避坑指南
  • 使用curl命令快速测试Taotoken大模型API连通性
  • 别再死记硬背了!用这20个Blender核心快捷键,5分钟搞定模型贴图基础操作
  • 5.19-5.20整体验收+文档整理+项目交付
  • 【云计算学习之路】学习Centos7系统:服务搭建(VSFTP)
  • 手把手教你用GD32450Z点亮AT070TN94屏幕:从SDRAM配置到RGB565时序调试全流程
  • 别再暴力循环了!用Floyd-Warshall算法5分钟搞定任意两点最短路径(附C++代码实战)
  • 技术解密:基于YOLOv10的实时AI瞄准辅助系统如何实现毫秒级响应
  • 为OpenClaw智能体工作流配置Taotoken作为多模型供应商
  • Fillinger智能填充脚本:如何用三角剖分算法彻底解决Illustrator图形分布难题?
  • Java 求职面试:微服务架构与安全框架的探索
  • 使用taotoken的openai兼容协议为ubuntu上的python脚本赋能
  • UNT413A刷机后体验:开机无广告、流畅度飙升,这波操作值不值?
  • 5.12智能识别+自动化功能开发
  • FastAPI 进阶实战:请求体、文件上传、响应模型与数据校验
  • 2026这6款硬核降AIGC软件全网首测,一键把AI检测率精准控到安全区!
  • 【2026最新收藏版】后端转AI大模型应用开发全路线,小白/程序员必看
  • 告别GUI点点点!用.do文件脚本让ModelSim仿真效率翻倍(附Xilinx库配置避坑指南)
  • 为什么83%的企业AI Agent培训项目6个月内失效?头部机构不愿公开的4个认知断层与重建方案
  • 告别建模苦手!用ContextCapture Center 10.20.1把航拍图变3D模型(附避坑指南)
  • 告别Labelme?实测对比:EISeg交互式分割在医疗细胞标注上的效率到底有多高
  • 水壶装箱检测怎么做?一个独立开发者的实战经验
  • 四面字节,现在大厂Agent开发岗都这么难了?