用外部符号替换MacOS Mach-O二进制文件中的静态符号

时间:2019-07-04 03:08:49

标签: macos dyld

我有以下情况:

  • 一种专有的MacOS游戏,它将图形框架MoltenVK静态链接到其主要的Mach-O x86-64二进制文件中。
  • 链接的MoltenVK版本很旧。
  • 我有.dylib形式的MoltenVK的较新版本(以及较新版本的SPIRV编译器,libVulkan等,如果需要,也可以dylib形式)。
  • 旧版本和新版本的MoltenVK都兼容ABI,这意味着导出的符号名称和功能签名应该与旧版本的MoltenVK相同。

这是MacOS链接之旅的根本原因:

  • 游戏无法在我的macOS版本(10.15 Catalina Beta 3)上正常运行。由于崩溃回溯,我已将问题隔离到MoltenVK。
  • 我想测试更新MoltenVK是否可以解决问题,既可以作为临时解决方法,又可以帮助开发人员隔离问题。

是否可以强制二进制文件使用动态加载的.dylib中定义的符号版本,而不是二进制文件本身中定义的版本?我想修补我拥有的每个.dylib中可用的所有符号,因为如果我仅修补某些符号而不修补其他符号,它可能会损坏(大概是MoltenVK仅在框架中的每个符号都来自相同版本的MoltenVK。

注意:由于我没有源代码,因此我无法重新编译游戏的主要Mach-O二进制文件。如果可能的话,我愿意绕过我本地系统上的安全保护措施;无论如何,我都接受在运行Beta(非生产)操作系统时做危险事情的风险。

我希望答案和评论都集中在所提出问题的技术解决方案上,但是如果需要进一步的论证,我试图尽快隔离该问题,以使游戏开发者有更多时间来解决问题。在macOS 10.15的最终版本之前对其进行修复。如果我保持沉默,则该问题有可能不会被发现;然后人们将升级到最终的macOS 10.15,并注意到游戏无法正常工作。这对任何人来说都是不好玩的,因为那样我们要么就呆在Mojave上,等待游戏开发者更新他们的游戏,要么要等上几周或几个月不使用游戏。

1 个答案:

答案 0 :(得分:1)

静态链接表示该库已有效烘焙到最终的可执行二进制文件中。因此,没有简单的技术方法来挂接呼叫并将它们重定向到其他地方(例如DYLD_INTERPOSEDYLD_INSERT_LIBRARIES允许使用外部dylib)。

修补二进制文件将需要遍历游戏进行的每个MoltenVK调用,并进行相当繁琐的后期处理。 通过后期处理,我的意思是:

  1. 使用dlopendlsym串联编写一个程序调用。你仍然会 需要已在二进制文件中使用的dlopendlsym符号(它们是 libSystem aka C std lib,但是您仍然需要专用的dyld操作码 才能真正使用它们)。最终,您需要将汇编操作码放在二进制文件中的某处,以使所有内容正常工作。这将非常困难
  2. 启动lldb调试器,准备手动调用的dlsym地址,并为每个调用动态修补二进制文件(您可能需要在__TEXT段中具有写权限它,但这是简单的部分)。如果您知道自己在做什么,那可能是最可行的方法。主要缺点是易失性,如果您破坏某些内容,则会从头开始。
  3. LC_LOAD_DYLIB引用的二进制和dyld操作码添加LC_DYLD_INFO_ONLY命令,这将是超硬

无论如何,最好的朋友是Hopper反汇编程序和MachOView来检查二进制文件。

必须紧紧掌握x86(和/或x86-64)组装的基本知识。我认为使用原始源代码可能是一种更可行的选择。