【发布时间】: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