首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在父进程中不工作的Ptrace选项

在父进程中不工作的Ptrace选项
EN

Stack Overflow用户
提问于 2022-06-14 15:55:48
回答 1查看 118关注 0票数 2

当所需的系统调用在父进程中恢复时,Ptrace选项不会设置正确的状态。我只能使用在这里看到的没有PEEKUSER,SYSGOOD或SYSCALL。在过去的几天里,我已经读过这篇文章,并寻找了一些例子,我精神上精疲力竭。

任何想法/建议,无论多小,都是受欢迎的。谢谢。

论点:/bin/bash -c "echo 'first test' | wc -c"

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>

int wait_for_syscall(pid_t child) {
    int status;
    while (1) {
        ptrace(PTRACE_CONT, child, 0, 0);
        waitpid(child, &status, 0);
        if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
            return 0;
        if (WIFEXITED(status))
            return 1;
    }
}

int main(int argc, char *argv[]) {
    int status;
    int counter = 0;
    pid_t pid = fork();
    if (pid < 0)
        exit(1);
    else if (pid == 0) {
        ptrace(PTRACE_TRACEME, pid, NULL, NULL);
        raise(SIGSTOP);
        return execve(argv[1], &argv[1], NULL);
    } else {
        wait(&status);
        ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC | PTRACE_O_TRACESECCOMP);

        while (1) {
            if (wait_for_syscall(pid) != 0) break;
            
            if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)))
                counter++;

            if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
                counter++;

            if (wait_for_syscall(pid) != 0) break;
        }
    }
    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-14 16:32:17

在主循环中,使用范围为statusmain

这不是您在wait_for_syscall中设置的相同的wait_for_syscall(它有自己的status的私有副本)。

因此,status in main从未更新过。

要修复,可以传递指向wait_for_syscall的指针

我保留了它的原样,但我相信循环中对wait_for_syscall的第二个调用是无关的,实际上可能会悄悄地吸收syscall。

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>

int
wait_for_syscall(pid_t child,int *stp)
{
    int status;

    while (1) {
        ptrace(PTRACE_CONT, child, 0, 0);

        waitpid(child, &status, 0);
        *stp = status;

        if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
            return 0;
        if (WIFEXITED(status))
            return 1;
    }
}

int
main(int argc, char *argv[])
{
    int status;
    int counter = 0;

    pid_t pid = fork();
    if (pid < 0)
        exit(1);

    if (pid == 0) {
        ptrace(PTRACE_TRACEME, pid, NULL, NULL);
        raise(SIGSTOP);
        return execve(argv[1], &argv[1], NULL);
    }

    wait(&status);
    ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC | PTRACE_O_TRACESECCOMP | PTRACE_O_TRACECLONE);

    while (1) {
        if (wait_for_syscall(pid,&status) != 0)
            break;

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)))
            counter++;

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
            counter++;

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)))
            counter++;

        if (wait_for_syscall(pid,&status) != 0)
            break;
    }

    return 0;
}

更新:

我明白了。它关闭bc,现在它只进行一次迭代,然后就停止了。所以它不会继续/转到下一个系统调用。:( - Olivia22

好吧,我玩过一些变奏曲。以下是一些变化:

除了

  1. PTRACE_O_TRACEFORK之外,还需要PTRACE_O_TRACECLONE (这是一件大事;-)

PATH)

  • 使用execvp来保存环境变量(例如,

  • )

  1. waitpid应该为pid获取-1以捕获子节点,等等,

我添加了调试打印(dbgprt)

ptrace(PTRACE_CONT,...)

  1. 添加了signo

下面是重构代码(包含大量调试):

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>

