微信跳一跳抓包修改分数-Java实现

作者: Seayon阿阳 分类: Java,技术 发布时间: 2018-01-01 19:15

原改分代码为Python代码,

#!/usr/bin/python
# -*- coding: utf-8 -*-
print("Hello World!")
import requests
import json
import time
from Crypto.Cipher import AES
import base64

action_data = {
    "score": 100,
    "times": 123,
    "game_data": "{}"
}

session_id = "session_id"

aes_key = session_id[0:16]
aes_iv  = aes_key

print(aes_key)

cryptor = AES.new(aes_key, AES.MODE_CBC, aes_iv)

str_action_data = json.dumps(action_data).encode("utf-8")
print("json_str_action_data ", str_action_data)

#Pkcs7
length = 16 - (len(str_action_data) % 16)
print(length)
str_action_data += bytes([length])*length

cipher_action_data = base64.b64encode(cryptor.encrypt(str_action_data)).decode("utf-8")
print("action_data ", cipher_action_data)

post_data = {
  "base_req": {
    "session_id": session_id,
    "fast": 1,
  },
  "action_data": cipher_action_data
}

headers = {
    "charset": "utf-8",
    "Accept-Encoding": "gzip",
    "referer": "https://servicewechat.com/wx7c8d593b2c3a7703/5/page-frame.html",
    "content-type": "application/json",
    "User-Agent": "MicroMessenger/6.6.1.1200(0x26060130) NetType/WIFI Language/zh_CN",
    "Content-Length": "0",
    "Host": "mp.weixin.qq.com",
    "Connection": "Keep-Alive"
}

url = "https://mp.weixin.qq.com/wxagame/wxagame_settlement"

response = requests.post(url, json=post_data, headers=headers,verify=False)
print(json.loads(response.text))

 

以上代码来自https://zhuanlan.zhihu.com/p/32473340 

考虑到很多同学没有Python环境,用起来并不是很方便,故参考此代码改写成Java版本。

GitHub链接:https://github.com/Seayon/Wxtyt_POST_DATA

另外简单写了个Web版提交工具,

http://java.zhaoxuyang.com/WxTyT/ (2018年1月3日 19:20,测试可用。)

但是不管哪种方法,都需要手动抓取微信跳一跳小游戏的session_id,抓包方法可以参考下面的或者自行搜索相关资料。

安卓抓包参考:安卓下使用Packet Capture抓取微信跳一跳小游戏的session_id值

iOS抓包参考:iOS下抓取微信跳一跳小游戏的session_id值

Java实现:

这里写了两个类,一个PKCS7加密的单独类,(参考自 WindCoder

package com;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;

public class Pkcs7Encoder {
    // 算法名称
    static  final String KEY_ALGORITHM = "AES";
    // 加解密算法/模式/填充方式
    static  final String algorithmStr = "AES/CBC/PKCS7Padding";
    private static Key key;
    private static Cipher cipher;
    boolean isInited = false;

    //默认对称解密算法初始向量 iv
    static byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 };

    public static void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr, "BC");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 加密方法
     *      --使用默认iv时
     * @param content
     *            要加密的字符串
     * @param keyBytes
     *            加密密钥
     * @return
     */
    public static byte[] encrypt(byte[] content, byte[] keyBytes) {
        byte[] encryptedText =  encryptOfDiyIV(content,keyBytes,iv);
        return encryptedText;
    }


    /**
     * 解密方法
     *      --使用默认iv时
     * @param encryptedData
     *            要解密的字符串
     * @param keyBytes
     *            解密密钥
     * @return
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
        byte[] encryptedText = decryptOfDiyIV(encryptedData,keyBytes,iv);
        return encryptedText;
    }
    /**
     * 加密方法
     *      ---自定义对称解密算法初始向量 iv
     * @param content
     *              要加密的字符串
     * @param keyBytes
     *              加密密钥
     * @param ivs
     *         自定义对称解密算法初始向量 iv
     * @return 加密的结果
     */
    public static byte[] encryptOfDiyIV(byte[] content, byte[] keyBytes, byte[] ivs) {
        byte[] encryptedText = null;
        init(keyBytes);
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivs));
            encryptedText = cipher.doFinal(content);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }
    /**
     * 解密方法
     *
     * @param encryptedData
     *            要解密的字符串
     * @param keyBytes
     *            解密密钥
     * @param ivs
     *         自定义对称解密算法初始向量 iv
     * @return
     */
    public static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes,byte[] ivs) {
        byte[] encryptedText = null;
        init(keyBytes);
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }
}

执行请求的工具类

