iOS HOOK

1.CydiaSubstrate Hook

CydiaSubstrate,iOS7越狱之前名为 MobileSubstrate(简称为MS或MS框架),作者为大名鼎鼎的Jay Freeman(saurik)。

在用theos开发中,control文件中的depend字段依赖库为mobilesubstrate,该工具实现CydiaSubstrate注入的关键所在,整个工具主要分为MobileHookerMobileLoader以及Safe mode三部分。

MobileHooker,是CydiaSubstrate的一个组件,对CObjective-C均有效。

MobileHooker组件主要提供了MSHookMessageExMSHookFunction两个函数针对不同语言的inline hook功能,其中MSHookMessageEx负责用来hook Objective-C函数,MSHookFunction负责用来hook C/C++函数。

MSHookMessageEx对于ObjC函数采用的也是method swizzle的方法,主要是Objetive-C的runtime机制,可以在ObjC方法时动态采用class_replaceMethod等runtime函数替换其实现。MSHookFunction对于C函数是在函数的开头修改了汇编指令,使其跳转到新的实现,执行完成后再返回执行原指令。

1.1MSHookMessageEx函数

MSHookMessageEx函数的作用对象是Objective-C函数,其原理是调用Objective-C中高等级的运行时函数API:class_getInstanceMethodmethod_setImplementationmethod_exchangeImplementations等来替换原函数的逻辑,比如method_exchangeImplementations函数在Objective-C官方文档中描述的作用便是交换两个函数的实现,其内部的调用逻辑类似于:

IMP imp1 = method_getImplementation(m1);
IMP imp2 = method_getImplementation(m2);
method_setImplementation(m1, imp2);
method_setImplementation(m2, imp1);

因此,MSHookMessageEx就是利用Objective-C中运行时的API来替换原函数逻辑。

MSHookMessageEx函数的使用方法,在CydiaSubstrate官网中该函数的描述如下:

void MSHookMessageEx(Class _class, SEL message, IMP hook, IMP *old);

其中第一个参数_class为要Hook的Objective-C函数的类名;第二个参数message为要Hook的Objective-C函数的message;第三个参数hook为hook后新的对应该message的执行逻辑,即替换后的函数地址;第四个参数old为对应该message的原函数的地址,若无需调用原函数则该参数可以设为NULL。其官方的使用方法如下:

NSString *(*oldDescription)(id self, SEL _cmd);

// implicit self and _cmd are explicit with IMP ABI
NSString *newDescription(id self, SEL _cmd) {
    NSString *description = (*oldDescription)(self, _cmd);
    description = [description stringByAppendingString:@"!"];
    return description;
}

MSHookMessageEx(
    [NSObject class], @selector(description),
    &newDescription, &oldDescription
);

以上的代码首先创建指针oldDescription用于保存原来的NSString类description方法的地址,随后实现了新的description方法,最后调用MSHookMessageEx函数来替换原来的description方法。

第一个参数为[NSObject class]类,第二个参数为方法description的message,第三个参数为替换后新的description方法地址,第四个参数为description方法的原地址。

按照官网的示例可以在Tweak工程的Tweak.xm源文件中调用MSHookMessageEx函数来hook想要hook的方法,也可以使用Logos语法来hook相关函数,实际上Logos语法只是对MSHookMessageEx函数进行了封装,实际上其调用的还是MSHookMessageEx函数。官方链接

1.2MSHookFunction函数

MSHookFunction函数的作用对象是C/C++函数,因为C/C++并不提供runtime这种高级的API来直接替换方法实现,因此实现Hook要更加困难一些。MSHookFunction实现Hook采用的是在内存中写入汇编指令来达到目的:简单说来就是首先修改要Hook函数的前N个字节的内存,使其跳转到替换后的函数头,这样就能执行自己的代码;同时会保存原函数的前N个字节的内容以便执行完自己的逻辑后能正确执行原函数的逻辑。具体的汇编实现可以参考这篇分析文章

MSHookFunction的使用方法,在CydiaSubstrate官网中函数的描述如下:

void MSHookFunction(void *symbol, void *hook, void **old);

其中第一个参数为所要Hook的函数地址,值得注意的是该地址不一定限于函数头,也可以是函数内部的任一代码地址;第二个参数为Hook后要替换的函数地址;第三个参数为指向Hook地址的指针,用来保存被Hook函数替换掉的汇编指令方便执行完自己的代码逻辑后能够继续执行原函数的逻辑,若不需要调用原函数,则此处可以设为“NULL”。MSHookFunction官方给出的使用方法如下:

