如图,今天我们要对这个游戏下手,抛弃每天订闹钟的烦恼:

不好意思,我放错了,蚂蚁森林是这张:

先来看看这是个什么页面: 通过查看页面的 UI 元素,可以知道蚂蚁森林是一个 Web 页面。

WKCompositingView是WKWebView的子视图。
接下来的主要目标有了:在客户端调用 JavaScript 代码收取能量。
如何调试任意 App 的 WebView 参见越狱环境全局开启任意 iOS App 的 WebView 调试 (opens new window)。

收取能量部分内容使用 canvas 绘制,没事写写 div 的我,对 canvas 了解不多,换个思路解决该问题,收取能量必然和后台有交互,有交互就存在出错的场景,出错就有 Toast。


那么试试 UNAVAILABLE 能搜出什么?

errorBubbleStateHandle 名字看起来很像收集能量出错的处理逻辑。
继续找下去:

是一个叫做 collectEnergy 的方法,似乎接近我们要的方法了,在这里打个断点,点击收集能量确认一下:

从变量 e 和 t 来看(以及 collectEnergy 在 actions 下),collectEnergy 是 vuex 中的一个 Action。
基本可以肯定这是收集能量相关的逻辑了,只要调用这个方法,我们就能完成手动获取能量的功能。
那么再来看看调用堆栈:

找到了!this.store.dispatch("tree/collectEnergy", [d]),d 应该是对应的能量球,这里还是个数组,说不定可以直接传入多个能量球,一起收集。
继续:


从这里断点可以看到 d 从 bubblePool 获取,bubblePool 是从 this.store.state.tree.bubbles 获取。
那么直接调用 this.store.dispatch('tree/collectEnergy', this.store.state.tree.bubbles.filter(b => b.collectStatus === 'AVAILABLE')) 就可以收集当前用户的全部能量了。
this,收取能量如何访问 this?
在 Safari 上,我们可以在一些相关方法中加个断点,访问 this,更可以在加断点后执行个 window._x_tree = this。
WebKit 内部有个 WKCustomProtocolLoader,负责管理 Web 中资源加载,其中有个私有方法:-(void)connection:(id)arg1 didReceiveData:(id)arg2;。
当 Web 页面 JS 资源文件请求回来时,这个私有方法会被调用,重写 NSData 即可,示例如下:
CHDeclareClass(WKCustomProtocolLoader)
CHMethod2(void, WKCustomProtocolLoader, connection, NSURLConnection *, connection, didReceiveData, NSData *, data) {
if ([connection.currentRequest.URL.absoluteString containsString:@"home.4e2b221412.js"]) {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
dataString = [dataString
stringByReplacingOccurrencesOfString:@"t.prototype._render=function(e,t){var n=this,r=this.store.state.tree.bubbles;"
withString:@"t.prototype._render=function(e,t){window._x_tree = this;var n=this,r=this.store.state.tree.bubbles;"];
NSData *newData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
CHSuper2(WKCustomProtocolLoader, connection, connection, didReceiveData, newData);
} else {
CHSuper2(WKCustomProtocolLoader, connection, connection, didReceiveData, data);
}
}
这样一来我们就可以在客户端直接访问 store,想改什么就改什么了。