iOS越狱开发之MobileSubstrate介绍

转自:http://hi.baidu.com/onejw/blog/item/47c91bdd0751c2c68c102940.html


MobileSubstrate介绍

20120319 星期一 15:14

MobileSubstrate


MobileSubstrate 实际上是一个框架,允许第三方的开发者在系统的方法里打一些运行时补丁,扩展一些方法.类似于 Application Enhancer(http://www.unsanity.com/haxies/ape).


MobileSubstrate 主要有3部分组成. MobileHooker,MobileLoader  safe mode.



1 MobileHooker


-------------------------------------------------------------------------------------------------------------------


MobileHooker 用于替换覆盖系统的方法,这个过程被称为Hooking(挂钩). 将使用到2API


IMP MSHookMessage(Class class, SEL selector, IMP replacement, const char* prefix); // prefix should be NULL.


void MSHookMessageEx(Class class, 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_setImplementationMSHookMmessage()是线程不安全的,不赞成使用,赞成MSHookMessageEx()



MSHookFunction() 很像 MSHookMessage() 但是 适合于c/c++ 的函数。MSHookFunctin() 将写入指令调入指定替换函数,并接会分配一些字节在内存地址,相当于原始切出指令并且跳入原始的挂钩方法。 由于iPhone系统默认的内存页不能同时写和执行,一个内核补丁必须申请MSHookFunction() 工作.


截止MobileSubstrate的最新版本,MSHookMessage() 也需要一个内核补丁 调用关闭的挂钩的所有正确方法。



代码示例:


使用 MSHookfunction:


static void (*original_CFShow)(CFTypeRef obj);  // a function pointer to store the original CFShow().


void replaced_CFShow(CFTypeRef obj) {           // our replacement of CFShow().


  printf("Calling original CFShow(%p)...", obj);


  original_CFShow(obj);                         // calls the original CFShow.


  printf(" done.\n");


}


...


// hook CFShow to our own implementation.


MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);


// From now on any call to CFShow will pass through replaced_CFShow first.


...


CFShow(CFSTR("test"));



使用 MSHookMessageEX:


static IMP original_UIView_setFrame_;


void replaced_UIView_setFrame_(UIView* self, SEL _cmd, CGRect frame) {  // Note the implicit self and _cmd parameters are needed explicitly here.


  CGRect originalFrame = self.frame;


  NSLog("Changing frame 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 on load.


__attribute__((constructor))


static void initialize() {


  NSLog(@"MyExt: Loaded");


  MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);


}


 开发者可能添加 过滤器 来限制延期应该加载或者不是。Filters are implemented as plist that lives beside the dylib(这句话不知怎样理解),如果 dylib 的名字时 foo.dylib,那么过滤器的名字应该是 foo.plist. 过滤器应该是一个字典key过滤器。这个另一种词典,包含这些Key


1) CoreFoundationVersion(array): The extension is loaded only if the version ofCoreFoundation.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值