iOS逆向之Hopper进阶

线上发现了一个bug,需要用自产的热补丁对 Bugly 的一个方法进行替换,改变返回值

/**

*  App 是否发生了连续闪退

*  如果启动SDK 且 5秒内 闪退,且次数达到 3次 则判定为连续闪退

*

*  @return 是否连续闪退

*/+ (BOOL)isAppCrashedOnStartUpExceedTheLimit;

可是重试了很多次发现热补丁都没生效。。。

后面发现我们调用该 Bugly 方法过早,热补丁又生效过迟,所以热补丁一直失效!

没办法直接拦截[Bugly isAppCrashedOnStartUpExceedTheLimit]返回YES。 那我们只能在闪退次数累加的时候进行拦截了,不让它次数累加起来

按照 bugly的注释 次数累加是在应用闪退的时候进行的,这个时候我们热补丁已经加载,可以发挥作用了。 可是我们怎么知道 Bugly 怎么累加闪退次数的呢?

Hopper 登场

iOS逆向之Hopper进阶_第1张图片

之前有简略介绍过 Hopper 逆向的使用,但是找不到文章了。。。

找个项目=> Bugly SDK 丢进去 => 编译,由于是debug包,所以可以不用脱壳,直接找到生成的 app 文件,拖到 hopper 工程窗口中

iOS逆向之Hopper进阶_第2张图片

等 Hopper 解析完,直接输入 Bugly 方法名,找到对应实现的汇编段, 点击 右上角的if(b)f(x)按钮。 hopper 会自动帮我们解析为 OC 代码。

iOS逆向之Hopper进阶_第3张图片
iOS逆向之Hopper进阶_第4张图片

其实可以看到 Bugly 只是个壳,具体逻辑是在BLYSDKManager类中实现的, 我们继续跟进

然后发现[BLYSDKManager isAppCrashedOnStartUpExceedTheLimit]也是个壳, 是直接返回crashedOverFlow方法值。

iOS逆向之Hopper进阶_第5张图片

分析 crashedOverFlow 实现,发现其实是个 get 方法, 直接返回了 bool 类型的 _crashedOverFlow 变量,BLYSDKManager 也实现了该变量的 set 方法。

所以我们重点就变为了,哪里调用setCrashedOverFlow:方法??

iOS逆向之Hopper进阶_第6张图片

看上图,其实直接搜关键字是搜不到调用方的,这个时候需要用到strings tab。

这个 strings 表示搜文本区

iOS逆向之Hopper进阶_第7张图片

因为 OC 以发消息的方式进行方法调用,方法名都会以 strings的方式在常量区内。  后续的 XREF 表示引用到该变量的地方, 可直接点击跳转。

我们跟过去看看

发现只有在-[BLYSDKManager startWithAppId:developmentDevice:config:]+249这一个地方调用了该方法

我们过去看看该方法的实现

iOS逆向之Hopper进阶_第8张图片

发现 Bugly 内部的次数累加是放在NSUserDefaults里面的。  key 名也找到了。 条件确实是 超过3次,就设置闪退标示位 为true

但是哪里对这个值进行累加呢?

所以我们需要找哪里使用了这个com.tencent.bugly.exitedonstartUplimitkey字符串

方法1: 直接读汇编,名字太明显了

iOS逆向之Hopper进阶_第9张图片

方法2: 还是通过 strings tab 进行搜索

引用区太长 直接通过代码来看吧

iOS逆向之Hopper进阶_第10张图片

0000000100eff3f8dq0x0000000100f58d60; @"com.tencent.bugly.exitedonstartUplimitkey", XREF=-[BLYSDKManager startWithAppId:developmentDevice:config:]+202,-[BLYSDKManager startWithAppId:developmentDevice:config:]_block_invoke+49,-[BLYAnalyticsManager willTerminateHandler]+72

可以看到 就3个地方有用到该变量。。 我们排查量就小了

[BLYAnalyticsManager willTerminateHandler]是把累加次数重置0,可以排除    看方法名,应该是收到 系统willTerminate通知的时候调用,就是应用被正常终止时会调用

iOS逆向之Hopper进阶_第11张图片

-[BLYSDKManager startWithAppId:developmentDevice:config:]+202,-[BLYSDKManager startWithAppId:developmentDevice:config:]_block_invoke+49,

有两个区域引用,一个在 block 内,内部逻辑是 重置为0, 可以排除。

外部区域也有两个地方使用,一个 get,一个 set, 那真正累加的代码就是set那块的逻辑了

iOS逆向之Hopper进阶_第12张图片

后面就是还原 bugly 内部逻辑了, OC 伪代码

- (void) startWithAppId:developmentDevice:config: {intcount = [NSUserDefaultsintegerForKey:@"LimitKey"];if(count >=3) {// 累加次数 大等于3,就设置连续闪退成立// isAppCrashedOnStartUpExceedTheLimit 方法返回 YES[selfsetCrashedOverFlow:YES];    }// 对闪退次数进行累加, 并保存回 NSUserDefaultscount +=1;    [NSUserDefaultssetInteger:count forKey:@"LimitKey"];// 如果5秒后 程序还在执行,把闪退次数 重置为 0dispatch_after(5, ^{        [NSUserDefaultssetInteger:0forKey:@"LimitKey"];    });    ...}

其实可以看到 bugly 整个累加的逻辑,现有的热补丁是没法插手的。。。

而且 bugly 并不是在闪退的时候对次数进行累加,而是在一启动的时候就累加,只是 5秒后 或者 系统调用了 willTerminate 通知, 然后把次数重置为 0。

整体逻辑符合 bugly 自己的注释。。。

题外话

怎么判断是 5秒 过后?

dispatch_time(0x0,0x12a05f200)0x12a05f200=5000000000#define DISPATCH_TIME_NOW (0ull)#define NSEC_PER_SEC 1000000000ulldispatch_time(DISPATCH_TIME_NOW, (int64_t)(5*NSEC_PER_SEC)


参考链接:https://www.jianshu.com/p/384dc5bc1cb4


需要企业签的,联系QQ:807224386     微信:wx807224386

你可能感兴趣的:(iOS逆向之Hopper进阶)