获取使用Kprobes的函数参数 [英] Getting function arguments using kprobes

查看:288
本文介绍了获取使用Kprobes的函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经把kprobe的功能,现在我需要在kprobe的prehandler函数的自变量的值。

I have put a kprobe on a function and now I need to get values of its arguments in kprobe's prehandler function.

下面是我的功能:

void foobar(int arg, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8)
{
    printk("foobar called\n");
}

这是它把kprobe和调用函数:

Putting kprobe on it and calling the function:

...
kp.addr = (kprobe_opcode_t *) foobar;
register_kprobe(&kp);

foobar(0xdead1, 0xdead2, 0xdead3, 0xdead4, 0xdead5, 0xdead6, 0xdead7, 0xdead8);

最后(这里从拍摄)prehandler功能

And finally prehandler function (taken from here):

static int inst_generic_make_request(struct kprobe *p, struct pt_regs *regs)
{
  printk(KERN_INFO "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
    regs->ax, regs->bx, regs->cx, regs->dx);
    printk(KERN_INFO "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
      regs->si, regs->di, regs->bp, regs->sp);
    regs++;
    //...
}

从prehandler函数的输出看起来像这样(我加暂存器指针3次)

May 10 22:58:07 kernel: [  402.640994] eax: 000dead1   ebx: f7d80086   ecx: 000dead3   edx: 000dead2
May 10 22:58:07 kernel: [  402.640996] esi: 00000000   edi: b77c8040   ebp: 00000000   esp: f7d8006c

May 10 22:58:07 kernel: [  402.641006] eax: f7d8032c   ebx: 000dead5   ecx: 000dead6   edx: 000dead7
May 10 22:58:07 kernel: [  402.641007] esi: 000dead8   edi: f7d800e0   ebp: f7d80330   esp: 08049674

May 10 22:58:07 kernel: [  402.641014] eax: 00000080   ebx: 0992b018   ecx: 0000108e   edx: 0992b008
May 10 22:58:07 kernel: [  402.641015] esi: 08049674   edi: b77c8040   ebp: bfe23fb8   esp: bfe23f50

现在我可以看到 foobar的函数的参数在各种寄存器(哪来的 0xdead4 ?),不应该他们在一个堆栈?如何访问从prehandler函数栈?或者,我怎么能得到任何函数的参数不知道它们的类型和数量?我知道这可能不是一个简单的任务(甚至没有可能得到的所有值),但只有约值应该够了。我的两个函数之间的参数计算相关,我真的不需要精确值。它是否有助于如果我有这里的参数是压入堆栈调用函数)的组装code?

Now I can see arguments of foobar function in various registers (but where's 0xdead4?), shouldn't they be in a stack? How can I access the stack from prehandler function? Or how can I get arguments of any function without knowing their types and count? I know that this might not be an easy task (and not even possible to get all values), but only approximately values should be enough. I'm calculating correlation between arguments of two functions and I really don't need exact values. Would it help if I had assembly code of caller function where the arguments are pushed onto the stack)?

推荐答案

有至少两种方法。

可能是最容易的:如果的 Jprobes 的是适合你的任务,你可以给他们一个尝试。他们是Kprobes的的近亲(见它们的详细描述和链接在内核文档的例子) 。

Probably the most easy one: if Jprobes are suitable for your task, you could give them a try. They are the close relatives of kprobes (see their detailed description and links to the examples in the kernel docs).

Jprobes允许调用你的函数具有相同签名作为进入后者探测之一。你得到所有的参数自动这种方式。

Jprobes allow to call your function with the same signature as the probed one on entry to the latter. You get all of the arguments automatically this way.

另一种方法可以延长一点你已经做的和检索寄存器和堆栈的参数。从输出日志在你的问题,我想你是在32位x86系统上工作。

Another approach could be to extend a bit what you already do and retrieve the arguments from the registers and the stack. From the output log in your question, I assume you are working on a 32 bit x86 system.

据我所看到的,也有上过Linux内核在x86(详情可论证两种最常见的约定在的由瓦格纳雾手册)。需要注意的是系统调用遵循其他公约(见手动),但我认为你有兴趣在分析了普通的功能,而不是一个系统调用。

As far as I have seen, there are two most common conventions on argument passing in the Linux kernel on x86 (the details are available in the manual by Agner Fog). Note that system calls follow other conventions (see the manual for details) but I assume you are interested in analysing an "ordinary" function rather than a system call.

有关标记 asmlinkage 以及为带有可变参数列表函数的功能,所有参数都通过堆栈。该函数的返回地址应该是在上进入函数的堆栈的顶部,所述第一参数位于右侧下方。第二个参数是第一个的下方,等等。

For the functions marked with asmlinkage as well as for the functions with variable argument lists, all parameters are passed on stack. The return address of the function should be at the top of the stack on entry to the function, the first parameter being located right below it. The second parameter is below the first one, and so on.

如您有尤其的保存价值,你可以找到它指向。 *(ESP + 4)应该是第一个参数, *(ESP + 8) - 第二个,等,如果这个约定使用。

As you have the saved value of esp, you can find what it points to. *(esp+4) should be the first argument, *(esp+8) - the second one, etc., if this convention is used.

这似乎是用于大部分的内核功能,包括您在问题中提到的那个。

It seems to be used for the most of the kernel functions including the one you mentioned in the question.

内核编译与 -mregparm = 3 ,因此前3个参数在 EAX 过去了, EDX ECX ,按照这个顺序,其余堆栈去。 *(ESP + 4)应该是第四个参数, *(ESP + 8) - 第五届之一,等等。

The kernel is compiled with -mregparm=3 and therefore the first 3 arguments are passed in eax, edx and ecx, in that order, the rest go on stack. *(esp+4) should be the 4th argument, *(esp+8) - the 5th one, and so on.

看来,东西都放在X86-64简单一些。大多数的内核函数(包括那些带有可变参数列表)获得第6个参数的 RDI RSI RDX RCX R8 R9 ,按照这个顺序,其余的去堆。 *(ESP + 8)应该是7日的说法, *(ESP + 16) - 第八届等

It seems that things are a bit simpler on x86-64. Most of the kernel functions (including those with variable argument list) get the first 6 arguments in rdi, rsi, rdx, rcx, r8, r9, in that order, the remaining ones go on stack. *(esp+8) should be the 7th argument, *(esp+16) - the 8th and so on.

编辑:

请注意,X86-32,价值尤其不保存在 pt_regs 内核模式陷阱(包括软件断点Kprobes的依赖)。 < ASM / ptrace.h> 提供 kernel_stack_pointer()函数来检索尤其,它的作品无论在X86-32和X86-64。更多详细信息参见该头文件的 kernel_stack_pointer()的说明。

Note that on x86-32, the value of esp is not saved in pt_regs for kernel-mode traps (including the software breakpoints that KProbes rely upon). <asm/ptrace.h> provides kernel_stack_pointer() function to retrieve the correct value of esp, it works both on x86-32 and on x86-64. See the description of kernel_stack_pointer() in that header file for details.

此外, regs_get_kernel_stack_nth()(在头定义)提供了一个方便的方式来获得在处理程序堆栈的内容。

In addition, regs_get_kernel_stack_nth() (also defined in that header) provides a convenient way to get the contents of the stack in the handler.

这篇关于获取使用Kprobes的函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