iOS安全:修改Mach-O / 2019-05-25

有的时候我们希望干预Xcode生成Mach-O的过程,在签名之前在Mach-O中插入自定义的segment和section数据。修改Mach-O看似简单却不总是那么好用。

在上文 iOS安全:LC_LOAD_DYLIB和LC_ID_DYLIB 中,我们使用了install_name_tool工具在Xcode Build过程中修改Mach-O依赖库的路径。

但install_name_tool工具的作用毕竟有限,它的主要功能是修改依赖库路径的。那么,有没有一种方式,可以允许我们在Xcode Build过程中动态的在Mach-O中插入新的Segment和Section呢?笔者已知的能在build过程中干预Mach-O文件生成有两种方式:

Linker Flags

典型的例子就是在Mach-O中新增__RESTRICT段防止注入,具体做法是在Other Linker Flags中添加:

-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null

这种做法在多数情况下作用有限,因为我们可能并不是想写入固定的数据。

使用 __attribute__ section

__attribute__((section("segment,section")

将指定的数据储存到指定的segment和section中。

参考:gcc function attribute

示例:

struct __COM_easeapi {
    int count;
    const char *name;
};
volatile struct __COM_easeapi easeapi_section __attribute__ ((section ("__COM,__easeapi"))) = { 255, "name"};

__attribute__((section("segment,section")只能声明C函数,全局(静态)变量,Objctive-C方法及属性。

由于我们需要存储指定信息,典型的做法就是像上述示例中使用结构体变量。这种方式看似解决了问题,但有诸多限制:新插入的section数据必须是静态或全局的,不能运行时生成,特别是__TEXT段由于是只读的限制更大,仅支持绝对寻址,所以也不能使用字符串指针。

__attribute__ section的方式实际上是Mach-O加载到内存后填充数据的,并不能直接填充至Mach-O文件中。

总结

以上两种方式均无法做到在Xcode构建中在Mach-O中填充动态数据,目前没发现更有效的方式。

其它文章

iOS安全:iOS APP注入动态库重打包(非越狱)
iOS安全:使用frida-ios-dump砸壳
iOS安全:Mach-O Type