微信跳一跳-最新可用技(zuo)巧(bi)!

6,945 阅读6分钟
原文链接: zhuanlan.zhihu.com

背景:

微信小游戏跳一跳刚出,很快就刷遍了朋友圈。

楼主自诩一个游戏高手,当然不能错过这次的热度,无奈玩了几次,分数都不是很高,于是决定曲线救国,探寻一下这个游戏的技巧 /** 发朋友圈装逼 */,便打算发挥职业特长,开发点小工具,初步思路是判断方块之前的距离,自动计算按下的时间,然而对着自己的iphone,研究了一会仍一脸懵逼。。

这两天看到自己的的分差距和排行榜差距越来越大,便又重操起了就业。

正文背景开始,知乎和github搜索了下相关辅助,主要是两种。

  1. 抓包后进行请求模拟 详见 微信跳一跳万分攻(作)略(弊)
  2. 图像捕捉自动模拟跳跃 wangshub/wechat_jump_game

第一篇文章中说已经失效,大概看了下方法,具体后面再说

github中的python项目和我一开始的思路一样,而iphone的解决方案wda让我这个没有做过ios开发的弱渣大开眼界,立刻兴奋的clone下来配置好了环境,

连上手机花了近一个小时,终于跳到了千分,看着排行榜第一,远超第二的成绩,我已经可以想象到朋友圈朋友的仰慕眼神= =


然而,关掉手机重新打开后发现分数又回到了惨淡的一百多??

经过一段时间的重试和怀疑人生后,无奈开始动手。

定位问题:

初步猜测有两种可能:

  1. 在用wda模拟跳跃的时候客户端做了作弊检测判断,最终在游戏结束后没有上传成绩。
  2. 作弊判断放在后台,上传成绩后被服务器拒绝。

so,后面毫无疑问,开始抓包:

前人已经铺好路,包分析的过程就不详述了,可以看到是成绩是被服务器端给拒绝了。<del>进行到这一步,那后面就小菜一碟了,打开RTX,联系下微信小程序部门的人,问下跳一跳成绩判断的逻辑规避掉就ok?? <del>

当然上面只是开个玩笑,楼主还是想多干几年的。要想让分数有效上传,那肯定得搞清楚微信对于这个分数,即对于action_data的校验规则。请求的action_data明显是经过加密的,不过这个加密在APK中肯定是存在的。

做好了反编译的准备,下载了微信最新版的apk,不过搜索后发现加密代码在/weixin661android1220_1/assets/whatsnew_embed/wx7c8d593b2c3a7703_3.wxapkg这个揉和了一坨二进制和一坨javascript的文件中,javascript代码是经过uglify的,不过仔细分析也能看出加密的方法:

分析的过程就省略了,直接说结果吧:

数据部分使用AES加密,加密模式为CBC,填充为pkcs7,数据块128位,密钥和偏移量为登陆态session_id的前16位。

附在线解析的网站:在线AES加密解密、AES在线加密解密、AES encryption and decryption

解析数据后如图:

看这数据。。一目了然,很明显是微信加了每一次用户屏幕触点的验证,而用python脚本模拟,每一次都是点的同一个点!之前抓包方式失效的原因也是因为这个。

解决方案

原理明白之后,那剩下的就简单了。只需要对原先两种方式做改进就好:

针对抓包方法:

构造好数据后经过AES加密后得到action_data,再构造请求即可。

如图所示,返回值为0,打开微信确认,装X成功!

————————————————————————————————————————

鉴于此处描述得不是很清楚,故补充一下:

1.首先先在手机玩一局,并抓包,如下图,抓好包后用代码或http构造工具(postman,paw等)添加相应请求头。

2. 抓取包的请求体数据,大概形式是:

{
  "base_req": {"fast":1,"session_id":"xxxxxxxx"},
  "action_data":"xxxxxxxxxxxxxxxxxxx..........."
}

3. 截取action_data数据,在在线AES加密解密、AES在线加密解密、AES encryption and decryption这个网站进行解密,获得数据格式大概为:(加解密规则见上文)

{
  "score":275,
  "times":245,
  "game_data":"{\"seed\":1514966477825,\"action\":[[0.714,1.29,false]...],\"musicList\":[false...],\"touchList\":[[200,200]...],\"version\":1}"
}

