你如何看待gdb中更改指针的值?

时间:2013-09-20 19:57:52

标签: c gdb buffer-overflow

我有另一个指针(**A)的指针(*B)。在程序的某个地方,B正在被破坏。但是,B存储在*A之前已损坏B并非始终位于同一地址(&B并非始终相同)。但是B总是被相同的值损坏(B总是相同的)。我知道这是因为我有一个腐败检测例程,它查看要存储在*A上的 next 值,所以我只知道它已经被破坏的点。

我想要的(当然)是找出B被破坏的地方。

我已经在A上尝试了一个gdb观察点,该点会自动生成A点(*A)上的观察点,以期在B时抓住*A它首先存储在*A上,然后再存储在*A上,变为损坏,然后存储回watch A commands silent watch *A commands silent if *A == magicalcorruptedvalue where end end end

*A

但问题是,对于硬件观察点,{{1}}上存储了太多中间内容,因此我很快就会耗尽观察点。我没有尝试过软件观察点,因为它们与线程不兼容。

此时,我认为唯一的解决方案是要回过头来仔细阅读代码(总是一个不错的选项),构建更多的单元测试,或者创建一个只扫描所有已分配内存的专用线程这个值。

然而,我怀疑我不是第一个遇到这个问题的人。用于表达这个问题的更多通用方法可能是:当所有简单技术都失败时,调试缓冲区溢出的技术是什么?

元参数:

  • 在Linux上

  • 这是一个多线程回调式应用程序。

1 个答案:

答案 0 :(得分:0)

我想出了两个答案,其中一个答案对我有效。

  1. 使用正确的工具完成工作。 gdb用于调试程序流程。 valgrind似乎更适合调试内存/缓冲区错误。用valgrind运行程序,我很快发现了这个bug。

  2. 理论上实际上有一种方法可以在gdb中执行此操作。在实践中,如果*A变化相对较少,那么它就足够快了。不是在这个特定程序中改变的10k +次。

  3. 这是:

    set $A = (void ***) &whateveritis
    set $B = (void **) 0
    set $WPN = 2
    set $WP = 0
    watch *$A
    commands
      silent
      set $B = *$A
      if $WP != 0
        delete $WP
        set $WP = 0
      end
      if $B != (void *) 0
        watch *$B
        commands
          silent
          if *$B == magicalcorruptedvalue
            where
          else
            continue
          end
        end
        set $WP = $WPN++
      end
      continue
    end
    

    这会在A上设置一个观察点,删除先前*A上存在的任何先前的观看(最终将设置为B),然后设置当前{{ 1}}。手表总是在寻找神奇的腐蚀值,虽然在我的情况下,*A存储在B时的任何变化都会出错,所以我省略了整个部分。

    请注意,$ WPN是下一个断点的编号。请注意由于临时隐式断点(例如通过*A创建的断点)而发生的变化。

    这应该有效,但请注意,在我的情况下,程序是如此陷入困境,以至于它从未进入腐败部分,因此start的观察点从未被绊倒过。 YMMV。

    回到真实的世界里,没有人能用gdb做任何复杂的事情。这里的课程是:(1)了解那里有哪些工具。 Valgrind是惊人的,我完全不确定任何C程序员,包括我自己,在没有它的情况下是如何应对的。 (2)仔细考虑问题域及其与您尝试使用的工具的关系。如果该工具不适合,请使用或写入其他内容。不要让语言欺骗你:只是因为你“调试”并不意味着你应该用“调试器”来做。