iOS越狱开发之MobileSubstrate介绍

iOS越狱开发之MobileSubstrate介绍  

2012-08-15 23:37:34|  分类: IOS |  标签:ios   |字号 订阅

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

MobileSubstrate介绍
2012年03月19日 星期一 15:14
MobileSubstrate

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

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


1 MobileHooker

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

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

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_setImplementation。MSHookMmessage()是线程不安全的,不赞成使用,赞成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
    评论
iOS越狱开发中,常用的Hook检测包括以下几种: 1. 检测当前进程是否被其他进程注入 ``` void anti_injection() { char path[1024]; int ret = proc_pidpath(getpid(), path, sizeof(path)); if (ret <= 0) { NSLog(@"anti_injection: proc_pidpath failed"); exit(1); } if (strstr(path, "/Library/MobileSubstrate") != NULL) { NSLog(@"anti_injection: MobileSubstrate detected"); exit(1); } if (strstr(path, "/Library/Frameworks/CydiaSubstrate.framework") != NULL) { NSLog(@"anti_injection: CydiaSubstrate detected"); exit(1); } } ``` 2. 检测是否被调试 ``` void anti_debugging() { int name[4]; struct kinfo_proc info; size_t info_size = sizeof(info); name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PID; name[3] = getpid(); if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) { NSLog(@"anti_debugging: sysctl failed"); exit(1); } if (info.kp_proc.p_flag & P_TRACED) { NSLog(@"anti_debugging: traced"); exit(1); } } ``` 3. 检测是否被hook ``` void anti_hooking() { const char *functionName = "ptrace"; void *handle = dlopen("/usr/lib/libc.dylib", RTLD_GLOBAL | RTLD_NOW); if (handle == NULL) { NSLog(@"anti_hooking: dlopen failed"); exit(1); } void *ptrace_func = dlsym(handle, functionName); if (ptrace_func == NULL) { NSLog(@"anti_hooking: dlsym failed"); exit(1); } if (ptrace_func != (void *)&ptrace) { NSLog(@"anti_hooking: hook detected"); exit(1); } } ``` 4. 检测是否被注入Cycript等调试工具 ``` void anti_cycript() { char *cycript = strstr(getenv("DYLD_INSERT_LIBRARIES"), "cycript"); if (cycript != NULL) { NSLog(@"anti_cycript: cycript detected"); exit(1); } } ``` 此外,还可以在代码中添加闪退检测断点,当程序发生闪退时就可以打断点进行调试,例如: ``` void crash_handler(int signal) { signal(SIGTRAP, NULL); NSLog(@"crash_handler: signal=%d", signal); exit(1); } void set_crash_handler() { signal(SIGTRAP, crash_handler); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值