程序打开特定文件时gdb中断

zda*_*dav 20 linux gdb system-calls strace

背景故事:在strace我运行程序时,我注意到'/ dev/urandom'正在被open编辑.我想知道这个调用的来源(它不是程序本身的一部分,它是系统的一部分).

所以,使用gdb,我试图在发出调用catch syscall open时中断(使用)程序执行open,所以我可以看到一个回溯.问题是open被调用很多次,比如数百次,所以我无法缩小打开/ dev/urandom的特定调用.我该如何缩小特定电话的范围?有没有办法按参数过滤,如果有,我该如何为系统调用做?

任何建议都会有所帮助 - 也许我认为这一切都是错的.

Chr*_*ton 14

GDB是一个非常强大的工具,但有一点学习曲线.

基本上,您想要设置条件断点.

首先使用-i标志来strace或objdump -d来查找open函数的地址,或更实际地找到那里的东西,比如在plt中.

在该地址设置一个断点(如果你有调试符号,你可以使用它们,省略*,但我假设你没有 - 尽管如果没有别的话,你可能会有它们用于库函数.

break * 0x080482c8 
Run Code Online (Sandbox Code Playgroud)

接下来你需要让它有条件

(理想情况下,您可以将字符串参数与所需的字符串进行比较.我在尝试的前几分钟内没有让它工作)

让我们希望我们可以假设字符串是程序中的某个常量或它加载的库之一.您可以查看/ proc/pid/maps以了解加载的内容和位置,然后使用grep验证字符串实际上是在文件中,objdump -s查找它的地址,gdb验证你是否已经实际上通过将地图的高位部分与文件的低部分组合在内存中找到它.(编辑:在可执行文件上使用ldd可能比在/ proc/pid/maps中查找更容易)

接下来,您将需要了解您正在处理的平台的abi,特别是如何传递参数.我最近一直在研究arm,这非常好,因为前几个参数只是在寄存器r0,r1,r2 ......等等.x86不太方便 - 看起来它们在堆栈上,即*($ esp + 4),*($ esp + 8),*($ esp + 12).

所以让我们假设我们在x86上,我们想要检查esp + 4中的第一个参数是否等于我们试图捕获它的常量所找到的地址.只有,esp + 4是指向 char指针的指针.所以我们需要取消引用它进行比较.

cond 1 *(char **)($esp+4)==0x8048514
Run Code Online (Sandbox Code Playgroud)

然后你可以输入run并希望最好

如果你捕获断点条件,并查看信息寄存器和x命令来检查内存似乎是正确的,那么你可以使用return命令渗透备份调用堆栈,直到找到你识别的东西.


Mic*_*zek 5

(改编自问题编辑)

根据克里斯的回答,以下是最终让我得到我想要的东西的过程:

(我试图找到哪些函数正在调用open“/dev/urandom”上的系统调用)

  1. 在可执行文件上使用 ldd 来查找加载的库
  2. grep通过每个 lib(shell 命令)寻找“urandom”
  3. 在十六进制编辑器中打开库文件并查找字符串的地址
  4. 了解如何在系统调用中传递参数(对于打开,文件是第一个参数。在 x86_64 上它是传递的rdi——您的情况可能会有所不同
  5. 现在我们可以设置条件断点:break open if $rdi == _addr_
  6. 运行程序并等待中断发生
  7. 运行bt查看回溯

毕竟我发现 glib 的 g_random_int() 和 g_rand_new() 使用 urandom。如果有人好奇的话,Gtk+ 和 ORBit 正在调用这些函数。


phi*_*294 5

就像安德烈·普埃尔(Andre Puel)所说:

break open if strcmp($rdi,"/dev/urandom") == 0

可能会做的工作。