背后的故事:在strace
下运行程序时,我注意到'/ dev / urandom'正在被open
。 我想知道这个调用来自哪里(这不是程序本身的一部分,它是系统的一部分)。
所以,使用gdb,我打算catch syscall open
(使用catch syscall open
)程序执行时, open
调用发出,所以我可以看到一个回溯。 问题是open
被称为很多 ,像几百倍,所以我不能缩小打开/ dev / urandom的具体调用。 我应该如何去缩小具体的电话? 有没有一种方法来过滤参数,如果是的话,我怎么做一个系统调用?
任何build议都会有所帮助 – 也许我正在做的这一切都是错误的。
GDB是一个非常强大的工具,但有一点学习曲线。
基本上,你想设置一个条件断点。
首先使用-i标志strace或objdump -d来查找打开函数的地址,或者在实际的链中找到某些东西,比如在plt中。
在这个地址设置一个断点(如果你有调试符号,你可以使用这些符号,省略*,但我假设你不这样做 – 尽管如果没有别的东西,你可能会有它们的库函数。
break * 0x080482c8
接下来你需要使它有条件
(理想情况下,您可以将字符串参数与所需的字符串进行比较,在尝试的最初几分钟内,我没有得到这个工作)
让我们希望我们可以假设这个字符串是程序中的某个常量,或者是它加载的一个库。 你可以查看/ proc / pid / maps来得知什么是加载和在哪里,然后使用grep来验证字符串实际上是在一个文件中,objdump -s找到它的地址,gdb来验证你已经实际上通过将地图的高部分与文件的低部分结合在一起,在内存中找到了它。 (编辑:它可能比使用/ proc / pid / maps更容易在可执行文件上使用ldd)
接下来,您需要了解您正在处理的平台的abi,具体说明如何通过参数。 最近我一直在使用arm,这是非常好的,因为前几个参数只是进入寄存器r0,r1,r2 …等等。x86有点不太方便 – 看起来他们在栈上,即* ($ esp + 4),*($ esp + 8),*($ esp + 12)。
因此,我们假设我们在x86上,并且我们想要检查esp + 4中的第一个参数是否等于我们为了捕获它传递的常量而找到的地址。 只有esp + 4是一个指向字符指针的指针。 所以我们需要对它进行解引用来进行比较。
cond 1 *(char **)($esp+4)==0x8048514
然后你可以打字跑步,并希望最好的
如果你捕捉到了断点的条件,并用信息寄存器和x命令来检查内存是否正确,那么你可以使用return命令渗透备份调用堆栈,直到找到你认识的东西。
(改编自问题编辑)
克里斯的回答之后 ,这里是最终得到我所寻找的过程:
(我试图找到什么函数调用“/ dev / urandom”上的open
系统调用)
grep
通过每个lib(shell命令)寻找“urandom” rdi
传递 – 你的里程可能会有所不同 break open if $rdi == _addr_
bt
来查看回溯 毕竟,我发现glib的g_random_int()和g_rand_new()使用urandom。 Gtk +和ORBit正在调用这些函数 – 如果有人好奇的话。
像Andre Puel一样说:
break open if strcmp($rdi,"/dev/urandom") == 0
可以做这个工作。