用外部符号替换 MacOS Mach-O 二进制文件中的静态符号
Posted
技术标签:
【中文标题】用外部符号替换 MacOS Mach-O 二进制文件中的静态符号【英文标题】:Replace static symbols in MacOS Mach-O binary with external symbols 【发布时间】:2019-07-04 03:08:49 【问题描述】:我有以下场景:
一款专有的 MacOS 游戏,将图形框架 MoltenVK 静态链接到其主要的 Mach-O x86-64 二进制文件中。 链接的 MoltenVK 版本太旧了。 我有一个较新版本的 MoltenVK,格式为.dylib
(如果需要,还有较新版本的 SPIRV 编译器、libVulkan 等,也可以是 dylib 格式)。
旧版和新版 MoltenVK 与 ABI 兼容,这意味着导出的符号 名称 和函数签名在旧版和新版 MoltenVK 中应相同。
以及这次进入 MacOS 链接之旅的根本原因:
游戏在我的 macOS 版本(10.15 Catalina Beta 3)上无法正常运行。由于崩溃回溯,我已将问题隔离到 MoltenVK。 我想测试更新 MoltenVK 是否可以解决问题,既可以作为临时解决方法,也可以帮助开发人员隔离问题。是否可以强制二进制文件使用动态加载的.dylib
中定义的符号版本,而不是二进制文件本身中定义的版本?我想修补我拥有的每个.dylib
s 中可用的 所有 符号,因为如果我只修补某些符号而不修补其他符号,它可能会损坏(大概 MoltenVK 仅在每个符号的代码时才有效框架中来自同一版本的 MoltenVK)。
注意:我无法重新编译游戏的主 Mach-O 二进制文件,因为我没有源代码。如果可能的话,我愿意绕过本地系统上的安全保护措施来执行此操作;无论如何,我接受在运行 Beta(非生产)操作系统时做危险事情的风险。
如果答案和 cmets 专注于所提出问题的技术解决方案,我更愿意,但如果需要进一步的理由,我会尝试尽快隔离这个问题,以便给游戏开发者尽可能多的时间在 macOS 10.15 的最终版本之前修复它。如果我保持沉默,问题就有可能不会被发现;然后人们将升级到最终的 macOS 10.15 并注意到游戏无法运行。这对任何人来说都不好玩,因为那样我们要么留在 Mojave 等待游戏开发者更新他们的游戏,要么可能几周或几个月不玩游戏。
【问题讨论】:
【参考方案1】:静态链接意味着库被有效地嵌入到您的最终可执行二进制文件中。因此,没有简单的技术方法可以挂钩呼叫并将它们重定向到其他地方(例如 DYLD_INTERPOSE
或 DYLD_INSERT_LIBRARIES
允许外部 dylibs)。
修补二进制文件需要遍历游戏进行的每个 MoltenVK 调用,并进行相当繁琐的后期处理。 通过后期处理,我的意思是:
-
使用
dlopen
和dlsym
串联编写一个dyld 调用。你还是会
需要已在二进制文件中使用的 dlopen
和 dlsym
符号(它们是
libSystem aka C std lib,但您仍然需要专用的 dyld 操作码
能够实际使用它们)。最终,您需要将汇编操作码放在二进制文件的某个位置,以使一切正常。这将非常困难。
触发lldb
调试器,准备dlsym
地址以手动调用并为每次调用即时修补二进制文件(您可能需要__TEXT
段中的写入权限才能做到这一点,但这很容易部分)。如果您知道自己在做什么,这可能是最可行的方法。主要缺点是它是不稳定的,如果你破坏了一些东西,你会从头开始。
将LC_LOAD_DYLIB
命令添加到LC_DYLD_INFO_ONLY
引用的二进制和dyld 操作码,这将是超级难
无论如何,你最好的朋友是Hopper
dissassembler 和MachOView
来检查二进制文件。
x86(和/或x86-64)汇编的基本知识必须学习。我认为使用原始源代码可能是一种更可行的选择。
【讨论】:
以上是关于用外部符号替换 MacOS Mach-O 二进制文件中的静态符号的主要内容,如果未能解决你的问题,请参考以下文章