2

我正在尝试在 x86_32 上的 Linux 内核 v3.5 中挂钩 sys_execve 系统调用。我只是将 sys_call_table 入口地址更改为我的钩子函数

asmlinkage long (*real_execve)( const char __user*, const char __user* const __user*,
                 const char __user* const __user* );
...
asmlinkage long hook_execve( const char __user* filename, const char __user* const __user* argv,
                    const char __user* const __user* envp )
{
    printk( "Called execve hook\n" );
    return real_execve( filename, argv, envp );
}
...
real_execve = (void*)sys_call_table[ __NR_execve ];
sys_call_table[ __NR_execve ] = (unsigned long)hook_execve;

我确实为修改 sys_call_table 条目设置了页面权限,并且提到的方案适用于其他系统调用(chdir、mkdir 等)。但是在 execve 挂钩时,我得到了空指针取消引用:

Mar 11 14:18:08 mbz-debian kernel: [ 5590.596033] Called execve hook
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596408] BUG: unable to handle kernel NULL pointer dereference at   (null)
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596486] IP: [<  (null)>]   (null)
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596526] *pdpt = 0000000032302001 *pde = 0000000000000000 
Mar 11 14:18:08 mbz-debian kernel: [ 5590.596584] Oops: 0010 [#1] SMP

我用三个参数调用 sys_execve,因为arch/x86/kernel/entry_32.S它包含PTREGSCALL3(execve). 但是,我尝试使用四个参数(添加struct pt_regs*)调用它,但我得到了同样的错误。也许这种执行方法完全有问题?还是我错过了什么?

更新#1

我发现它sys_call_table[ __NR_execve ]实际上包含ptregs_execve(不是sys_execve)的地址。在 中定义如下arch/x86/kernel/entry_32.S

#define PTREGSCALL3(name) \
ENTRY(ptregs_##name) ; \
CFI_STARTPROC; \
leal 4(%esp),%eax; \
pushl_cfi %eax; \
movl PT_EDX(%eax),%ecx; \
movl PT_ECX(%eax),%edx; \
movl PT_EBX(%eax),%eax; \
call sys_##name; \
addl $4,%esp; \
CFI_ADJUST_CFA_OFFSET -4; \
ret; \
CFI_ENDPROC; \
ENDPROC(ptregs_##name)
...
PTREGSCALL3(execve)

所以为了修改sys_execve我需要替换它的代码而不修改它的地址?我在这里读过类似的东西,这是要走的路吗?

更新#2

实际上我发现了以下调用序列:do_execve->do_execve_common->search_binary_handler->security_bprm_check,这security_bprm_check是一个围绕 LSM(Linux 安全模块)操作的包装器,它控制二进制文件的执行。之后,我阅读并关注了这个链接,我得到了它的工作。它解决了我的问题,因为现在我可以看到要执行的进程的名称,但我仍然不确定它的正确性。也许其他人会对所有这些东西增加一些清晰度。

4

1 回答 1

1

过去,在 Linux 内核中挂钩系统调用是一项更容易的任务,然而,在较新的内核中,程序集存根被添加到系统调用中。为了解决这个问题,我在运行中修补了内核的内存。

您可以在此处查看我用于挂钩 sys_execve 的完整解决方案: https ://github.com/kfiros/execmon

于 2016-11-07T15:51:18.913 回答