【问题标题】:How to execute a debugger command from within the app如何从应用程序中执行调试器命令
【发布时间】:2020-01-08 00:30:04
【问题描述】:

在运行时,我试图恢复未导出但可通过共享库的符号表获得的函数的地址,因此对调试器可见。

我正在研究需要捕获某些事件并操纵运行时的高级调试程序。其中一项操作需要知道在其他地方用作密钥的私有函数的地址(只是地址)。

我当前的解决方案使用nm 在构建时计算该私有函数相对于已知导出函数的偏移量。此解决方案限制了调试功能,因为它依赖于共享库的特定构建。

最好的解决方案应该是能够在运行时恢复地址。

我希望从应用程序中与附加的调试器进行通信,但很难找到任何 API。

我有什么选择?

【问题讨论】:

  • 你想和调试器交流什么?函数地址?你能把它打印出来然后手动输入调试器吗?
  • 有问题的功能来自我无法控制的第 3 方图像。我需要使用调试器按名称恢复它的地址,以便我可以在应用程序代码的其他地方使用它。
  • 听起来您真正想做的是查询调试数据库以获取有关符号的信息。
  • 我不完全确定这个符号只能通过调试数据库获得:可能还有一个我不知道的链接器标志。

标签: c gdb lldb mach-o


【解决方案1】:

在运行时,我试图恢复未导出但可通过共享库的符号表获得的函数的地址,因此对调试器可见。

调试器不是神奇的独角兽。如果调试器可以使用符号表,那么您的应用程序也可以使用它。

我需要通过名称恢复它的地址使用调试器 ...

那是完全错误的做法。

不要使用调试器,而是读取应用程序中库的符号表,并使用获得的信息来调用目标函数。

读取 ELF 符号表非常容易。 Example。如果您不在 ELF 平台上,获得同等信息应该不会太难。

【讨论】:

  • 我的目标平台是macOS,所以格式是MachO。您是否碰巧知道系统中是否存在具有必要结构定义的标头?
  • @Kentzo 我对 MacOS 了解不多,除了 GDB 和 LLDB 都可以在其上构建。对于 GDB,只需要 Xcode,因此所需的头文件必须在 Xcode 中可用。
  • 您也可以解析 Mach-O 二进制文件并从中提取 DWARF 信息。这是一个 Python 示例:github.com/sevaa/dwex/blob/master/dwex/formats.py filebytespyelftools 库都可以通过 pip 获得。
【解决方案2】:

在 lldb 中,如果调试器通过任何方式知道该地址,您可以通过设置符号断点来快速找到该地址:

b symbolname

如果您想在没有附加调试器的情况下从库中调用非导出函数,有几个选项,但从长远来看,每个选项都不可靠

  • 硬编码导出库的偏移量并调用exportedSymbol+offset(这将适用于特定的库二进制版本,但可能会因其他任何内容而中断)
  • 尝试在加载的库中搜索未导出函数的二进制签名。 (不太容易破解,但二进制签名可能总是会改变)

也许如果您提供更详细的上下文,可以考虑您正在尝试实现更好的选择。

更新:
由于 lldb 以某种方式知道该符号,我怀疑它是在您的库的 Mach-O LC_SYMTAB load 命令中定义的。要验证您是否可以使用 MachOViewMachOExplorer 等工具检查您的 lib 二进制文件。或者 Apple 的 otool 或 Jonathan Levin 的 jtool/jtool2 在控制台中。

这是一个示例,来自 MachOView 中的 LC_SYMTAB 产生的第一个符号条目。这是 /usr/lib/dyld 二进制文件 在此处的示例中,0x1000 是虚拟地址。您的库很可能是 64 位的,因此请期待 0x10000000 及更高版本。实际的基数由 ASLR 随机化,但您可以使用

验证当前值
sample yourProcess

yourProcess 是使用您所追求的库的可执行文件。 输出应包含:

Binary Images:
       0x10566a000 -        0x105dc0fff  com.apple.finder (10.14.5 - 1143.5.1) <3B0424E1-647C-3279-8F90-4D374AA4AC0D> /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
       0x1080cb000 -        0x1081356ef  dyld (655.1.1) <D3E77331-ACE5-349D-A7CC-433D626D4A5B> /usr/lib/dyld
...

这些是加载的地址 0x100000000 被 ASLR 移位。为 dylib 选择这些地址的方式可能存在更多细微差别,但您明白了。

Tbh 我从来不需要以编程方式找到这样的地址,但这绝对是可行的(因为/usr/bin/sample 能够做到)。

从这里实现一些实际的东西:

  1. 解析您的 lib 二进制文件的 Mach-o 标头(请查看 thisthis 了解初学者)
  2. 查找LC_SYMTAB加载命令
  3. 找到基于符号文本的条目并找到虚拟地址(红色框的东西)
  4. 计算 ASLR 并应用移位

有一些用于解析 Mach-O 的 C Apple API。还有一些 Python 代码存在于野外(在逆向工程人员中很流行)。

希望对您有所帮助。

【讨论】:

  • 您很好地掌握了这个问题:我目前的解决方案几乎完全符合您的建议!用更多细节编辑了 Q。
  • 能否详细说明一下 MachO 解析?
  • 添加一些链接,您也可以检查 MachOView 或 MachOExplorer ,但我建议坚持一些相当简单的事情。还可以查看关于 SO 的现有答案,这些答案涵盖了 Mach-O 的一些处理,以了解它是如何完成的。在您进行任何编码之前,我建议您验证我在 MachOView 中编写的内容,以验证它是否真的适用于您的情况。
  • 很好,这似乎比我想象的要容易。必须弄清楚如何在运行时定位库的加载地址。
  • @Kentzo 请分享您的发现和/或代码作为答案,如果您更进一步,因为这是一个相当有趣的案例。
猜你喜欢
  • 1970-01-01
  • 2014-03-08
  • 1970-01-01
  • 2021-02-09
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多