其中score为得分,times为总计的分数,game_data为游戏数据,action为每一步的数据,musicList用处未知,不过数量和action一致就好,touchList为用户每一步屏幕的触摸点。

{"score":275,"times":245,"game_data":"{\"seed\":1514966477825,\"action\":[[0.714,1.29,false],[0.764,1.19,false],[0.781,1.16,false],[0.602,1.53,false],[0.777,1.19,false],[0.492,1.77,false],[0.683,1.36,false],[0.366,2,false],[0.635,1.46,false],[0.648,1.43,false],[0.583,1.56,false],[0.715,1.29,false],[0.652,1.43,false],[0.615,1.5,false],[0.697,1.36,false],[0.563,1.63,false],[0.433,1.87,false],[0.433,1.87,false],[0.86,1.06,false],[0.616,1.53,false],[0.558,1.63,false],[0.9,0.95,false],[0.633,1.5,false],[0.517,1.7,false],[0.762,1.19,false],[0.459,1.84,false],[0.899,0.99,false],[0.5,1.73,false],[0.621,1.5,false],[0.396,1.94,false],[0.599,1.56,false],[0.665,1.43,false],[0.339,2.07,false],[0.361,2,false],[0.551,1.63,false],[0.683,1.39,false],[0.735,1.33,false],[0.618,1.5,false],[0.836,1.06,false],[0.747,1.26,false],[0.651,1.43,false],[0.761,1.19,false],[0.564,1.6,false],[0.418,1.9,false],[0.542,1.63,false],[0.282,2.17,true],[0.71,1.36,false],[0.71,1.36,false],[0.383,2,false],[0.766,1.26,false],[0.524,1.7,false],[0.864,1.06,false],[0.534,1.67,false],[0.307,2.14,true],[0.567,1.6,false],[0.781,1.19,false],[0.466,1.84,false],[0.684,1.36,false],[0.723,1.33,false],[0.47,1.8,true],[0.542,1.67,false],[0.436,1.87,true],[0.719,1.33,true]],\"musicList\":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],\"touchList\":[[178,472],[385,293],[200,312],[35,403],[425,167],[264,141],[233,372],[489,470],[122,111],[242,303],[133,369],[95,122],[305,280],[245,189],[268,165],[344,315],[464,184],[26,442],[214,171],[388,218],[285,428],[385,165],[241,51],[161,109],[259,168],[2,135],[477,186],[190,115],[303,403],[81,236],[453,45],[371,45],[292,233],[385,24],[398,94],[242,93],[35,195],[173,45],[240,432],[275,315],[201.3,200.6],[333.2,111],[166.5,503],[159.5,508.5],[143.5,505.5],[149.5,505.5],[143.5,498],[143,497.5],[142,498.5],[138,493],[135.5,491.5],[130,493],[130.5,495],[127,492.5],[127,491.5],[127,488.5],[133.5,499.5],[136,493.5],[131.5,496],[129,497.5],[118.5,497],[123.5,495],[110.5,497]],\"version\":1}"} 

上述是我跑的一个数据,可以在其基础上进行扩充。

如把分数*4,action,musicList,touchList的数量各复制四份发送就能得到1100的数据,当然也可以完全重新构造,注意一些后台检查规则就行,如总分与后面游戏数据计算相同,触摸点不能连续多次重复,游戏次数与后面数据条数相同等。

4. 将构造好的数据经过aes加密放入action_data并在http构造工具中填充请求包。

发送请求,返回errcode为零

如果为-2说明解析action_data错误,为108表示监测到作弊,被拒绝。

打开微信确认:

OK,大功告成!😯

Python模拟法

只需要每次模拟长按不同的地方即可,对于上面提到的github项目

def jump(distance):
    press_time = distance * time_coefficient / 1000
    print('press time: {}'.format(press_time))
    s.tap_hold(200, 200, press_time)

 // ========>
 
 def jump(distance):
    press_time = distance * time_coefficient / 1000
    print('press time: {}'.format(press_time))
    s.tap_hold(random.uniform(0, 500), random.uniform(0, 500), press_time)

将jump函数增加随机参数,改为下面的即可!

全文完,欢迎拍砖和点赞关注~