package com;

import okhttp3.*;
import org.bouncycastle.util.encoders.Base64;
import org.json.JSONObject;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * @author: Seayon
 * @date: 2017/12/31
 * @time: 21:11
 */
public class Util {
    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    private static final String WXGAME_URL = "https://mp.weixin.qq.com/wxagame/wxagame_settlement";
    public static final String SESSIONID_ERROR = "SESSIONID有误,请检查";

    private static String getActionData(String sessionKey, String encryptedData, String iv) {
        byte[] sessionKeyBy = sessionKey.getBytes();
        byte[] en = new byte[0];
        try {
            en = encryptedData.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] ivBy = iv.getBytes();
        byte[] enc = Pkcs7Encoder.encryptOfDiyIV(en, sessionKeyBy, ivBy);
        return new String(Base64.toBase64String(enc));
    }

    public static String postData(String score, String times, String session_id) {
        String result = null;
        String content = "{\"score\": " + score + ", \"times\": " + times + "}";
        String AES_KEY = null;
        try {
            AES_KEY = session_id.substring(0, 16);
        } catch (Exception e) {
            return SESSIONID_ERROR;
        }

        String AES_IV = AES_KEY;
        OkHttpClient okHttpClient = new OkHttpClient();
        String actionData = Util.getActionData(AES_KEY, content, AES_IV);
        String json = "{\"base_req\":{\"session_id\":\"" + session_id + "\",\"fast\":1},\"action_data\":\"" + actionData + "\"}";
        RequestBody requestBody = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(WXGAME_URL)
                .header("Accept","*/*")
                .header("Accept-Language","zh-cn")
                .header("User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304 MicroMessenger/6.6.1 NetType/WIFI Language/zh_CN")
                .header("Content-Length","680")
                .header("Content-Type","application/json")
                .header("Referer","https://servicewechat.com/wx7c8d593b2c3a7703/5/page-frame.html")
                .header("Host","mp.weixin.qq.com")
                .header("Connection","keep-alive")
                .post(requestBody)
                .build();
        ResponseBody responseBody = null;
        try {
            responseBody = okHttpClient.newCall(request).execute().body();
            result = responseBody.string();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (responseBody != null) {
                responseBody.close();
            }
        }
        return result;
    }
}

执行测试

public class Main {
    public static void main(String[] args) {
        String sessionid = "==";
        String score = "100";
        String times = "700";
        String result = Util.postData(score, times, sessionid);
        System.out.println(result);
    }

目前观察当执行errcode为0时代表成功,此时需要结束杀死微信的后台进程,重新进入微信,打开跳一跳小游戏,可以查看自己的分数,分数千万不要太高,我目前设置过的最高分是1024分,没有被封。

代码中使用到的依赖,Maven :

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-debug-jdk15on</artifactId>
    <version>1.55</version>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20171018</version>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.9.1</version>
</dependency>

云服务器购买推荐 外星云服务器

 

127 条评论
  • 小阳光

    2018年1月1日 下午11:30

    现在fiddler抓包 找不到sessionid了 是empty 这个方法应该失效了

    1. Seayon

      2018年1月2日 上午12:50

      写了个简单的iOS下抓包教程:ios下抓取微信跳一跳小游戏的session_id值

  • 我困扰

    2018年1月1日 下午11:34

    sessionID 指的是啥啊,困扰了好几个小时了。。。。。。

    “Time”: 1999/4/9 13:52:08
    SessionID: 36 83 F8 11 F6

    1. Seayon

      2018年1月2日 上午12:49

      写了个简单的iOS下抓包教程:ios下抓取微信跳一跳小游戏的session_id值

  • 我困扰

    2018年1月1日 下午11:35

    楼上还有跟我一样困扰的哥们,,,,,这个问题让我抓狂。。。。。在线等解答啊

  • 烦躁

    2018年1月2日 上午10:03

    xposed框架和justTrustMe装不上 烦躁

    1. Seayon

      2018年1月2日 下午2:28

      手上没有安卓设备,恕无能为力

      1. 烦躁

        2018年1月2日 下午4:20

        哈哈哈 还是壕的世界

  • koke

    2018年1月2日 下午12:47

    你好,我最先看到的也是这个方法,改了一PHP版本的,昨天试了还有效,今天再试服务端返回108,和上面的python脚本返回结果一样。看到你的web工具可以使用,请教一下是哪里出了问题,谢谢。

    1. Seayon

      2018年1月2日 下午2:27

      现在要删除JSON数据里面的 “game_data”: “{}” 这对键值对。

      1. koke

