我尝试使用ptrace来捕获子进程系统调用id,例如execve(11)或fork(2)。
我的代码在这里。
#include <sys/syscall.h>
#include <sys/reg.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main(){
pid_t pid;
if ((pid = fork()) == 0){
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
pid_t t = fork();
} else{
int status;
struct rusage resource;
while (true){
wait4(pid, &status, 0, &resource);
if (WIFEXITED(status)) break;
int syscall = ptrace(PTRACE_PEEKUSER, pid, 4 * ORIG_EAX, NULL);
if (syscall == SYS_execve) printf("%d\n", syscall);
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
}
}
return 0;
}
在我看来,程序应该在屏幕上打印“2”(因为系统调用“fork”id为2),但程序结束后我什么都没得到。 有人可以解释一下吗?
答案 0 :(得分:1)
如果你的程序已经正常退出,那么
if (WIFEXITED(status)) break;
这句话可能导致不打印2,因为它将其从循环中取出。
请参阅此声明。
答案 1 :(得分:0)
Op现在可能不需要答案了,但是其他人可能需要,所以我就把它放在那里。
首先,只有在执行if (syscall == SYS_execve)
系统调用时,行execv
才有效。这意味着它将打印分配给execv的系统调用号码,该号码在我的机器(x86)中为号码11
。但是您实际上从未调用过execv,因此什么也不会打印。
其次,您可能看不到屏幕上显示2
的原因是,如果您使用的是2.3.3版或更高版本,则fork()
调用实际上不是系统调用。
不会调用kernel's fork()
,而是调用glibc fork()
包装器函数,它实际上不是系统调用。
然后,此函数将调用clone()
系统调用。因此,如果要捕获它并对其进行操作,则需要搜索克隆系统调用ID(取决于您使用的版本)或使用SYS_clone。