c语言 - 重新编码痕迹,为什么我抓不住"write syscall ?"



我当前正在重新编写Strace命令。

我理解这个命令的目标,并且可以从可执行文件中捕获一些系统调用。

我的问题是:为什么我没有抓住"写";系统调用

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <wait.h>
int main(int argc, char* argv[]) {
int status;
pid_t pid;
struct user_regs_struct regs;
int counter = 0;
int in_call =0;
switch(pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execvp(argv[1], argv + 1);
break;
default:
wait(&status);
while (status == 1407) {
ptrace(PTRACE_GETREGS, pid, NULL, &regs);
if(!in_call) {
printf("SystemCall %lld called with %lld, %lld,     %lldn",regs.orig_rax, 
regs.rbx, regs.rcx, regs.rdx);
in_call=1;
counter ++;
}
else
in_call = 0;
ptrace(PTRACE_SYSEMU, pid, NULL, NULL);
wait(&status);
}
}
printf("Total Number of System Calls = %dn", counter);
return 0;
}

这是使用我的程序的输出:

./strace ./my_program
SystemCall 59 called with 0, 0,     0
SystemCall 60 called with 0, 4198437,     5
Total Number of System Calls = 2

59表示执行系统调用60表示退出系统调用。这是使用真实strace的输出:

strace ./my_program
execve("./my_program", ["./bin_asm_write"], 0x7ffd2929ae70 /* 67 vars */) = 0
write(1, "Toton", 5Toto
)           = 5
exit(0)                                 = ?
+++ exited with 0 +++

正如您所看到的,我的程序没有捕获写系统调用

我不明白为什么,你知道吗?

谢谢你的回答。

while循环的设置非常奇怪——您有这个in_call标志,可以在0和1之间来回切换,并且只有当它为0时才打印系统调用。最终的结果是,当您捕获每个系统调用时,您只打印其他所有系统调用。因此,当您接到写调用时,标志为1,并且您不打印任何内容。

另一个奇怪的地方是,您使用的是PTRACE_SYSEMU,而不是PTRACE_SYSTCALL。SYSEMU旨在模拟系统调用,因此系统调用根本不会实际运行(它将被跳过(;通常情况下,ptracing程序会执行systime调用本身应该执行的任何操作,然后调用PTRACE_SETREGS以使用适当的返回值设置tracee的寄存器,然后再次调用PTRACE_SYSEMU以运行到下一个系统调用。

如果您实际使用的是PTRACE_SYSCALL,那么in_call标记将更有意义,因为这将为每个系统调用停止两次——一次在进入系统调用时停止,第二次在调用返回时停止。然而,它也会因信号而停止,因此您需要对状态进行解码,以查看是否发生了信号。

最新更新