        2018年1月2日 下午2:43

        赞,这个你是怎么发现的?

        1. Seayon

          2018年1月2日 下午2:44

          是知乎专栏网友说的呀,你是没有仔细看他们的讨论,捂脸.jpg

          1. koke

            2018年1月3日 下午4:21

            https://gist.github.com/Clarence-pan/e809ecd83dc4f3c8aeb2b71f3fffbf48#file-hack-js-L75
            看下这个,里面的参数,我这边正在试,应该可以用

          2. koke

            2018年1月3日 下午5:00

            可以用,我改了PHP版本的

            1. supperdiyer

              2018年1月3日 下午11:35

              兄弟 php 版本的可以share 一下吗

  • 茶树博士丶

    2018年1月2日 下午2:56

    执行结果或腾讯服务器返回的数据: {“base_resp”:{“errcode”:-1}} 是不是已经被修复了啊?

    1. Seayon

      2018年1月2日 下午2:58

      这种情况应该是session_id 无效,你试试随便输入一个session_id,大于16位,都会返回这个错误。

  • Kevin

    2018年1月2日 下午4:55

    话说我测试了一下,显示执行成功,但是分数并没有改

    1. Seayon

      2018年1月2日 下午4:56

      有结束微信后台,等待几分钟再进去试试看吗?

      1. 777

        2018年1月2日 下午4:59

        傻瓜操作有吗?

      2. Kevin

        2018年1月2日 下午5:03

        杀掉进程,然后再进就可以了。话说Mac抓包搞了好久。。。

      3. Kevin

        2018年1月2日 下午5:05

        谢谢谢谢!!!!Charles抓包的,Fiddler 总是下不动,

  • bravecoder

    2018年1月2日 下午5:02

    想提的一点是:

    session_id 和微信账号相关联, session_id 公示或提供给他人 都是有账号安全风险的

    1. 嗨贼王

      2018年1月4日 下午4:49

      这个没办法避免吗?重新登录微信,会更改这个id吗?

    2. 嗨贼王

      2018年1月4日 下午5:10

      如果提供之后,应该怎么避免这种风险呢?重新登录不可以吗?

  • emmm

    2018年1月2日 下午5:27

    为什么我执行的结果报错了。。。

    ——————
    Traceback (most recent call last):
    File “C:\Python27\跳一跳.py”, line 26, in
    cipher_action_data = base64.b64encode(cryptor.encrypt(str_action_data)).decode(“utf-8”)
    File “C:\Python27\lib\site-packages\Crypto\Cipher\blockalgo.py”, line 244, in encrypt
    return self._cipher.encrypt(plaintext)
    ValueError: Input strings must be a multiple of 16 in length

    1. Seayon

      2018年1月2日 下午5:43

      我并不会Python,但是这个原因好像是Python版本得Python 3以上

  • zhaoyi

    2018年1月2日 下午5:28

    能否出个视频教程啊。!小白很多不会。

  • Ali

    2018年1月2日 下午6:13

    sessionid抓不到了么

  • 游客甲

    2018年1月2日 下午7:22

    同学,想问这个代码要在哪个软件运行啊?

    1. Seayon

      2018年1月2日 下午8:55

      一般的 写Java的IDE都可以,比如Eclipse,Intellij IDEA,但是还得先安装JDK

  • wanllk

    2018年1月2日 下午7:37

    我的 id:

    帮我改下好吗,改成5201314

    1. 2018年1月2日 下午10:45

      给你改成66666 成功了么

  • 撸射夫

    2018年1月2日 下午7:39

    楼主大大大,WEB提交的不行了!!!

  • 稻草人

    2018年1月2日 下午7:42

    网站打不开了啊

  • L

    2018年1月2日 下午7:42

    网站打不开了兄弟

  • Null

    2018年1月2日 下午7:45

    web版链接无法打开了

  • wanllk

    2018年1月2日 下午7:50

    DDOS攻击,什么时候能恢复呢?

  • hellc

    2018年1月2日 下午7:53

    哈哈哈哈腾讯难道是来不及修补漏洞,第一时间DDOS掉

    1. Seayon

      2018年1月2日 下午8:13

      哇那真是看得起我 T_T

  • 啦啦啦啦啦

    2018年1月2日 下午9:25

    2018年1月2日21:24:16 成功了 thanks 开心

  • null

    2018年1月2日 下午9:26

    恶意搞我?给我改10000什么意思?

    1. Seayon

      2018年1月2日 下午9:37

      不知道,我没改,千万别泄漏自己的session_id啊!不要发留言板里面。隐私信息需要发给我的话可以发邮件 info@zhaoxuyang.com

