[FW]使用kprobes查看内核内部信息
一、首先内核必须支持kprobes、jprobes:
#make menuconfig
General setup --->
[*] Kprobes
使内核支持kprobes。
二、kprobes的使用方法:
1、分配一个kprobe结构体供kprobes运行时使用。
2、在kprobe结构体的addr成员中设置要插入侦测器的函数地址,可以通过查看system.map查找,或者通过proc文件系统查找
# cat /proc/kallsyms | grep "do_execve"
c00bbfb8 T do_execve
3、如果不想设置addr成员,可以设置symbol_name成员为"do_execve"(想要侦测的函数),需要内核版本在2.6.19以上才支持。
4、在kprob结构的pre_handler成员设置侦测函数exec_pre_handler。
5、调用register_kprobe函数注册侦测器函数。
以下是一个用kprobes监测do_execve()函数的例子,在每次调用do_execve()函数之前,就会打印当前的进程pid、jiffies值等全局变量信息。#include <linux/module.h>
- #include <linux/kprobes.h>
- #include <linux/kallsyms.h>
- struct kprobe exec_kp;
- static int exec_pre_handler(struct kprobe *p, struct pt_regs *regs)
- {
- printk("Enter into %s\n", __func__);
- printk("pt_regs:%p, pid:%d, jiffies:%ld\n", regs, current->tgid, jiffies);
- return 0;
- }
- static __init int kprobes_exec_init(void)
- {
- /*设置要检测的函数do_execve()的地址*/
- //exec_kp.addr = (kprobe_opcode_t *)0xc00bbfb8;
- /*如果不想直接给addr成员设置地址,也可以使用符号名*/
- exec_kp.symbol_name = "do_execve";
- exec_kp.pre_handler = exec_pre_handler;
- /*注册kprobes*/
- register_kprobe(&exec_kp);
- return 0;
- }
- static __exit void kprobes_exec_cleanup(void)
- {
- /*撤销kprobes注册*/
- unregister_kprobe(&exec_kp);
- }
- module_init(kprobes_exec_init);
- module_exit(kprobes_exec_cleanup);
- MODULE_LICENSE("GPL");
编译并insmod上述ko,那么在do_execve()函数执行之前就会先执行kprobes的pre_handler所指向的exec_pre_handler,打印内核的当前进程pid、jiffies等全局变量的值。由于do_exec函数用于生成进程,因此每次执行ls等命令都会显示一次:
pt_regs:c52ebf08, pid:110, jiffies:155286
pt_regs:c5313f08, pid:113, jiffies:159137
pt_regs:c52ebf08, pid:112, jiffies:159137
利用kprobes也可以查看内核函数内部任意位置的信息,此时需要把内核函数反汇编,确定想要查看位置相对于函数起始地址的偏移量,在初始化kprobes时,设置kprobe结构体的offset成员,就可以查看内核内部函数任意位置的信息。
三、jprobes的使用方法
用kprobes可以方便的查看内核内部任意位置的信息,相反,jprobes则是特别为函数开头的侦测准备的,通过jprobes,可以更容易的获取传递给函数的参数。使用jprobes与使用kprobes大体上一样,主要有以下区别:
1、分配给jprobes的结构体是jprobe结构体,并将指针传递给register_jprobe。jprobe结构的成员如下所示,只包括kprobe和entry两者。
- struct jprobe {
- struct kprobe kp;
- void *entry; /* probe handling code to jump to */
- };
struct kprobe kp成员设置的是要侦测函数的符号或地址,entry中为通过JPROBE_ENTRY()宏处理过的侦测器处理程序。
2、侦测器处理程序的参数应当与需要侦测的函数的参数相同,这样可以方便的打印被侦测函数的形参。使用kprobes时,必须通过寄存器或者栈才能计算出参数的值。而计算方法还依赖于cpu架构,如果使用jprobes,则无须了解架构的详细知识,也能查看参数的值。
3、侦测器处理函数的尾部必须加上jprobe_return();
以下是使用jprobes打印do_execve函数的参数的例子,每次调用do_execve之前,都会打印相应的参数:
- #include <linux/module.h>
- #include <linux/kprobes.h>
- #include <linux/kallsyms.h>
- struct jprobe exec_jp;
- int jp_do_execve(const char * filename,
- const char __user *const __user *argv,
- const char __user *const __user *envp,
- struct pt_regs * regs)
- {
- int cnt = 0;
- printk("filename = %s\n", filename);
- for(; *argv != NULL;argv++,cnt++)
- printk("argv[%d] = %s\n", cnt, *argv);
- jprobe_return();
- return 0;
- }
- static __init int jprobes_exec_init(void)
- {
- exec_jp.kp.symbol_name = "do_execve";
- exec_jp.entry = JPROBE_ENTRY(jp_do_execve);
- /*注册jprobes*/
- register_jprobe(&exec_jp);
- return 0;
- }
- static __exit void jprobes_exec_cleanup(void)
- {
- /*撤销jprobes注册*/
- unregister_jprobe(&exec_jp);
- }
- module_init(jprobes_exec_init);
- module_exit(jprobes_exec_cleanup);
- MODULE_LICENSE("GPL");
每次执行ls时都会调用do_execve函数,具体的打印如下:
# ls
filename = /bin/ls
argv[0] = ls
[FW]使用kprobes查看内核内部信息的更多相关文章
- 使用kprobes查看内核内部信息
前言:使用printk打印变量等方法,是调试内核的有效方法之一,但是这种方法必须重新构建并用新内核启动,调试效率比较低.以内核模块的方式使用kprobes.jprobes,就可以在任意地址插入侦测器, ...
- [linux系统]查看内核版本和系统版本方法
查看内核版本信息的两个命令: uname -a cat /proc/version 查看系统版本的命令: lsb_release -a more /etc/issue cat /etc/redhat- ...
- linux查看内核版本、系统版本、系统位数(32or64)
linux查看内核版本.系统版本.系统位数(32or64) 2011-05-01 22:05:12 标签:linux 内核版本 休闲 系统版本 系统位数 1. 查看内核版本命令: 1) [root@ ...
- 在linux下查看内核版本、gcc版本、操作系统多少位等参数
1. 查看linux版本 cat /etc/issue Ubuntu 11.04 \n \l 2. 查看内核版本 1)cat /proc/version Linux version 2.6.38-13 ...
- Linux下查看内核、CPU、内存及各组件版本的命令和方法
Linux下查看内核.CPU.内存及各组件版本的命令和方法 Linux查看内核版本: uname -a more /etc/*release ...
- Ubuntu 中查看内核版本和系统版本的三个命令
一.查看内核版本:cat /proc/version 二.查看内核版本:uname -a 三.查看系统版本:lsb_release -a 四.查看发行版类型:cat /etc/issue
- Linux查看内核和系统版本
1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux version 2.6.9-22.ELsmp (bhcompile@crowe.d ...
- Linux查看内核信息或系统信息
先说说为什么会写这个.这是我去面试的时候面试官问的一个问题,我感觉是一个普遍会被问到的问题.为了让我自己记住,也便于收集下Linux运维方向考官的题目. 第一,查看内核信息 cat /proc/ver ...
- Ubuntu 中查看内核版本和系统版本的四个命令
一.查看内核版本:cat /proc/version 二.查看内核版本:uname -a 三.查看系统版本:lsb_release -a 四.查看发行版类型:cat /etc/issue
随机推荐
- 高级定时器-setTimeout()、setInterval()、链式setTimeout()
使用 setTimeout()和 setInterval()创建的定时器可以用于实现有趣且有用的功能.执行时机是不能保证的,因为在页面的生命周期中,不同时间可能有其他代码在控制 JavaScript ...
- JavaScript面向对象编程(2)-- 类的定义
最近这一段时间事情太多了,没有时间再继续写,幸好这两天有点小闲,先小写一下JavaScript中面向对象一中推荐的方法.本文承接上一篇JavaScript面向对象编程(1) -- 基础. 上篇说过,J ...
- python 异常处理【转载】
什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Python脚本 ...
- JAVA-第一期学习(上)
前言 果然,flag这个东西不能随便立,在我立志要学习java的第4天,我终于打开了我的eclipse.. 本章学习的内容是红框,第一期学习.真好,7月份需要学习完的东西,现在连helloworld还 ...
- SELECT - 从表或视图中取出若干行
SYNOPSIS SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] * | expression [ AS output_name ] [ ...
- SpringBoot 快速支持国际化i18n
学习目标 快速学会如何在工程中支持国际化语言. 快速查阅 专题阅读:<SpringBoot 布道系列> 源码下载:springboot-locale-i18n — Hey Man,Don' ...
- ZYNQ跑系统 系列(二) petalinux方式移植linux
三.搭建petalinux工程 0.定位目录 先在shell中找一个准备存放工程的地方,(我的是home/hlf/PRO),命令行cd home/hlf/PRO 1.定位编译链 根据安装p ...
- 7.搭建hyperledger fabric环境及启动——2019年12月12日
2019年12月12日13:05:16 声明:从网络中学习整理实践而来. 1.介绍fabric Fabric 是一个面向企业应用的区块链框架,基于 Fabric 的开发可以粗略分为几个层面: 1. 参 ...
- STM32中stm32f0xx_flash.icf文件的作用详解!(不错的!)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/weibo1230123/article/details/80142210 每个芯片开发商都会针对每款 ...
- Python实现手机号自动判断性别
本文性别判断主要依靠airtest中的自动化测试实现 通过自动对比支付宝页面男女图像,从而实现男女判断 代码如下: 男女判断函数: // An highlighted block def numbe( ...