使用kprobes查看内核内部信息
2017-02-19 03:12
351 查看
http://blog.chinaunix.net/uid-9543173-id-3571748.html
使用kprobes查看内核内部信息
wushuan10141 2013-04-08 16:50:43
一、首先内核必须支持kprobes、jprobes:
#makemenuconfig
General setup --->
[*]Kprobes
使内核支持kprobes。
二、kprobes的使用方法:
1、分配一个kprobe结构体供kprobes运行时使用。
2、在kprobe结构体的addr成员中设置要插入侦测器的函数地址,可以通过查看system.map查找,或者通过proc文件系统查找
# cat/proc/kallsyms | grep "do_execve"
c00bbfb8T 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
使用kprobes查看内核内部信息
wushuan10141 2013-04-08 16:50:43
一、首先内核必须支持kprobes、jprobes:
#makemenuconfig
General setup --->
[*]Kprobes
使内核支持kprobes。
二、kprobes的使用方法:
1、分配一个kprobe结构体供kprobes运行时使用。
2、在kprobe结构体的addr成员中设置要插入侦测器的函数地址,可以通过查看system.map查找,或者通过proc文件系统查找
# cat/proc/kallsyms | grep "do_execve"
c00bbfb8T 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
相关文章推荐
- 使用kprobes查看内核内部信息
- kprobes查看内核内部信息的使用方法
- 使用kprobes查看内核内部信息
- linux如何使用kprobes查看内核内部信息
- 使用kprobes查看内核内部信息
- 使用kprobes查看内核内部信息
- [FW]使用kprobes查看内核内部信息
- 我使用过的Linux命令之dmesg - 查看开机信息/打印或控制内核环形缓冲区
- 【视频】配置信息管理 的 使用方法(三):查看和修改元数据、查看数据库的表视图存储过程等信息
- 使用PsList查看Windows上Oracle的线程等信息
- 【视频】配置信息管理 的 使用方法(三):查看和修改元数据、查看数据库的表视图存储过程等信息
- 查看Linux内核丢包信息
- 在系统启动时至少有一个服务或驱动程序产生错误。详细信息,请使用事件查看器查看事件日志
- 查看linux内核信息及版本信息
- 查看linux内核信息
- 【视频】配置信息管理 的 使用方法(三):查看和修改元数据、查看数据库的表视图存储过程等信息
- 在系统启动时至少有一个服务或驱动程序产生错误,详细信息,请使用事件查看器查看事件日志
- windows mobile进程查看器开发(四)—— 查看内存、内部存储和存储卡的使用情况
- 使用Coefficient查看数据库内部运行情况