MobileSubstrate
MobileSubstrate 实际上是一个框架,允许第三方的开发者在系统的方法里打一些运行时补丁,扩展一些方法.类似于Application Enhancer(http://www.unsanity.com/haxies/ape).
MobileSubstrate 主要有3部分组成. MobileHooker,MobileLoader 和 safemode.
1 MobileHooker
-------------------------------------------------------------------------------------------------------------------
MobileHooker 用于替换覆盖系统的方法,这个过程被称为Hooking(挂钩). 将使用到2个API:
IMP MSHookMessage(Classclass, SEL selector, IMP replacement, constchar* prefix);// prefix should beNULL.
voidMSHookMessageEx(Classclass, SEL selector, IMP replacement, IMP *result);
void MSHookFunction(void*function, void*replacement, void**p_original);
MSHookMessage() 在Objective-C中替换implementation。[class Selector] 通过替换并返回原来的执行。挂钩一个类的方法,
在MSHookemessage(EX)中调用Objc_getMetaClass得到提供的元数据和类检索,例如下面的注释。这种动态替换是Objective-c的一个功能.使用method_setImplementation。MSHookMmessage()是线程不安全的,不赞成使用,赞成MSHookMessageEx()
MSHookFunction() 很像 MSHookMessage() 但是 适合于c/c++ 的函数。MSHookFunctin()将写入指令调入指定替换函数,并接会分配一些字节在内存地址,相当于原始切出指令并且跳入原始的挂钩方法。由于iPhone系统默认的内存页不能同时写和执行,一个内核补丁必须申请MSHookFunction() 工作.
截止MobileSubstrate的最新版本,MSHookMessage() 也需要一个内核补丁调用关闭的挂钩的所有正确方法。
代码示例:
使用MSHookfunction:
static void (*original_CFShow)(CFTypeRefobj); // a function pointerto store the original CFShow().
voidreplaced_CFShow(CFTypeRefobj) { // our replacement ofCFShow().
printf("Calling originalCFShow(%p)...", obj);
original_CFShow(obj); // calls the originalCFShow.
printf(" done.\n");
}
...
// hook CFShow to our own implementation.
MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);
// From now on any call to CFShow will pass throughreplaced_CFShow first.
...
CFShow(CFSTR("test"));
使用MSHookMessageEX:
static IMP original_UIView_setFrame_;
void replaced_UIView_setFrame_(UIView*self, SEL _cmd, CGRect frame) { // Note the implicitself and _cmd parameters are needed explicitly here.
CGRect originalFrame = self.frame;
NSLog("Changingframe of %p from %@to %@", self,NSStringFromCGRect(originalFrame),NSStringFromCGRect(frame));
original_UIView_setFrame_(self, _cmd, frame); // Remember to pass self and_cmd.
}
...
MSHookMessageEx([UIView class], @selector(setFrame:), (IMP)replaced_UIView_setFrame_, (IMP*)&original_UIView_setFrame_);
...
myView.frame = CGRectMake(0,0, 100, 100);
注意,如果你挂钩一个类的方法,有必须放一个元类在类参数中。
MSHookMessageEx(objc_getMetaClass("UIView"), @selector(commitAnimations), replaced_UIView_commitAnimations,(IMP *)&original_UIView_commitAnimations);
2 MobileLoader
-------------------------------------------------------------------------------------------------------------------
MobileLoader 加载第三方补丁代码在运行的应用程序中。
MobileLoader先加载它自己在运行的应用程序中时使用DYLD_INSERT_LIBRARIES环境变量。然后查看所有动态库在目录/Library/MobileSubstrate/DynamicLibraries/
并且Dlopen 他们(Dlopen是供用户直接访问(存取)动态链接库的一类函数中的一个).一个扩展将要使用构造函数代码去完成一些工作.
...
// The attribute forces this function to be called onload.
__attribute__((constructor))
static void initialize() {
NSLog(@"MyExt:Loaded");
MSHookFunction(CFShow, replaced_CFShow,&original_CFShow);
}
开发者可能添加 过滤器 来限制延期应该加载或者不是。Filters are implemented as plist thatlives beside the dylib(这句话不知怎样理解),如果 dylib 的名字时foo.dylib,那么过滤器的名字应该是 foo.plist.过滤器应该是一个字典key过滤器。这个另一种词典,包含这些Key:
1)CoreFoundationVersion(array): The extension is loaded onlyif the version of CoreFoundation.framework is above the specified values.Currently, only the first 2 values are checked.
Firmware |
2.0 |
2.1 |
2.2 |
3.0 |
3.1 |
3.2 |
CF version |
478.23 |
478.26 |
478.29 |
478.47 |
478.52 |
478.61 |
2)Bundles(array): 该扩展仅仅加载 运行的应用程序列表中相匹配的ID.
3)Classes (array): 加载该扩展只有 在运行的应用程序中实现指定Objective-C 类.
4)Executables(array):加载该扩展只有一个可执行文件的名称相匹配的运行程序。。这是必须的挂钩没有其它的可以识别特征。
例如, 限制扩展只在 SpringBoard,中加载,Plist 的配置:
Filter = {
Bundles = (com.apple.springboard);
};
你也可以使用此方法来限制扩展只加载到特定应用程序的一个指定的(Bundle)绑定. 例如 UIKit,例如:
Filter = {
Bundles = (com.apple.UIKit);
};
另外,MobileLoader 也挂钩 nilst() 去提高它的性能。并定义安全模式多种信号处理器。
对于标识的应用程序,由于所有嵌入的环境变量被忽略,开发者的应用程序必须明确的 dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib")让MobileLoader运行.
3 Safe mode
-------------------------------------------------------------------------------------------------------------------
当一个扩展在SpringBoard崩溃, MobileLoader会进入设备的安全模式捕捉并且处理。在安全模式下,所有的第三放扩展将失效.
下列信号将调用的安全模式:
1)SIGTRAP
2)SIGABRT
3)SIGILL
4)SIGBUS
5)SIGSEGV
6)SIGSYS
这是我第一次翻译英文技术文档,我承认我的英语很菜,翻译完后,我还云里雾里,不知该怎样使用...--!
有什么不对的地方请指出,谢谢!
原文地址:http://iphonedevwiki.net/index.php/MobileSubstrate