使用 ptrace 时如何区分“syscall”和“int 80h”

使用 ptrace 时如何区分“syscall”和“int 80h”

据我所知,ptrace 只能通过 PTRACE_SYSCALL 获取系统调用号,但 x86 和 x64 上的系统调用号不同。那么有什么方法可以找出这个系统调用的真正来源吗?

我现在正在编写一个程序来通过系统调用号限制其他程序的系统调用,我知道 x86 和 x64 上的系统调用号,但有些程序使用“int 80h”而不是“syscall”,因此它们可以执行我在 x64 上限制的危险操作。例如,我在 x64 上禁止了 fork(),它们可以使用“int 80h(2)”(fork()),而我觉得它们正在使用“syscall(2)”(open()),因此它们可以突破限制。虽然 ptrace 可以跟踪它们并获取系统调用号,但我无法区分系统调用实际上来自何处。

答案1

截至撰写本文时(2019-02-08),这是不可能的

乃至strace 弄错了

编辑: Linus Torvalds 在这里谈论了这一点,还分析了代码中可能(但注释掉)的解决方法,strace这些解决方法直接查看二进制文件中的指令。此代码已被删除这里作为我下面提到的补丁集的一部分。它说It works, but is too complicated, and strictly speaking, unreliable,但我不清楚在哪些情况下“严格来说,不可靠”适用,是否仅在多线程可执行文件在运行时重写自身的情况下(因此不适合禁止某些系统调用以用于安全用例),还是也适用于其他情况。

编辑:“不可靠”部分被添加在这次提交

编辑:我现在已经尝试了 strace 的操作码窥视实现(版本v4.25),并怀疑它有问题:通过更改激活该代码路径时这行#if 0这行#elif 1,没有打印任何系统调用,因为scno根本没有设置。我scno = x86_64_regs.orig_rax;在之后添加了这行使其工作。

观看演示如何让 strace 开心,幻灯片 2,问题 2:

没有可靠的方法来区分 x86_64 和 x86 系统调用。

详情见幻灯片 4-6。建议的解决方案添加到内核中:

使用 PTRACE_GET_SYSCALL_INFO 请求扩展 ptrace API

但这个解决方案并未合并到内核。

该补丁集被调用ptrace: add PTRACE_GET_SYSCALL_INFO request,并且它2019 年 1 月仍在进行中。希望它能尽快合并。


strace已经得到支持自 4.26 版以来(但除非你手动应用内核补丁,否则它不会起作用):

PTRACE_GET_SYSCALL_INFO实现了使用ptrace API获取系统调用信息。

答案2

这是系统调用sys_rt_sigtimedwait(自内核 2.2 开始)。请参阅手册页其中:

man 2 rt_sigtimedwait

该系统调用暂停执行,直到参数指定的信号(或一组信号)被传递。还给出了超时时间。

要 100% 确定有一个名为 的文件unistd_64.h。请在您的系统中搜索该文件。它通常位于 include 文件夹 ( /usr/include/x86_64-linux-gnu/asm/unistd_64.h) 中。其中定义了数字。以下是我的情况下的相关行(它也是 64 位系统,内核 3.2.0-58):

#define __NR_rt_sigtimedwait                    128
__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)

注意128十六进制是十进制80

相关内容