【问题标题】:How do I see full strings in dtruss output?如何在 dtruss 输出中看到完整的字符串?
【发布时间】:2013-11-09 22:37:13
【问题描述】:

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

我怎样才能让dtruss 向我显示应用程序通过 SSL 服务器发送和接收的数据?

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

【问题讨论】:

    标签: macos ssl dtrace


    【解决方案1】:

    dtruss 既是为 DTrace 编写的脚本的优雅示例,也是 DTrace 可以完成的演示。然而,虽然它与trussstrace 的相似性在相对贫瘠的OS X 上受到了热烈欢迎,但我怀疑dtruss 从未打算完全替代两者。

    无论如何,您的问题有点模棱两可:我不确定您是否担心看到的字符串被截断,或者您根本看不到 sendto()recvfrom() 的任何字符串(DTrace 揭示的底层接口)。我会同时解决这两个问题。

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

    #pragma D option strsize=512
    

    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#
    

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

    tracemem(copyin(self->bufp, self->size), 64, self->size);
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 2013-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      • 2017-05-09
      • 1970-01-01
      相关资源
      最近更新 更多