void *(*oldConnect)(int, const sockaddr *, socklen_t);

void *newConnect(
    int socket, const sockaddr *address, socklen_t length
) {
    if (address->sa_family == AF_INET) {
        sockaddr_in *address_in = address;
        if (address_in->sin_port == htons(6667)) {
            sockaddr_in copy = *address_in;
            address_in->sin_port = htons(7001);
            return oldConnect(socket, &copy, length);
        }
    }

    return oldConnect(socket, address, length);
}

MSHookFunction(&connect, &newConnect, &oldConnect);

这段代码首先定义了一个名为oldConnect的指针用于保存要Hook函数被替换的指令;然后实现了新的newConnect方法,即Hook后实际想要执行的代码逻辑;最后使用MSHookFunction来对目标函数进行Hook。

第一个参数为原方法connect的地址,第二个参数为实现的新方法地址,第三个参数为用于保存connect被替换的汇编指令的地址。其中“&connect”是MSHookFunction内部调用了CydiaSubstrate的另一个MSFindSymbol函数来实现根据函数名查找其函数地址,更多的MSHookFunction实现原理可以参考以下链接

1.3MobileLoader

该组件的作用是让应用程序加载第三方的dylib,theos工程编译后生成的dylib就需要MobileLoader组件来加载。

MobileLoader的原理主要是在系统启动时由launchd进程将MobileLoader加载进内存,随后MobileLoader会利用DYLD_INSERT_LIBRARIES环境变量将自己加载进设备的各个进程中,并会遍历/Library/MobileSubstrate/DynamicLibraries/目录下的文件,根据和每个dylib同名的plist文件来确定该dylib的作用范围,若当前进程满足该作用范围,则会使用dlopen函数动态加载对应的dylib

比如实验设备/Library/MobileSubstrate/DynamicLibraries/目录下便可已看到以下文件:

XXXX-iPhone:~ root# ls /Library/MobileSubstrate/DynamicLibraries/
MobileSafety.dylib  MobileSafety.plist test.dylib  test.plist

其中test.plist文件便是plist工程配置文件,MobileLoader读取该文件内容如下:

XXXX-iPhone:~ root# cat /Library/MobileSubstrate/DynamicLibraries/test.plist
{
Filter = {
Bundles = (
"com.apple.springboard",
);
};

即进程Bundlescom.apple.springboard时便会加载对应的test.dylib。值得注意的是,MobileLoader加载完每个dylib后会首先调用dylib中用__attribute__((constructor))声明的入口函数,官网给出的示例代码如下:

__attribute__((constructor))
static void initialize() {
  NSLog(@"MyExt: Loaded");
  MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);
}

以上代码便用__attribute__((constructor))声明了入口函数initialize(),MobileLoader加载完该dylib后便会调用initialize()方法打印log并使用MSHookFunction Hook CFShow函数。之前的demo中并未用__attribute__((constructor))声明是因为Logos语法中%hook便封装了该声明,因此会直接进行hook操作。

1.4SafeMode

注入别的进程并改变其逻辑一定存在风险,难免会造成程序崩溃的现象,如果崩溃的是SpringBoard等系统进程,则会造成系统瘫痪。为了避免这类情况,SafeMode会捕获SIGABRT、SIGILL、SIGBUS、SIGSEGV、SIGSYS这几种信号,捕获到目标信号后SafeMode会使设备进入安全模式,在安全模式下所有第三方插件(即dylib)都会被禁用,便于修复系统。

2.fishhook

对C函数有效,对Objective-C不知道是否有效。

fishhook的原理是替换mach-o里的符号表,符号表的作用可以简单理解成,代码在执行到一个函数符号时,不知道这个符号对应的函数实现在内存的哪个地址,需要去一个表里查找这个地址。如果你更改了这个地址,那么函数实现就被改变了。

3.method swizzle

仅针对Objective-C方法有效。

method swizzle的原理主要是Objetive-C的runtime机制,可以在ObjC方法时动态采用class_replaceMethod等runtime函数替换其实现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 工具名称用途区别备注 theos、iosOpenDev生成dylib insert_dylib、optool、yo...
    XX开发从开始到放弃阅读 4,016评论 0 6
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,635评论 0 9
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,612评论 4 59
  • 每个生命都想成为自己,当不能用成长的方式时,就会用反抗的方式来表达这份意志,如果反抗无效,极有可能会走向毁...
    鲍弘军阅读 158评论 0 0