How to use ptrace(2) to change behaviour of syscalls?

半腔热情 提交于 2019-12-03 20:52:52
Michael Foukarakis

You can use the PTRACE_SYSCALL request: it restarts the child process (just like PTRACE_CONT) but arranges for it to stop at the next entry to or exit from a system call. For example (assume a kernel built for x86):

#include <sys/ptrace.h>
#include <signal.h>
#include <linux/user.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char **argv)
{
    int status = 0, pid, r;
    struct user_regs_struct uregs;

    if ((pid = fork()) == 0) {
        printf("pid = %d, ppid = %d\n", getpid(), getppid());
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        kill(getpid(), SIGINT);
        r = getpid();
        printf("%d\n", r);
    } else {
        wait(&status);
        ptrace(PTRACE_SYSCALL, pid, 0, 0);
        wait(&status);
        ptrace(PTRACE_GETREGS, pid, 0, &uregs);

        /* this prints the syscall number of getpid */
        printf("syscall nr: %d\n", uregs.orig_eax);
        /* 64 is syscall number of getppid */
        uregs.orig_eax = 64;
        ptrace(PTRACE_SETREGS, pid, 0, &uregs);
        ptrace(PTRACE_CONT, pid, 0, 0);
        wait(&status);
        if(WIFEXITED(status))
            printf("we're done\n");
    }
}

The child prints its PID and delivers a signal to itself. Because of the prior call to ptrace() this means it will be stopped.

The parent waits for this to happen and restarts the child with PTRACE_SYSCALL, then waits. Next, the child invokes the getpid system call and it is stopped once again. The parent process uses the PTRACE_GETREGS invocation to peek into the child's registers, where eax holds the system call number. The parent changes this to the system call number of getppid, then once again allows the child to continue. Because the system call number has changed prior to the invocation of the system call, the child will now invoke getppid instead of getpid.

Using ptrace for this purpose may be portable, but I have not tested it. In gdb, you can also use the catch syscall command.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!