【问题标题】:Hooking sys_execve on Linux kernel 4.6 or higher在 Linux 内核 4.6 或更高版本上挂钩 sys_execve
【发布时间】:2018-04-17 08:49:58
【问题描述】:

低于 4.6 的内核使用程序集存根来加强关键系统调用(如 fork、clone、exec 等)的挂钩。特别是对于 execve,Kernel-4.5 的以下 sn-p 显示了 execve 的入口存根:

ENTRY(stub_execve)
    call    sys_execve
return_from_execve:
 ... 
END(stub_execve)

系统call table 包含这个存根的地址,这个存根进一步调用原始的execve。因此,要在这个环境中挂钩 execve,我们需要使用我们的挂钩例程修补存根中的call sys_execve,并在完成我们想要的事情之后调用原始的 execve。这一切都可以在execmon 中看到,这是一个用于 linux 的进程执行监控实用程序。我已经测试 execmon 在内核 4.4 的 Ubuntu 16.04 中成功运行。

从内核 4.6 开始,关键调用保护的上层方案已更改。现在存根看起来像:

ENTRY(ptregs_\func)
    leaq    \func(%rip), %rax
    jmp     stub_ptregs_64
END(ptregs_\func)

其中\func 将扩展为sys_execve 用于执行调用。同样,系统call table 包含这个存根,这个存根调用原始的 execve,但现在以更安全的方式而不是仅仅执行call sys_execve。 这个较新的存根将被调用函数的地址存储在RAX 寄存器中,并跳转到下图所示的另一个存根(已删除 cmets):

 ENTRY(stub_ptregs_64)
     cmpq   $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp)
     jne    1f

     DISABLE_INTERRUPTS(CLBR_NONE)
     TRACE_IRQS_OFF
     popq   %rax
     jmp    entry_SYSCALL64_slow_path

 1:
     jmp    *%rax        /* called from C */
 END(stub_ptregs_64)

请查看this 以查看此存根中的 cmets 和其他引用标签。

我努力想出一些逻辑来克服这种保护并使用挂钩函数修补原始调用,但还没有成功。 有人愿意加入我并帮助摆脱困境吗?

【问题讨论】:

    标签: c linux-kernel hook


    【解决方案1】:

    我完全不明白你从哪里采取安全角度。

    func 之前和当前的 from 都不是“硬化”的。

    你也没有说明为什么要挂钩 execve。

    标准的挂钩机制使用 kprobes,您可以查看 systemtap 以获取示例使用者。

    我查看了前面提到的“execmon”代码,发现它的质量很差,不适合学习。比如https://github.com/kfiros/execmon/blob/master/kmod/syscalls.c#L65

    • 直接访问用户空间内存(没有 get_user、copy_from_user 等)
    • 两次。首先它计算长度(未绑定!),然后复制内容。特别是如果有人在计算后使字符串更长,但在它们被复制之前,这会触发缓冲区溢出。

    【讨论】:

      猜你喜欢
      • 2013-02-26
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 2023-03-27
      • 2011-01-07
      相关资源
      最近更新 更多