在 OS X 10.13 上对旧的 Director 投影仪进行代码设计 - 可能操纵 __LINKEDIT 段值

codesign an old Director projector on OS X 10.13 - perhaps manipulate __LINKEDIT segment value

(请参阅本文末尾的更新 post)

出于 $ 原因,我需要对我们不能再重新发布的旧 Director 投影仪进行代码签名(无法访问原始源代码或 Director)。

我这样做是因为当 运行 没有签名时,应用程序现在会打开一个 Finder window 并提示 "Where is..." 请求作为嵌入式投影仪资源之一的文件。

但是...如果我 cd 进入 Projector.app 内容(实际上并没有这么叫,但你明白了)并在 Contents/MacOS/ 和 运行 这个来自终端的二进制文件,应用程序启动并且 运行 没问题,一旦它解压了二进制文件末尾的(大概)附加存档...

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.30.2/Common/ChunkCompression.cpp:50: Error: unsupported compressor 8
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.30.2/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Exceptions.plist'
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.30.2/Common/ChunkCompression.cpp:50: Error: unsupported compressor 8
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.30.2/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/AppExceptions.bundle/Exceptions.plist'
271 blocks
1120 blocks
274 blocks
136 blocks
255 blocks
120 blocks
1487 blocks
575 blocks
1128 blocks
570 blocks
104 blocks
2042 blocks
4889 blocks
677 blocks
388 blocks
363 blocks
700 blocks
23010 blocks

...app opens and runs correctly at this point

我不能要求我们的用户这样做(他们非常非技术)所以我猜 "Where is..." 提示是某个方面OS X Gatekeeper,因此我希望对二进制文件进行签名将使它再次单击-运行nable。

当我尝试对二进制文件进行代码签名时 App.app/Contents/MacOS/projector 我得到:

main executable failed strict validation

设置 --no-strict 协同设计选项可提供更多详细信息:

the __LINKEDIT segment does not cover the end of the file (can't be processed)

我认为这是因为 Director 投影仪是一个二进制文件,带有一个包含应用程序其余资源的捆绑存档,附加到可执行文件的末尾。一些 googling shows 其他项目的嵌入式资源也存在类似问题。

我试过使用 macho_edit to see if I could modify the binary, but with no joy. I've also tried signing using jtool,但还是不行。

现在,在 MachOView 中打开二进制文件:

我希望我可以对二进制文件进行十六进制编辑并更改 __LINKEDIT segment 的值,以便它覆盖文件的末尾,因此协同签名将起作用,但我不知道是什么修改后的值应该是,或者如果我需要更改的话还有什么。任何提示表示赞赏。

更新 1 - 响应

我试过调整 __LINKEDIT 段中的 File Size 值,所以这个 + File Offset 与实际二进制文件相同(我试了几次;你实际上需要将 VM Size 更改为与 File Size 相同的值,或者您通过 OS 获得 Killed: 9。如果将 File Size 设置为二进制文件的总大小),但没有运气。使用新的 File SizeVM Size 值,我仍然可以 运行 二进制文件,但我不能对其进行代码签名;但是,我确实 收到略有不同的错误消息 :

file not in an order that can be processed (link edit information does not fill the __LINKEDIT segment)

更新 2 - https://github.com/pyinstaller/pyinstaller/wiki/Recipe-OSX-Code-Signing#pyinstaller-fix-implementation 对同一问题有更多详细信息:

PyInstaller breaks OSX code signing because it appends python code at the end of the binary. Appending data at the end of executable breaks the Mach-o format structure. codesign utility complains with the following messages.

the __LINKEDIT segment does not cover the end of the file (can't be processed)

file not in an order that can be processed (link edit information does not fill the __LINKEDIT segment)
  • Fix __LINKEDIT - File Size (offset + File size == exe size), VM Size- same as 'File Size'

  • Fix LC_SYMTAB - String Table Size - last data in mach-o file (offset + size = exe size on the filesystem) - The data appended to the executable will be part of the 'String Table' (Last data section in Mach-O file).

我会看看修复 LC_SYMTAB 是否有帮助。

如果应用在 Finder 运行 中正常使用时找不到其外部资源,这听起来像是 Gatekeeper Path Randomization 的结果。 OS 在 运行 时将应用移动到隐藏的只读位置,并且找不到资源。

我认为签署应用程序二进制文件本身不会解决此问题并阻止 OS 进行路径随机化。用户要么需要在提取应用程序后将其移动到其他目录,要么您需要将应用程序分发到已使用您的 Developer ID 证书签名的磁盘映像中。 DropDMG(从上面的 post 链接)可以创建签名磁盘映像,这可能值得一试。

__LINKEDITFile Offset + File Size 应该等于物理可执行文件大小。您可以通过双击值、编辑它并保存来修改 MachOView 中的 File Size - 可执行文件应该没问题。只是不要碰 File Offset 因为这肯定会破坏它。

DIrector 使用一种在 Windows 上广泛使用的方案,称为 "Overload"。我在物理文件的末尾附加了一些数据,但超出了可执行映像的大小。 Mach-O 文件不支持此方法。物理图像必须以 LINKEDIT 段覆盖的最后一个字节结束,甚至 LINKEDIT 段内的项目顺序也有明确定义。过去的原因是预绑定,现在是代码设计。

附加数据是初始DIR/DXR目录要先加载。我想这已在稍后通过将 DIR/DXR 添加到应用程序包中得到解决。但是我已经不喜欢导演了,所以我不确定。