微信跳一跳 可以直接更改分数, POST 请求没有校验

文章目录

目前为止,已经刷了成功,后面有可能被封了。上图666

tyt

以下文章来自v2ex大神贴:https://www.v2ex.com/t/419056?p=2

这两天逛 v 站出现了一众微信跳一跳 'AI',已经被刷屏了……

大致思路都是通过计算两点距离,模拟点击起跳来方式来实现的,

可是作为不越狱的苹果党,手里又没安卓机,看着被刷屏刷榜,非常不爽啊

想着抓个包看看能不能模拟下网络请求刷分,结果 ……

发现可以直接伪造 POST 请求刷分

https://gist.github.com/feix/6dd1f62a54c5efa10f1e1c24f8efc417

目前比较麻烦的是

  1. 需要先抓包拿到 sesseion_id
  2. 分数最高只能设置为 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 文件:

更正写错的地方

感兴趣的可以把 小程序 的代码下下来,解包在本地运行玩玩

  1. 用 微信开发者工具新建小游戏,选择空的项目目录,game4fun
  2. wget http://123.125.9.32/resstatic.servicewechat.com/weapp/release/wx7c8d593b2c3a7703/4.wxapkg
  3. python2 unwxapkg.py 4.wxapkg
  4. cp 4.wxapkg_dir/* game4fun/
  5. 重启微信开发者工具后就可以在电脑上运行 跳一跳

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)
})
原创文章:微信跳一跳 可以直接更改分数, POST 请求没有校验 ,未经许可,禁止转载,©版权所有
原文出处:前端开发博客 (http://caibaojian.com/tyt-hack-js.html)