#define SHOW(_sym) \
    dbgprt(#_sym ": %8.8X %8.8X\n",_sym,SIGTRAP | (_sym << 8))

#define dbgprt(_fmt...) \
    do { \
        int sverr = errno; \
        printf(_fmt); \
        errno = sverr; \
    } while (0)

#define ONERR(_expr) \
    do { \
        if (! (_expr)) \
            break; \
        dbgprt("ONERR " #_expr " line %d -- %s\n",__LINE__,strerror(errno)); \
        exit(1); \
    } while (0)

int
main(int argc, char *argv[])
{
    int status;
    int counter = 0;
    long err;

    pid_t pidm = getpid();

    pid_t pid0 = fork();
    if (pid0 < 0)
        exit(1);

    if (pid0 == 0) {
        ptrace(PTRACE_TRACEME, pid0, NULL, NULL);
        //raise(SIGSTOP);
#if 0
        execve(argv[1], &argv[1], NULL);
#else
        execvp(argv[1], &argv[1]);
#endif
        exit(97);
    }

    dbgprt("main: pid0=%d/%d\n",pid0,pid0 - pidm);
    dbgprt("main: SIGSTOP %d\n",SIGSTOP);
    dbgprt("main: SIGTRAP %d\n",SIGTRAP);

    SHOW(PTRACE_EVENT_EXEC);
    SHOW(PTRACE_EVENT_SECCOMP);
    SHOW(PTRACE_EVENT_CLONE);

#if 0
    err = ptrace(PTRACE_ATTACH,pid0,0,0);
    ONERR(err < 0);
#endif

    err = waitpid(-1,&status,0);
    ONERR(err < 0);

#if 1
    unsigned int opt = 0;
    opt |= PTRACE_O_EXITKILL;
    opt |= PTRACE_O_TRACEEXEC;
    opt |= PTRACE_O_TRACESECCOMP;
    opt |= PTRACE_O_TRACECLONE;
    opt |= PTRACE_O_TRACEFORK;
    err = ptrace(PTRACE_SETOPTIONS, pid0, 0, opt);
    ONERR(err < 0);
#endif

    err = ptrace(PTRACE_CONT,pid0,0,0);
    ONERR(err < 0);

    while (1) {
#if 1
        pid_t pid = waitpid(-1, &status, 0);
#else
        pid_t pid = wait(&status);
#endif

        unsigned int evmsk = status >> 16;

        dbgprt("waitpid: pid=%d/%d status=%8.8X\n",pid,pid - pidm,status);
        dbgprt("waitpid: status %8.8X %8.8X evmsk=%8.8X\n",
            status >> 8,status & 0x7F,evmsk);

        if (pid < 0) {
            dbgprt("waitpid: errno=%d -- %s\n",errno,strerror(errno));
            break;
        }

        if (WIFEXITED(status)) {
            dbgprt("waitpid: WIFEXITED code=%d\n",WEXITSTATUS(status));
            continue;
        }

        int signo = 0;

        do {
            if (WIFSTOPPED(status)) {
                signo = WSTOPSIG(status);
                dbgprt("waitpid: WIFSTOPPED signo=%d\n",signo);
            }

            if (WIFSIGNALED(status)) {
                signo = WTERMSIG(status);
                dbgprt("waitpid: WIFSIGNALED signo=%d\n",signo);
            }
        } while (0);

#if 0
        if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
            return 0;
        if (WIFEXITED(status))
            return 1;
#endif

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
            dbgprt("EXEC\n");
            counter++;
        }

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
            dbgprt("SECCOMP\n");
            counter++;
        }

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
            dbgprt("CLONE\n");
            counter++;
        }

        dbgprt("main: counter=%d\n",counter);

        err = ptrace(PTRACE_CONT, pid, 0, signo);
        ONERR(err < 0);
    }

    return 0;
}

下面是程序调用和输出:

代码语言:javascript
代码运行次数:0
运行
复制
+ ./fix3 /bin/bash -c 'cat /bin/bash | wc -c'
main: pid0=1905216/1
main: SIGSTOP 19
main: SIGTRAP 5
PTRACE_EVENT_EXEC: 00000004 00000405
PTRACE_EVENT_SECCOMP: 00000007 00000705
PTRACE_EVENT_CLONE: 00000003 00000305
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905217/2 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905217/2 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905217/2 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905218/3 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905218/3 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905218/3 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905219/4 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905220/5 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905220/5 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905220/5 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=1
waitpid: pid=1905220/5 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905219/4 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905219/4 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=1
waitpid: pid=1905221/6 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905221/6 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905221/6 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=1
waitpid: pid=191190216
05222/7 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905222/7 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905221/6 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905222/7 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=2
waitpid: pid=1905222/7 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905221/6 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=2
waitpid: pid=1905221/6 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=2
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=2
waitpid: pid=1905223/8 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905223/8 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=2
waitpid: pid=1905224/9 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905224/9 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905223/8 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=3
waitpid: pid=1905224/9 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=4
waitpid: pid=1905223/8 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905224/9 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=4
waitpid: pid=1905216/1 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=-1/-1905216 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: errno=10 -- No child processes

