【问题标题】:Recoding Strace, why I can't catch the "write syscall ?"重新编码 Strace,为什么我无法捕捉到“写系统调用”?
【发布时间】:2021-04-06 17:00:33
【问题描述】:

我目前正在重新编码 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,     %lld\n",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 = %d\n", 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 代表 execve 系统调用60 代表退出系统调用。 这是使用 real strace 的输出:

strace ./my_program

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

如您所见,我的程序没有捕获 write syscall

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

感谢您的回答。

【问题讨论】:

  • 您的 while 循环设置为切换 in_call(在 0 和 1 之间来回翻转),因此您只打印每隔一个系统调用。所以你正在捕捉 write 系统调用,但由于它是一个奇怪的调用,它不会被打印出来。

标签: c system-calls strace


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多