      1. null

        2018年1月2日 下午9:43

        那就奇怪了,我就试了下,没几分钟被人改成10000了。不好意思

  • John

    2018年1月2日 下午9:58

    来个视频吧 强烈建议

  • 大西瓜

    2018年1月2日 下午9:59

    谢谢大佬

  • 石头

    2018年1月2日 下午10:01

    key vi 是session_id 0.16 加密吗

    1. Seayon

      2018年1月3日 上午12:58

      这是截取session_id 的前16位字符作为加密时候的 iv值

  • 2018年1月2日 下午11:04

    请求https 会有ssl异常 楼主是通过导出mp.weixin.qq.com的证书保存到本地解决的么?

  • 玫瑰花的葬礼

    2018年1月3日 上午12:27

    12:20可用 谢谢大佬

  • 撸射夫

    2018年1月3日 上午12:45

    楼主!!!!!不行了!!!

  • 刘某

    2018年1月3日 上午1:23

    好像凉了

  • A1013947966

    2018年1月3日 上午1:27

    108了。凉了

  • 炸了

    2018年1月3日 上午1:52

    凉了嘛???弄了好久,一直未知错误-2

  • 帅鹏鹏

    2018年1月3日 上午2:13

    凉凉了怎么办

  • 今天就好

    2018年1月3日 上午3:43

    刚弄好就凉了?

  • MrW

    2018年1月3日 上午5:41

    找的到啊 https://mp.weixin.qq.com/wxagame/wxagame_init 在这个url里

  • 紫隆

    2018年1月3日 上午9:02

    腾讯服务器返回的原始数据:
    {“base_resp”:{“errcode”:108}}
    代表含义:发出的参数有误,频繁出现此错误可能是凉了。

    1. 紫隆

      2018年1月3日 上午9:04

      我这咋整??

  • 飞翔

    2018年1月3日 上午9:04

    error…楼主 我还没刷过呢

  • 谁能帮我改下

    2018年1月3日 上午10:06

    8tQlRvrD3PsVGc4fNRlK8g8pfbPUGYjDJf9IwcQsClDTasGzNQi6rPVdRGY74juXW3COitDG+pDA4sDZxiwX2KPHJjDyqq5jYyImCBE7WL2GVyMd+7jz8itFTPPoR3dfmVXZzgrmf2zkctmGr5IWFw\u003d\u003d

  • SOp

    2018年1月3日 上午10:48

    一首凉凉送给自己

  • 卤煮是可爱的吕孩子

    2018年1月3日 上午11:01

    卤煮是凉了嘛?

  • slipknot

    2018年1月3日 下午1:30

    哈哈。刚还想刷呢报这个了 {“base_resp”:{“errcode”:-5}}看来得另辟蹊径了

  • QAQ

    2018年1月3日 下午2:21

    凉了,求新的。

  • 2018年1月3日 下午2:48

    亮了..

  • 小马

    2018年1月3日 下午3:30

    108了 楼主 。。 求新的,期待,嘻嘻

  • Leo

    2018年1月3日 下午3:45

    现在出现的情况的确不能用了,又增加了验证机制需要提交你手机的info来校验提交者是否为手机端,所以web提交就被错误了

  • 小马

    2018年1月3日 下午4:42

    亲测可用!!

  • Jay

    2018年1月3日 下午5:24

    100000最高了

  • 炸了

    2018年1月3日 下午5:33

    腾讯服务器返回的原始数据:
    {“base_resp”:{“errcode”:-2}}
    代表含义:未知错误

    疯了,一直是这个。。。。

    1. 阿佳

      2018年1月4日 上午12:32

      我也是

  • 飞翔

    2018年1月3日 下午5:35

    大佬 方不方便贴下你的代码 让我看看这次改了什么

    1. Seayon

      2018年1月3日 下午5:37

      待会儿我总结一下贴上去,我自己还挺迷的,核心要点是要伪造game_data里面的参数,且格式必须正确

      1. 飞翔

        2018年1月3日 下午5:38

        好勒 感谢分享 特别是你那个加密解码那块代码 看了好迷…

  • 大佬帮帮忙

    2018年1月3日 下午6:05

    显示执行成功 返回排行看没变化 怎么办?

    1. 博主求助

      2018年1月8日 下午2:38

      我也是,不知道为什么。@博主,求救

  • 尴尬

    2018年1月3日 下午6:14

    呵呵high

  • 没有昵称

    2018年1月3日 下午6:18

    web提交一直显示分数错误是怎么回事 而且也没有周游戏次数