昨天同学推荐了一个最近比较火的游戏「贪吃蛇大作战」,今天已经到了AppStore总榜第二的位置。这两天一有空就会掏出手机玩几盘,不过无尽模式玩到3000分左右就遇到了瓶颈,于是怀着单纯的目的想研究下这个游戏的接口…

图1

使用Charles抓取请求

既然是研究接口,第一步就是看看接口的URL和参数返回都是什么了,请出神器Charles。

图2

通过Charles可以清楚地看到,游戏提交分数的接口和参数,至于返回,貌似没什么用。接下来仔细研究下请求,有几个参数能比较容易的判断他们的含义和作用。

1
2
3
4
5
6
7
8
9
10
11
12
device_id: 设备ID
game_mode: 1是无尽模式 2是限时模式
kill: 击杀次数
length: 蛇的长度
market: 我抓的是iOS设备发的请求,所以这里是apple
platform: 抓到的请求里是1,还不太明白具体的意思
push_channel: 也是1,不明白意思
push_id: 固定值111111111222222223333333344444444,后面逆向apk也证明了这一点
sid: 每次登录都会更新
snake_sign: 签名
uid: 用户ID
version: 我使用的版本是固定值2.1

通过逆向APK获取签名算法

明确了参数的意思,接下来就可以伪造请求了,不过在伪造请求之前,还有一个参数比较麻烦,那就是snake_sign,请求签名,从图中snake_sign的内容看,似乎有点像是一个base64过的东西,不过base64decode发现,根本不可读。与其猜签名算法,不如考虑一下其他办法。

「贪吃蛇大作战」还有安卓版本,并且引导下载的页面提供了apk,于是下载apk,使用jadx-gui进行逆向,使用jadx-gui打开apk后,代码一览无余。

通过查看代码,可以清楚的看到snake_sign字段的签名逻辑,首先将请求中所有参数按ASCII码顺序排列拼接成字符串,然后在字符串前添加POST& + [URL Path],添加后使用Key进行SHA1加密,key也可以在代码中获取到。对加密生成的结果,需要做一次base64,才是最终snake_sign字段的结果。

1
POST&top_list_v2/update_score&device_id=XXX&game_mode=1&kill=1&length=35&market=apple&platform=1&push_channel=1&push_id=111111111222222223333333344444444&sid=XXX&uid=XXX&version=2.1

图3

关于「贪吃蛇大作战」的一些猜测

签名方法已经获取到,本以为可以安心刷分了,但是只成功刷了一次4000分160击杀。猜测可能进入排行版需要人工审核,一个理由是刷完后过了几分钟才显示到排行版,另一个理由是,刷完4000分169击杀后,很快刷了一个高的离谱的分,但是并没有显示在排行榜,后面无论刷多少分都再也没有显示出来过,怀疑可能被人工屏蔽。

另外整个游戏和API的交互只有登录、获取用户信息、获取排行版最高分、提交分数等几种,所以游戏也不是真正的实时。

图4