目前为止,已经刷了成功,后面有可能被封了。上图666
以下文章来自v2ex大神贴:https://www.v2ex.com/t/419056?p=2
这两天逛 v 站出现了一众微信跳一跳 ‘AI’,已经被刷屏了……
- https://www.v2ex.com/t/418833
- https://www.v2ex.com/t/418775
- https://www.v2ex.com/t/418467
- https://www.v2ex.com/t/418785
- https://www.v2ex.com/t/419011
- https://www.v2ex.com/t/418831
- https://www.v2ex.com/t/419005
- https://www.v2ex.com/t/418905
- https://www.v2ex.com/t/418982
大致思路都是通过计算两点距离,模拟点击起跳来方式来实现的,
可是作为不越狱的苹果党,手里又没安卓机,看着被刷屏刷榜,非常不爽啊
想着抓个包看看能不能模拟下网络请求刷分,结果 ……
发现可以直接伪造 POST 请求刷分
https://gist.github.com/feix/6dd1f62a54c5efa10f1e1c24f8efc417
目前比较麻烦的是
- 需要先抓包拿到 sesseion_id
- 分数最高只能设置为 999,还未找到为啥
如何抓包:
1. 下载最新 [charlesproxy]( https://www.charlesproxy.com/download/)
2. 启动 charlesproxy
3. 配置代理: 设置 > 无线局域网 > 配置代理 > 手动 > IP:电脑 ip,端口:8888
4. 导入 https 证书: 浏览器访问 http://chls.pro/ssl 下载安装证书
5. 启动跳一跳小程序
6. 去 charlesproxy 里查看抓到的请求, https://servicewechat.com/ 域名的请求,请求体里就包含 session_id
突破 999 的分数限制
Just for fun !
另外附上两个个有意思的点:
如何下载小程序源代码
wget http://123.125.9.32/resstatic.servicewechat.com/weapp/release/{appid}/{version_num}.wxapkg
{appid} 为小程序码, {version_num} 为 版本号,示例:
http://123.125.9.32/resstatic.servicewechat.com/weapp/release/wx7c8d593b2c3a7703/3.wxapkg
如何解析 wxapkg 文件:
更正写错的地方
- 去 charlesproxy 里查看抓到的请求, https://mp.weixin.qq.com/wxagame/wxagame_init url 的请求,请求 json 里包含 session_id
- 能够正常解 小程序 wxapkg 包的代码: https://gist.github.com/feix/32ab8f0dfe99aa8efa84f81ed68a0f3e
感兴趣的可以把 小程序 的代码下下来,解包在本地运行玩玩
- 用 微信开发者工具新建小游戏,选择空的项目目录,game4fun
- wget http://123.125.9.32/resstatic.servicewechat.com/weapp/release/wx7c8d593b2c3a7703/4.wxapkg
- python2 unwxapkg.py 4.wxapkg
- cp 4.wxapkg_dir/* game4fun/
- 重启微信开发者工具后就可以在电脑上运行 跳一跳
game.js 文件可以用 chrome 调整后再看,逻辑其实蛮清晰的
好消息,拿 JS 重撸了一遍逻辑,发现 999 这个限制没了,也就是可以任意刷分了……
https://gist.github.com/feix/6dd1f62a54c5efa10f1e1c24f8efc417#file-wx_t1t_hack-js
大家悠着点玩
鉴于留言区有贴 session_id 求组的,增加一个附言: session_id 为 base64 字符串, 示例如下
zmprIsSEt/dxWNTH4iyU4V2uM7p8DTQWg1Op+dR0hwbvBW2bl00IHXuIGssPGoMeydL0thdRoxXa9MWqX1xEbDvk+o+1rLiihz0VDhUgbprjLVC4qBqiUQF54c061IhJ1JjBy79dI2xWYs0G9oyI9A==
session_id 和微信账号相关联, session_id 公示或提供给他人 都是有账号安全风险的
虽然 CDN 方式下载失效了, 原链还是可以下载的,各位 ……
https://servicewechat.com/weapp/release/${appid}/${version_num}.wxapkg
Hack.js,代码2 有人说下面的代码失效,把version=5改为version=6就可以,我没试过。
/* * Recommend run with node v8.9.x or higher version * npm install lodash crypto-js request-promise request * node hack.js */ const version = 5 // the version of t1t const score = 370 // the score you wanna get const playTimeSeconds = score * 0.01 // simulate the playing time (seconds) // replace with your session_id here const session_id = "your session_id" // import libraries const CryptoJS = require('crypto-js') const requestPromise = require('request-promise') const sleep = (time) => { console.log(`sleeping ${time/1000} second(s)....`) return new Promise(resolve => setTimeout(resolve, time)) } const rand = (min, max) => Math.random() * (max - min) + min const randInt = (min, max) => ~~rand(min, max) const sleepRand = (min, max) => sleep(rand(min, max)) const headers = { 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89 MicroMessenger/6.6.1 NetType/WIFI Language/zh_CN', 'Referer': 'https://servicewechat.com/wx7c8d593b2c3a7703/' + version + '/page-frame.html', 'Content-Type': 'application/json', 'Accept-Language': 'zh-cn', 'Accept': '*/*' } const base_req = { 'base_req': { 'session_id': session_id, 'fast': 1 } } const base_site = 'https://mp.weixin.qq.com/wxagame/' // the main proccess async function main(){ let settlementRes, res res = await request("POST", 'wxagame_getuserinfo') await sleepRand(100,300) res = await request("POST", 'wxagame_getfriendsscore') // return let times = res.my_user_info.times + 1 await sleepRand(100,300) res = await request('POST', 'wxagame_init', {version: 9}) await sleepRand(playTimeSeconds * 0.9 * 1000, playTimeSeconds * 1.1 * 1000) await (async function(){ let action = [], musicList = [], touchList = [] for (let i = 0; i < score; i++) { action.push([rand(0.752, 0.852), rand(1.31, 1.36), false]) musicList.push(false) touchList.push([randInt(180, 190), randInt(441, 456)]) } let data = { score: score, times: times, game_data: JSON.stringify({ seed: Date.now(), action: action, musicList: musicList, touchList: touchList, version: 1 }) } let action_data = encrypt(data, session_id) settlementRes = await request('POST', 'wxagame_settlement', {action_data}) })() res = await request("POST", 'wxagame_getfriendsscore') console.log("settlement result: ", settlementRes) console.log("Well done! Happy new year! ") } async function request(method, path, body={}){ console.log('----------------------------------------') console.log(`Sending request: %s %s -- %o`, method, path, body) try { const res = await requestPromise({ method: method, url: base_site + path, headers: headers, json: true, body: {...base_req, ...body}, }) console.log("Response: %o", res) return res } catch (e) { console.error('Failed to get response: ', e) throw e } } function encrypt (text, originKey) { const originKey2 = originKey.slice(0, 16) const key = CryptoJS.enc.Utf8.parse(originKey2) const iv = CryptoJS.enc.Utf8.parse(originKey2) const msg = JSON.stringify(text) const ciphertext = CryptoJS.AES.encrypt(msg, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return ciphertext.toString() } function decrypt (text, originKey) { const originKey2 = originKey.slice(0, 16) const key = CryptoJS.enc.Utf8.parse(originKey2) const iv = CryptoJS.enc.Utf8.parse(originKey2) const bytes = CryptoJS.AES.decrypt(text, key, {iv}) const plaintext = CryptoJS.enc.Utf8.stringify(bytes) return plaintext } // execute! main().catch(e => { console.error("Opps~ ERROR EXIT: ", e) })