# 背景
项目中遇到一个问题,需要引入两个 SDK,我们暂且命名为 A 和 B,由于业务需要这两个 SDK 都需要对一个系统函数 C 进行 hook, 但是有一个前提,由于 B 所做的是一个统计相关的 SDK,所以 B 要监控 App 内的所有代码这其中也包括了 SDK A 所做的一些操作,所以我们必须确保 B 在 hook C 函数时候 A 已经对 C 函数 hook 完毕,其实这就涉及到 hook 顺序的问题。
# 研究
先看下代码,我用 hookMethod 来模仿系统方法。
代码语言:javascript复制- (void) TEST_HOOK_TWICE {
[self changeOrginalSelectorName:@"hookedMethod" inClass:@"RootViewController" withCustomSelectorName:@"swizzle_hookedMethod1" isClassMethod:NO];
[self changeOrginalSelectorName:@"hookedMethod" inClass:@"RootViewController" withCustomSelectorName:@"swizzle_hookedMethod2" isClassMethod:NO];
[self hookedMethod];
}
- (void)hookedMethod {
NSLog(@"原始方法");
}
- (void)swizzle_hookedMethod1 {
NSLog(@"1");
[self swizzle_hookedMethod1];
}
- (void)swizzle_hookedMethod2 {
NSLog(@"2");
[self swizzle_hookedMethod2];
}
然后看下没有 hook 之前的样子
然后我们执行代码
代码语言:javascript复制//第一步:交换A中的方法和系统方法
[self changeOrginalSelectorName:@"hookedMethod" inClass:@"RootViewController" withCustomSelectorName:@"swizzle_hookedMethod1" isClassMethod:NO];
//第二步:交换B中的方法和系统方法
[self changeOrginalSelectorName:@"hookedMethod" inClass:@"RootViewController" withCustomSelectorName:@"swizzle_hookedMethod2" isClassMethod:NO];
//第三步:调用系统方法
[self hookedMethod];
然后我们一步一步来看,先看调用第一步之后是什么样子的 (红色箭头为第一步之后的样子)
然后看第二步调用完之后的样子 (绿色是第二步调用)
接下来我们调用系统方法也就是第三步,然后我们看下流程是怎样的 (每个方法实现里面都会递归调用下自身,为了是 hook 时候不改变原有逻辑)
这样一来就很明显 如果想想监控住所有的代码那就需要在 A IMP 这步,因为之前的 Hook 顺序是先 A -> B -> System 这样一来只要我们改一下顺序改为 B -> A -> System 就可以让 B SDK 监控到所有的代码。
底层 runtime Hook