如何跟踪从一开始就与程序不运行它作为根(How to trace a program from it

2019-07-31 02:35发布

我正在写一个工具,通过调用到DTrace跟踪用户指定的程序。

如果我的工具使用DTrace -c运行程序作为的DTrace的子进程,不仅可以我不传递任何参数的程序,但程序与DTrace的,也就是说,作为root(我对所有的权限运行的Mac OS X)。 这使得某些事情应该工作休息,显然使得很多事情是不应该工作成为可能。

其他的解决方案,我知道的是启动该程序自己,通过发送暂停SIGSTOP ,通过它的PID到dtrace -p ,然后通过发送它继续它SIGCONT 。 的问题是,无论是节目几秒钟运行没有同时的DTrace集的符号信息,或者,如果我继续该过程之前入睡了几秒钟被跟踪,DTrace的抱怨objc<pid>:<class>:<method>:entry无探头匹配。

有没有办法,我可以在用户的​​帐户下运行的程序,而不是root的方式,但还是有DTrace的能够从一开始就跟踪它?

Answer 1:

喜欢的东西sudo dtruss -f sudo -u <original username> <command>很适合我,但我这件事后来觉得不好。

我提起了雷达的错误吧,把它关闭为#5108629一式两份。



Answer 2:

如果对方的回答不会为你工作,你可以运行在gdb程序,在主(或更早)打破,得到PID,并启动脚本? 我试过在过去,它似乎工作。



Answer 3:

那么,这是有点老了,但为什么不:-) ..

我不认为有一种方法可以在命令行操作也很简便,但作为建议,一个简单的启动应用程序,如以下,将做到这一点。 手动附着当然也有几个电话到libdtrace更换。

int main(int argc, char *argv[]) {
    pid_t pid = fork();
    if(pid == 0) {
        setuid(123);
        seteuid(123);
        ptrace(PT_TRACE_ME, 0, NULL, 0);
        execl("/bin/ls", "/bin/ls", NULL);
    } else if(pid > 0) {
        int status;
        wait(&status);

        printf("Process %d started. Attach now, and click enter.\n", pid);
        getchar();

        ptrace(PT_CONTINUE, pid, (caddr_t) 1, 0);
    }

    return 0;
}


Answer 4:

这个脚本采用可执行文件的名称(一个应用程序,这是info.plist中的CFBundleExecutable)要监视到的DTrace作为参数(就可以启动这个脚本运行后,目标应用程序):

string gTarget;     /* the name of the target executable */

dtrace:::BEGIN
{
    gTarget = $$1;  /* get the target execname from 1st DTrace parameter */

    /*
    * Note: DTrace's execname is limited to 15 characters so if $$1 has more
    * than 15 characters the simple string comparison "($$1 == execname)"
    * will fail. We work around this by copying the parameter passed in $$1
    * to gTarget and truncating that to 15 characters.
    */

    gTarget[15] = 0;        /* truncate to 15 bytes */
    gTargetPID = -1;        /* invalidate target pid */
}

/*
* capture target launch (success)
*/
proc:::exec-success
/
    gTarget == execname
/
{
    gTargetPID = pid;
}

/*
*   detect when our target exits
*/
syscall::*exit:entry
/
    pid == gTargetPID
/
{
    gTargetPID = -1;        /* invalidate target pid */
}

/*
* capture open arguments
*/
syscall::open*:entry
/
    ((pid == gTargetPID) || progenyof(gTargetPID))
/
{
    self->arg0 = arg0;
    self->arg1 = arg1;
}

/*
* track opens
*/
syscall::open*:return
/
    ((pid == gTargetPID) || progenyof(gTargetPID))
/
{
    this->op_kind = ((self->arg1 & O_ACCMODE) == O_RDONLY) ? "READ" : "WRITE";
    this->path0 = self->arg0 ? copyinstr(self->arg0) : "<nil>";

    printf("open for %s: <%s> #%d",
        this->op_kind,
        this->path0,
        arg0);
}


Answer 5:

创建了启动程序,将等待某种(不一定是文字信号,只是一个参考,它已经准备好)的信号,然后执行exec()你的目标。 现在dtrace的-p的启动程序,一旦DTrace是起来,让Launcher进入。



Answer 6:

dtruss有-n选项,您可以指定要跟踪过程的名称,但不启动它(感谢@ kenorb的答案的后半部分在https://stackoverflow.com/a/11706251/970301 )。 因此,像下面应该这样做:

sudo dtruss -n "$program"
$program


Answer 7:

见我的回答对相关问题 “怎样才能获得DTrace的运行与非root权限的跟踪的命令?” [原文如此]。

从本质上讲,你就可以开始(非根)后台进程来等待1秒为DTrace启动(种族条件对不起),并且探听该进程的PID。

sudo true && \
(sleep 1; cat /etc/hosts) &; \
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $! \
&& kill $!

在链接的答案完全解释。



文章来源: How to trace a program from its very beginning without running it as root
标签: macos dtrace