在MAC与IOS平台上,动态库的后缀一般是dylid,而加载这些动态库的程序叫做dynamic linker(dyld)。这个程序有很多的环境变量来设置程序的一些行为,最为常用的一个环境变量叫做"DYLD_INSERT_LIBRARIES"。它是一个使用冒号分隔的动态库路径字符串,表示一个将要加载运行的动态库额外依赖的其它动态库。通过这个环境变量,我们就可以向应用中注入自己的动态库,进而改变应用运行时的特定行为。而这种方式,也正是mobileSubstrate所使用的最基本方法。
MobileSubstrate又叫Cydia Substrate,它是由Saurik开发的一个框架。第三方开发者调用其API,可以实现给IOS系统打补丁,改变系统或者应用的运行行为。随着时间的发展,Mobilesubstrate也不再仅仅局限于IOS平台,同样提供了对Android平台的支持,同时也支持了c/c++。Mobile Substrate由MobileHooker/MobileLoader/SafeMode三部分组成。
MobileHooker是对外的API部分,它们主要用来替换系统的函数实现。最主要的二个API见下图:
MSHookMessage是非线程安全的,用于替换原函数实现。而MSHookMessageEx则是线程安全,二者主要是在OC的Runtime机制上实现的。MSHookFunction功能与上面两个类似,但主要用于C/C++函数,与OC不同,它另有一套自己的实现方式,有兴趣的同学可以到其wiki上查阅。
MobileLoader的主要功能是将指定目录下的补丁文件(动态库文件)加载到指定的程序中。MobileLoader首先会将自己通过DYLD_INSERT_LIBRARIES加载到目录程序中,然后它会在/Library/MobileSubstrate/DynamicLibraries/目录下寻找需要加载的第三方补丁文件并使用dlopen加载它们。是否加载是通过一个plist文件来控制的,该文件中可以指定目标程序的bundle id等。如下图:
其中CoreFoundationVersion表示该库的版本,第一个值表示大于或等于,第二个值表示小于,具体的值见wiki。
Executables表示目标程序可执行文件的名称。Bundles表示目标程序的bundle id,Mode表示以上条件之间的逻辑关系,Any表示与运算。
SafeMode的主要功能是容错处理。第三方开发者通过MobileSubstrate向系统注入自定义代码时,如果考虑不周就可能导致终端设备处于崩溃的状态。MobileLoader会捕获这个崩溃异常,然后让设备进入SafeMode状态,在这个状态下,所有的第三方补丁都将被禁用,开发者可以比较从容的恢复设备。
MobileSubstrate是cydia实现的基础,现有的越狱开发环境一般使用的是THEOS或者iosopendev,这两者hook功能都是对MobileSubstrate API的封装。而MobileSubstrate又是基于DYLD_INSERT_LIBRARIES方式实现的,因此有些应用(如美团)为了阻止他人的破解,采用了一些措施阻止了DYLD_INSERT_LIBRARIES这种注入方式,基本原理参见链接https://pewpewthespells.com/blog/blocking_code_injection_on_ios_and_os_x.html。方法是在应用编译时加入下图的编译参数:
参考资料:
1.https://wizardforcel.gitbooks.io/ios-sec-wiki/content/chapter7/issue7-1.html
2.http://www.cydiasubstrate.com/inject/darwin/
3.http://blog.timac.org/?p=761
4.https://pewpewthespells.com/blog/blocking_code_injection_on_ios_and_os_x.html