更新2:

非常感谢,我会去研究它,看看它是如何工作的。如果0和1在这里意味着什么呢?- Olivia22

为了在这里进行说明,我使用cpp条件来表示旧代码和新代码:

代码语言:javascript
代码运行次数:0
运行
复制
#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

有时,我会输入一些实验代码,但结果会是“不太好”。所以,我将把它包装在一个#if 0中。我将保留它一段时间,以提醒自己,我做了,但它没有工作(例如,PTRACE_ATTACH块)。

条件词是“注释掉”代码的快速方法,它比使用(例如)更干净。/**/对。

当我完成并且我认为代码是最终的,我将删除适当的条件。

一种简单的方法是通过unifdef -k运行代码(我们得到):

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>

#define SHOW(_sym) \
    dbgprt(#_sym ": %8.8X %8.8X\n",_sym,SIGTRAP | (_sym << 8))

#define dbgprt(_fmt...) \
    do { \
        int sverr = errno; \
        printf(_fmt); \
        errno = sverr; \
    } while (0)

#define ONERR(_expr) \
    do { \
        if (! (_expr)) \
            break; \
        dbgprt("ONERR " #_expr " line %d -- %s\n",__LINE__,strerror(errno)); \
        exit(1); \
    } while (0)

int
main(int argc, char *argv[])
{
    int status;
    int counter = 0;
    long err;

    pid_t pidm = getpid();

    pid_t pid0 = fork();
    if (pid0 < 0)
        exit(1);

    if (pid0 == 0) {
        ptrace(PTRACE_TRACEME, pid0, NULL, NULL);
        //raise(SIGSTOP);
        execvp(argv[1], &argv[1]);
        exit(97);
    }

    dbgprt("main: pid0=%d/%d\n",pid0,pid0 - pidm);
    dbgprt("main: SIGSTOP %d\n",SIGSTOP);
    dbgprt("main: SIGTRAP %d\n",SIGTRAP);

    SHOW(PTRACE_EVENT_EXEC);
    SHOW(PTRACE_EVENT_SECCOMP);
    SHOW(PTRACE_EVENT_CLONE);

    err = waitpid(-1,&status,0);
    ONERR(err < 0);

    unsigned int opt = 0;
    opt |= PTRACE_O_EXITKILL;
    opt |= PTRACE_O_TRACEEXEC;
    opt |= PTRACE_O_TRACESECCOMP;
    opt |= PTRACE_O_TRACECLONE;
    opt |= PTRACE_O_TRACEFORK;
    err = ptrace(PTRACE_SETOPTIONS, pid0, 0, opt);
    ONERR(err < 0);

    err = ptrace(PTRACE_CONT,pid0,0,0);
    ONERR(err < 0);

    while (1) {
        pid_t pid = waitpid(-1, &status, 0);

        unsigned int evmsk = status >> 16;

        dbgprt("waitpid: pid=%d/%d status=%8.8X\n",pid,pid - pidm,status);
        dbgprt("waitpid: status %8.8X %8.8X evmsk=%8.8X\n",
            status >> 8,status & 0x7F,evmsk);

        if (pid < 0) {
            dbgprt("waitpid: errno=%d -- %s\n",errno,strerror(errno));
            break;
        }

        if (WIFEXITED(status)) {
            dbgprt("waitpid: WIFEXITED code=%d\n",WEXITSTATUS(status));
            continue;
        }

        int signo = 0;

        do {
            if (WIFSTOPPED(status)) {
                signo = WSTOPSIG(status);
                dbgprt("waitpid: WIFSTOPPED signo=%d\n",signo);
            }

            if (WIFSIGNALED(status)) {
                signo = WTERMSIG(status);
                dbgprt("waitpid: WIFSIGNALED signo=%d\n",signo);
            }
        } while (0);

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
            dbgprt("EXEC\n");
            counter++;
        }

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
            dbgprt("SECCOMP\n");
            counter++;
        }

        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
            dbgprt("CLONE\n");
            counter++;
        }

        dbgprt("main: counter=%d\n",counter);

        err = ptrace(PTRACE_CONT, pid, 0, signo);
        ONERR(err < 0);
    }

    return 0;
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72620023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档