【问题标题】:Difference between gdb addresses and "real" addresses?gdb地址和“真实”地址之间的区别?
【发布时间】:2012-04-21 03:12:10
【问题描述】:

如果我在 gdb 中运行 C/C++ 程序(在使用 -g 标志编译之后)并检查某些变量、参数...等的地址,然后在 gdb 之外运行它(使用 ./ ) 这些地址会和我在 gdb 中看到的一样吗?如果它们不同,它们通常是相似的还是完全不同的?

我问这个是因为我有一个缓冲区溢出程序,它在 gdb 中完美运行(有和没有断点),但是当我尝试在 gdb 之外运行它时它不起作用。

【问题讨论】:

  • 关于缓冲区溢出,我建议您尝试 valgrind。
  • 强制程序使用“ulimit -c unlimited”进行核心转储,然后使用gdb检查核心文件。

标签: c++ c gdb hex memory-address


【解决方案1】:

我检查某些变量、参数...等的地址,然后我在 gdb 之外运行它(使用 ./)这些地址是否与我在 gdb 中看到的相同

视情况而定。

  1. 在主可执行文件中定义的全局变量将保留在同一地址(除非可执行文件是使用-fpie 构建并与-pie 标志链接的。
  2. 由于ASLR,在其他共享库中定义的全局变量可能具有截然不同的地址。
  3. 由于 ASLR,局部变量和参数可能会移动几个 K 字节。
  4. 堆分配的变量也可能由于 ASLR 或您的程序是多线程的而急剧移动。

请注意,Linux 上的 GDB 默认禁用 ASLR,以便于调试。您可以使用set disable-randomization off 在 GDB 下重新启用 ASLR。这可能允许您在 GDB 下重现该问题。

我的缓冲区溢出

另请注意,ValgrindAddress Sanitizer 之类的工具在查找缓冲区溢出方面通常比在 GDB 下运行更有效。 Address Sanitizer 尤其很棒,因为它可以在全局变量和堆栈中发现缓冲区溢出(Valgrind 没有)。

【讨论】:

    【解决方案2】:

    您永远不应假设某个代码或变量将位于固定位置。

    过去在大多数操作系统中都是如此,但这是一个安全漏洞。恶意软件使用它来影响程序。操作系统会倾向于打乱地址以提高安全性。

    【讨论】:

    • 我们可以安全地假设在位置相关的可执行文件中,所有全局变量从一次执行到另一次执行都将保持在相同的固定地址。
    • @雇佣俄罗斯人:我没想到会这样。你为什么这么认为?
    • 我不认为,我知道(因为我了解可执行文件如何加载到内存中以及它们是如何链接的)。试试看。
    • @stefanbachert:那是因为代码直接引用了这些地址,并且它们的内存位于 PE 的特殊部分(例如 .data、.bss - 取决于几个因素)。跨度>
    【解决方案3】:

    使用-g 标志编译会增加代码大小,因为它会嵌入可执行的额外信息。

    至于您的缓冲区问题,在出现问题的地方发布一个 sn-p 代码会有所帮助。

    【讨论】:

    • “使用 -g 标志编译会增加代码大小”——不,不会。
    猜你喜欢
    • 2019-07-04
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多