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

时间:2013-11-09 22:37:13

标签: macos ssl dtrace

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

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

在任何人告诉我代理与我控制的SSL服务器的连接之前,是的,我知道这个技巧,并且没有这个特定的应用程序太聪明而不适合它。

1 个答案:

答案 0 :(得分:3)

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

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

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

来改变限制
dtrace(1)

低于#pragma D option strsize=512 现有的dtruss

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

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# 使用DTrace的数据记录缓冲区提供硬限制。如果极少接近极限,则会产生令人不快的结果,即输出可能是压倒性的,而且大部分都是多余的。如果你知道你在寻找字符串,那么你可以简单地使用tracemem();如果你有比我的OS X 10.6.8更现代的DTrace实现,那么你可能会发现你可以写

copyinstr()

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

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