如何使用ptrace的(2)改变系统调用的行为?(How to use ptrace(2) to c

2019-08-02 20:55发布

是否有使用任何导游或实例(尤其是ARM的)或库ptrace影响其他进程的执行? 例如,使其相信一些数据出现在文件描述符(即释放选择/ poll的一些结果和“答案”内核前下阅读系统调用)。 期待一些涉及PTRACE_SYSEMU。

可以在便携式的方式进行? 我想是这样的libc,压倒一切的LD_PRELOAD技巧,但它可以在运行时连接。

可以将它与一些GDB命令来实现?

理想的变型是,如果有一些图书馆,在那里我可以很容易的和可移植挂接到系统调用和实际通话作出后的前编辑(或模仿他们),喜欢使用LD_PRELOAD做时 。

@link 使用PTRACE_SYSEMU任何好导游?

Answer 1:

您可以使用PTRACE_SYSCALL请求:重新启动子进程(就像PTRACE_CONT),但安排其停止在下次进入或退出系统调用。 例如(假定为86内置内核):

#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");
    }
}

孩子打印其PID和信号传送到自身。 由于现有呼叫的ptrace()这意味着它会被停止。

父等待要做到这一点,并重新启动与PTRACE_SYSCALL孩子,然后等待。 接下来,孩子调用getpid系统调用,它再次停止。 父进程使用PTRACE_GETREGS调用窥视孩子的寄存器,其中eax持有的系统调用号。 父改变了这的系统调用号getppid ,然后再一次让孩子继续。 由于系统调用号已经先于系统调用的调用改变,孩子现在将调用getppid代替getpid

使用ptrace用于此目的可以是便携式的,但我没有测试它。 在gdb,您还可以使用catch syscall命令。



文章来源: How to use ptrace(2) to change behaviour of syscalls?