【问题标题】:gdb break when program opens specific file程序打开特定文件时 gdb 中断
【发布时间】:2011-08-17 07:31:34
【问题描述】:

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

因此,使用 gdb,我试图在发出 open 调用时中断(使用 catch syscall open)程序执行,因此我可以看到回溯。问题是open 被称为alot,大概有几百次,所以我无法缩小打开/dev/urandom 的具体调用范围。我应该如何缩小特定呼叫的范围?有没有办法按参数过滤,如果是这样,我该如何为系统调用进行过滤?

任何建议都会有所帮助——也许我做错了。

【问题讨论】:

  • 你可以简单地做:break open if strcmp($rdi,"/dev/urandom") == 0

标签: linux gdb system-calls strace


【解决方案1】:

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

基本上,你想设置一个条件断点。

首先使用 -i 标志来 strace 或 objdump -d 来查找打开函数的地址,或者更实际地在到达那里的链中找到某个地址,例如在 plt 中。

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

break * 0x080482c8 

接下来你需要让它有条件

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

希望我们可以假设字符串是程序中某处的常量或它加载的库之一。您可以查看 /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 并希望最好

如果您捕捉到断点条件,并使用 info 寄存器环顾四周,并且 x 命令检查内存似乎是正确的,那么您可以使用 return 命令过滤备份调用堆栈,直到找到您识别的内容。

【讨论】:

  • 感谢您的帮助!你几乎让我到了那里......我已经用完整的过程编辑了我的答案。
  • 抱歉,没有意识到您使用的是 64 位系统。
  • 好的,我想我发现:进程重启后地址似乎没有改变,不妨使用 (gdb) info functions [[regex]]
  • the address we found for the constant - 我们什么时候找到地址的?怎么知道字符串Hello.txt 的地址,却不知道它是在何时何地初始化的?换句话说,您的0x8048514 是从哪里获得的?
【解决方案2】:

就像安德烈·普埃尔所说:

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

或许能胜任。

【讨论】:

    【解决方案3】:

    (改编自问题编辑)

    Chris's answer 之后,这是最终让我得到了我想要的东西的过程:

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

    1. 在可执行文件上使用 ldd 来查找加载的库
    2. grep 通过每个库(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 正在调用这些函数——如果有人好奇的话。

    【讨论】:

      猜你喜欢
      • 2015-04-19
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多