如何在 dtruss 输出中看到完整的字符串?

rui*_*ief 3 macos ssl dtrace

我dtruss在 MacOS X 10.8.5 上使用,试图查看正在运行的应用程序和它与之对话的 SSL 服务器之间的对话。与strace在 Linux 上不同,我没有在输出中看到完整的数据字符串,就像我希望在程序send和recv文件描述符上找到的那样。

如何dtruss向我显示应用程序通过 SSL 服务器发送和接收的数据?

在有人告诉我将连接代理到我控制的 SSL 服务器之前,是的,我知道这个技巧,而且没有这个特定的应用程序太聪明而无法上当。

Rob*_*ris 6

dtruss既是为 DTrace 编写的脚本的优雅示例,也是 DTrace 可以完成的功能的演示。然而,尽管它与相对贫瘠的 OS X相似truss或strace深受欢迎,但我怀疑它dtruss从未打算完全替代两者。

在任何情况下,您的问题都有点含糊:我不确定您是否担心您看到的字符串被截断了,或者您根本看不到sendto()or 的任何字符串recvfrom()(DTrace 显示的底层接口)。我会解决两个问题。

首先,DTrace 在内核中收集数据;用户空间缓冲区是使用 D 语言获得的,copyin()或者copyinstr()在被记录并传输回消费者之前获得——通常是dtrace(1)命令。DTrace 要求在编译时知道其内核缓冲区大小,因此对字符串的其他不可预测长度施加了限制。默认情况下,此限制为 256 字节;如果您看到截断,那么您可以通过添加来更改限制,例如,

#pragma D option strsize=512
Run Code Online (Sandbox Code Playgroud)

下面dtruss的现有pragma.

其次,dtruss是硬编码以了解各种系统调用的格式要求。你不会看到任何缓冲解释为sendto()或recvfrom()在它的输出,因为他们没有在源显式处理。没有什么可以阻止您找到适合添加它们的地方,但您可以编写自己的脚本:

bash-3.2# cat sr.d
#pragma D option rawbytes

syscall::sendto:entry,
syscall::recvfrom:entry
/pid == $target/
{
    self->bufp = arg1;
    self->size = arg2;
}

syscall::sendto:return,
syscall::recvfrom:return
/pid == $target && self->bufp && self->size/
{
    printf("%s():\n", probefunc);
    tracemem(copyin(self->bufp, self->size), 64);
    printf("\n");
    self->bufp = self->size = NULL;
}
bash-3.2# dtrace -qs ./sr.d -p 16988
sendto():

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00  hello...........
        10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

^C

bash-3.2#
Run Code Online (Sandbox Code Playgroud)

请注意,对于字符串,我们必须对tracemem()DTrace 的数据记录缓冲区的使用提供硬性限制。如果很少接近限制,那么这会产生令人恼火的结果,即输出可能是压倒性的并且大多是多余的。如果您知道您正在寻找字符串,那么您可以简单地使用copyinstr();如果您有比我的 OS X 10.6.8 更现代的 DTrace 实现,那么您可能会发现您可以编写

tracemem(copyin(self->bufp, self->size), 64, self->size);
Run Code Online (Sandbox Code Playgroud)

其中第二个参数仍然是对记录的字节数的硬限制,但显示的字节数受可选的第三个参数的限制。

最后,请注意用户地址在进入系统调用时被记录,但仅在退出时使用。这是一个常见的习惯用法,它允许系统调用在必要时对数据进行错误处理——DTrace 本身不会这样做,并且如果被要求跟踪非常驻地址,则会在运行时产生错误。