扩展 Mach-O 文件中的部分

Extend section in Mach-O file

我正在尝试从 Dyld_shared_cache 中提取库,需要修复外部引用。

例如,__DATA.__objc_selrefs 部分中的指针通常指向 mach-o 文件之外的数据,为了修复我必须从 dyld 复制相应的 c 字符串并将其附加到__TEXT.__objc_methname节。

虽然根据我对 Mach-O 文件格式的理解,__TEXT.__objc_methname 的这个扩展会移动它后面的所有部分,并会迫使我修复引用它们的所有偏移量和指针。有没有办法在不破坏很多东西的情况下向部分添加数据?

谢谢!

更新
在与 OP 澄清 __TEXT.__objc_methname 的扩展将在 Mach-O post 处理现有可执行文件的过程中发生后,我对这个问题有了新的认识。

另一种做法是创建一个新的加载命令 LC_SEGMENT_64 和一个新的 __TEXT_EXEC.__objc_methname 段/节条目(通常 __TEXT_EXEC 用于某些内核内容,但本质上是相同的__TEXT)。这是一个快速的 POC 来说明这个概念:

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        printf("%lx",[NSObject new]);
    }
    return 0;
}

这样编译:

gcc main.m -c -o main.o 
ld main.o -rename_section __TEXT __objc_methname __TEXT_EXEC __objc_methname -lobjc -lc 

有趣的是只有 ld 到 High Sierra 10.14.6 生成 __TEXT.__objc_methname,在 Catalina 上没有它的踪迹,它的做法不同。

UPDATE2.
玩弄它,我注意到 __objc_methname 工作不需要 __TEXT 段(和 __TEXT_EXEC 的执行权)。 不需要更好的特定段和部分名称:
我可以成功:

__DATA.__objc_methname   
__DATA_CONST.__objc_methname 
__ARBITRARY.__arbitrary 

或者在我的情况下,最后 __DATA 部分
__DATA.__objc_classrefs 原始数据由选择器名称连接在一起。 只要有一个带有选择器名称的正确的空终止 C 字符串就可以了。如果我故意破坏十六进制编辑器或 MachOView 中的 "new[=54=]" 我会得到

"+[NSObject ne]: unrecognized selector sent to instance ..."

启动我的 POC 可执行文件后,肯定会使用该值。

所以总结 __TEXT.__objc_methname 部分本身可能是链接器发出的一些调试器提示。应用程序运行时似乎只需要在内存中的任何位置选择器名称为 char*

感谢@Kamil.S 关于添加新加载命令和部分的想法。

向节中添加更多数据的一种方法是创建一个重复的节和节,并将其插入到 __LINKEDIT 节之前。

  • 滑动 __LINKEDIT 部分,以便我们 space 添加新部分。
    1. 定义滑动量,这个必须是页面对齐的,所以我选择0x4000。
    2. 在相关加载命令中添加滑动量,包括但不限于:
      • __LINKEDIT 段(废话)
      • dyld_info_command
      • symtab_command
      • dysymtab_command
      • linkedit_data_commands
    3. 物理移动文件中的 __LINKEDIT。
  • 复制该部分并更改以下内容1
    • size,应该是你的新数据的长度。
    • addr,应该在空闲的space.
    • offset,应该在free space.
  • 复制段并更改以下内容1
    • fileoff,应该是free的开始space.
    • vmaddr,应该是free的开始space.
    • 文件大小,只要大于您的数据即可。
    • vmsize,必须与文件大小相同。
    • nsects,更改以反映您添加的部分数。
    • cmdsize,更改以反映段命令及其部分命令的大小。
  • 在 __LINKEDIT 段之前插入重复的段和节
  • 更新 mach_header
    • ncmd
    • sizeofcmds
  • 在文件中物理写入额外数据。

  1. 您可以选择更改 segname 和 sectname 字段,但这不是必需的。谢谢Kamil.S!