Re

Android 比赛

Re

分析流程 #

这个软件呢,其实分析主要就是想要看他拉人获得vip的操作

抓包可以找到一个api

api/user/traveler

这之前token还没有得到,参数

{"deviceId": device, "dev": 随机3字符, "code": '{"p":"PDTVPD"}'}

这个code参数其实开始我也不知道是啥,走了一遍拉人的流程,发现app给我们的邀请链接有p参数,就是邀请码

https://z6mhir31k.xyz?p=PDTVPD

在进到网页中点击下载软件会将邀请码复制到我们的粘贴板上

{"p":"PDTVPD"}

当你进入app时,读取粘贴板的第一条数据

 public static String u() {
        ClipData v0 = FragmentAnim.f.getSystemService("clipboard").getPrimaryClip();
        String v1 = "";
        if(v0 != null && v0.getItemCount() > 0) {
            CharSequence v0_1 = v0.getItemAt(0).getText();
            if(TextUtils.isEmpty(v0_1)) {
                return v1;
            }
            else {
                return v0_1.toString();
            }
        }

        return v1;
    }

deviceId #

顺着上去就发现了deviceId的生成

public final void C() {
        String v0_2;
        String v3_1;
        String v1 = "everb";
        String v2 = "";
        if(a.a.exists()) {
            try {
                ObjectInputStream v0_1 = new ObjectInputStream(new FileInputStream(a.a));
                Object v3 = v0_1.readObject();
                try {
                    v0_1.close();
                    goto label_21;
                }
                catch(Exception v0) {
                }
            }
            catch(Exception v0) {
                v3_1 = v2;
            }

            Log.d(v1, v0.toString());
        }
        else {
            v3_1 = v2;
        }

    label_21:
        if(v3_1 == null) {
            Log.d(v1, "data == null");
            v3_1 = v2;
        }

        if(TextUtils.isEmpty(((CharSequence)v3_1))) {
            v0_2 = String.valueOf(System.currentTimeMillis() + UUID.randomUUID().getLeastSignificantBits());
            try {
                byte[] v0_4 = MessageDigest.getInstance("MD5").digest(v0_2.getBytes());
                StringBuilder v1_1 = new StringBuilder();
                int v5;
                for(v5 = 0; v5 < v0_4.length; ++v5) {
                    String v6 = Integer.toHexString(v0_4[v5] & 0xFF);
                    if(v6.length() < 2) {
                        v1_1.append(0);
                    }

                    v1_1.append(v6);
                }

                v3_1 = v1_1.toString();
            }

他会打开是个名为.CAD的文件,把deviceid写进去,如果像要看一遍生成新device,记得删除这个文件

...

flutter - blutter

0x1 #

手把手带你逆向flutter。

如今flutter的逆向光靠使用reflutter已经有些不行了,在逛github的时候发现了一个项目 worawit/blutter:Flutter移动应用程序逆向工程工具

根据作者的步骤来。

win,先把Visual Studio 2022 给安装上,配置好C/C++的开发环境。

期间因为需要访问github,所以最好使挂上代理,注意将port替换为你代理的端口

set HTTP_PROXY=http://127.0.0.1:port
set HTTPS_PROXY=http://127.0.0.1:port

克隆下来

git clone https://github.com/worawit/blutter.git
cd blutter

安装所需的库文件

python scripts\init_env_win.py

然后把flutter软件里的lib文件夹提出来,如arm64-v8a文件夹,注意两个文件都需要(libapp.so、libflutter.so)

在win的所有应用里面找到Visual Studio 2022 里面的 x64 Native Tools Command Prompt for VS 2022

在里面输入,注意在此终端仍建议挂上代理(需下载很多),一定注意代理

python blutter.py ./app/lib/arm64-v8a ./output

会有相当多的需要编译,cpu都给干烧了

C:\Users\jinchuan\Desktop\2\blutter>python blutter.py ./demo ./output
Dart version: 2.19.3, Snapshot: adb4292f3ec25074ca70abcd2d5c7251, Target: android arm64
Cloning into 'C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3'...
remote: Enumerating objects: 2361, done.
remote: Counting objects: 100% (2361/2361), done.
remote: Compressing objects: 100% (1912/1912), done.
remote: Total 2361 (delta 82), reused 1427 (delta 63), pack-reused 0
Receiving objects: 100% (2361/2361), 1.34 MiB | 197.00 KiB/s, done.
Resolving deltas: 100% (82/82), done.
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 23 (delta 0), reused 7 (delta 0), pack-reused 0
Receiving objects: 100% (23/23), 119.77 KiB | 257.00 KiB/s, done.
Updating files: 100% (23/23), done.
remote: Enumerating objects: 3424, done.
remote: Counting objects: 100% (3424/3424), done.
remote: Compressing objects: 100% (2343/2343), done.
remote: Total 3424 (delta 1159), reused 2165 (delta 1048), pack-reused 0
Receiving objects: 100% (3424/3424), 8.90 MiB | 4.09 MiB/s, done.
Resolving deltas: 100% (1159/1159), done.
Updating files: 100% (3886/3886), done.
-- Configuring done (4.8s)
-- Generating done (0.1s)
-- Build files have been written to: C:/Users/jinchuan/Desktop/2/blutter/build/dartvm2.19.3_android_arm64
[124/268] Building CXX object CMakeFiles\dartvm2.19.3_android_arm64.dir\runtime\vm\profiler_service.cc.obj
C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3\runtime\vm/scope_timer.h(38): warning C4566: 由通用字符名称“\u00B5”表示的字符不能在当前代码页(936)中表示出来
[133/268] Building CXX object CMakeFiles\dartvm2.19.3_android_arm64.dir\runtime\vm\regexp_assembler.cc.obj
C:\Users\jinchuan\Desktop\2\blutter\external\icu-windows\include\unicode/stringoptions.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode  格式以防止数据丢失
C:\Users\jinchuan\Desktop\2\blutter\external\icu-windows\include\unicode/uchar.h(3156): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
//省略n多
C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3\runtime\vm/timer.h(156): warning C4566: 由通用字符名称“\u00B5”表示的字符不能在当前代码页(936)中表示出来
[268/268] Linking CXX static library dartvm2.19.3_android_arm64.lib
-- Install configuration: "Release"
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/dartvm2.19.3_android_arm64.lib
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/include
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/include/analyze_snapshot_api.h
//省略n多
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/platform/utils_win.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/allocation.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/app_snapshot.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/base64.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/base_isolate.h

-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/zone_text_buffer.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvmTarget.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvmTarget-release.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvm2.19.3_android_arm64Config.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvm2.19.3_android_arm64ConfigVersion.cmake
-- Configuring done (1.6s)
-- Generating done (0.0s)
-- Build files have been written to: C:/Users/jinchuan/Desktop/2/blutter/build/blutter_dartvm2.19.3_android_arm64
[22/22] Linking CXX executable blutter_dartvm2.19.3_android_arm64.exe
-- Install configuration: "Release"

以上为编译成功

...

flutter 初探

安装 #

首先我们手搓一个flutter apk来

去官网下载flutter 解压,配置环境bin目录

考虑网络因素,配置国内源,环境变量清华源

export PUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub
export FLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter

配置 #

使用vscode,插件安装flutter,配置flutter sdk的路径

安装dart插件。

ctrl+shift+P 输入flutter 选择 new project,选择application,会生成项目

在里面随便加点加密

在文件pubspec.yaml文件中 dependencies节点下添加依赖

crypto: ^3.0.3

随后在项目的根目录下执行

flutter packages get

main.dart文件

import 'package:crypto/crypto.dart';
import 'dart:convert';

md5加密

md5.convert(utf8.encode("hello")).toString()

先测试一下是否正常安装,随后打包release版本

打包

flutter build apk

反编译 #

使用reflutter来获取dart文件,其中包含了……,使用详见

记得将apk重新签名一遍

打开,在app 数据目录,找到dump.dart文件

当你满脸欢喜的打开,搜索md5,诶,我函数呢,妈的。

frida

Re

查看进程

frida-ps -U
frida-ps -R

注入js,注意这里是软件名,填包名的话会出现process not found

frida -U -1 1.js 软件名
frida -U -l 1.js -f 软件名 --no-pause

正常附加

frida -U -l 1.js 软件名

swap附加

frida -U -l 1.js -f 软件名

报错

"Error: invalid address

setenforce 0

ps |grep keyword  # 查看进程
su kill -9 pid


用一楼工具那个启动为什么会软重启(我也不到这是不是软重启,因为出现了开机动画,但是adb没掉),之后再附加会提示 unable to find process with name 'system_server',设备真机root

端口转发

adb forward tcp:27043 tcp:27043
l8N2iooyp07M9IWa

动态加载dex



Java.perform(function () {

    console.log('dddd')
    // frida有个类加载器,遍历
    Java.enumerateClassLoaders({
        onMatch: function (loader) {
            // 每次匹配到,都要把匹配到的赋值给java默认的loader
            Java.classFactory.loader = loader;
            var TestClass;
            // 没报错就hook到了,报错了就hook下一个,如果全都报错了,没打印东西,那可能就是hook错了。
            try {
                let a = Java.use("okhttp3.b0$a");
                a['a'].overload('java.lang.String', 'java.lang.String').implementation = function (str, str2) {
                    if(str=='X-TOKEN') console.log('b is called' + ', ' + 'str: ' + str + ', ' + 'str2: ' + str2+'this X-TOKEN-----------------');
                    
                    let ret = this.b(str, str2);
                    console.log('b ret value is ' + ret);
                    return ret;
                }
            
        }catch(error) {
            if (error.message.includes("ClassNotFoundException")) {
                console.log(" You are trying to load encrypted class, trying next loader");
            }
            else {
                console.log(error.message);
            }
        }
    },
        onComplete: function () {

        }
    })
})

动态dex,来自看雪论坛

...

ida 动态调试so

Re, Ida

ida 动态调试 so文件

在ida目录下有dbgsrv文件夹,选择合适的

真机用android_server/android_server64,模拟器用android_x86_server/android_x64_server

adb push android_x64_server /data/local/tmp

进入adb shell

adb shell
su
chmod 777 /data/local/tmp/android_x64_server
./data/local/tmp/android_x64_server

转发端口,ida默认端口是23946

adb forward tcp:23946 tcp:23946

手机/模拟器打开app

  • 方法1

    先打开so文件,debug->Remote linux ->Process option 中host 127.0.0.1

    再attch附加

  • 方法2

​ 打开需调试文件对应的ida,degun->attch

​ 模拟器选Remote linux,真机用Remote ARM android/Linux

在列表中找到包名,可用快捷键ctrl+F 搜索

打开后,在右侧 找到Module 找到so需调试的so文件,找不到的注意java代码中的,让他加载有就有了

static {
        System.loadLibrary("JniLib");
    }

注: 在apk lib中有多个文件夹如v8,v7,x86,x84,如遇到ida 反编译不便解读,可尝试换不同的so文件

反编译

签名 #

生成jks文件

keytool -genkeypair -alias ljyhljyh -keypass ljyhljyh -keyalg RSA -keysize 1024 -validity 365 -keystore filename.jks -storepass ljyhljyh

重新签名

jarsigner -verbose -keystore filename.jks -storepass 501937 -signedjar ai3.apk -digestalg SHA1 -sigalg MD5withRSA ai2.apk filename

apktool #

反编译

apktool d apk_name

重新打包

apktool b 文件 -o apk_name

大学搜题

Re

一个搜书的软件,图片还挺高清的,有多个版本。其中包含flutter 开发的版本,且只有32为so文件,但是也有早期的flutter 包含arm-v8a,但是flutter 版本是2.14,用blutter 解析不了这么早的版本,但是转机又来了,拿一台root的机子抓包,我们其实只要图片下载链接,抓到的数据有加密,没想到的是,所有的逻辑都在java中,但是又有so,用frida hook,RC4解密。写个脚本。易得

import json
import base64
key='963ac4d1931cbd65a058145ede2e443c6a59ac4591ec29c27a41545f602da5f93e61372b6840e4120825cb5e786f37ef31cd22941af1d9898bc5ba70303e71f8'
from Crypto.Cipher import ARC4 as rc4cipher

def rc4_algorithm(encrypt_or_decrypt, data, key1):
    if encrypt_or_decrypt == "encrypt":
        key = bytes(key1, encoding='utf-8')
        enc = rc4cipher.new(key)
        res = enc.encrypt(data.encode('utf-8'))
        res=base64.b64encode(res)
        res = str(res,'utf8')
        return res
    elif encrypt_or_decrypt == "decrypt":
        data = base64.b64decode(data)
        key = bytes(key1, encoding='utf-8')
        enc = rc4cipher.new(key)
        res = enc.decrypt(data)
        res = str(res,'utf8')
        return res



# rc4_algorithm('decrypt', 'VDyAGqfU78Qa6tb5z5A1zsaWRwpmSSXjSMh4y0EA5dx1gT7QxBpQzTWoE3Co3WCpWta517pIF48jkloERSwwBRTYDFt4fataFjKQyBYgsgizTIRbgCC/', key)



with open("token.txt",'r',encoding='utf-8') as f:
    jscode=json.load(f)
# print(jscode)
for i in jscode['chapterList']:
    title=rc4_algorithm('decrypt',i['chapterTitle'],key)
    print("### "+title)
    for _ in i['answers']:
        url=rc4_algorithm('decrypt',_['origin'],key)
        print(url)

小程序 逆向

小程序逆向 #

  1. 抓包

    电脑版微信最新版抓不了包,用3.7.6一下的

    微信在登陆时,右上角把代理填上

    把AppData\Roaming\Tencent\WeChat\XPlugin\Plugins里面的东西删了,不影响使用

  2. 解密

    下载aen516954023/wxappUnpacker: 微信小程序本地应用包逆向工具 (github.com)

    解密wxapkg文件,在C:\Users\xxx\Documents\WeChat Files\Applet

    在解密的时候出现各种几把问题,均可参考百度,google等

    可能因为解密不出来wml和wss不能动态调试很难受

    wxapkg文件解包

    其他的单独解

  3. 逆向

    因为没有拿到wml和wss,所以只能静态分析

    还好比较简单

    image-20221018221138862

​ 因为不能调试,不知道最后一个sign传的什么参数,是做的md5

import requests
import execjs

phone='17628818007'
url='https://www.sharewash.cn/saywash/WashCallApi/common/user/requestVerifyCode.api'
data={'phoneNumber':phone,'ssid':'','tokenId':'','sign':''}

with open('../js/2.js','r',encoding='utf-8') as fp:
    js1=fp.read()
ssid=execjs.compile(js1).call('getTime')
data['ssid']=ssid
data['sign']=execjs.compile(js1).call('getsign',ssid,phone)
print(data)
function getsign() {
    var i, g = arguments;
    i = { 'phoneNumber': '17628818007', 'ssid': '', 'tokenId': '' }
    return i.ssid = getTime(), i.tokenId = false || "", i.sign = sign(i)
}
    function r(r) {
        var a = new Array(), n = r.length, s = parseInt(n / 4), f = n % 4, o = 0;
        for (o = 0; o < s; o++) a[o] = e(r.substring(4 * o + 0, 4 * o + 4));
        return f > 0 && (a[o] = e(r.substring(4 * o + 0, n))), a;
    }

    function e(r) {
        var e = r.length, a = new Array(64), n = 0, s = 0, f = 0, o = 0;
        if (e < 4) {
            for (n = 0; n < e; n++) {
                var c = r.charCodeAt(n);
                for (s = 0; s < 16; s++) {
                    var t = 1, l = 0;
                    for (l = 15; l > s; l--) t *= 2;
                    a[16 * n + s] = parseInt(c / t) % 2;
                }
            }
            for (f = e; f < 4; f++) {
                c = 0;
                for (o = 0; o < 16; o++) {
                    t = 1, l = 0;
                    for (l = 15; l > o; l--) t *= 2;
                    a[16 * f + o] = parseInt(c / t) % 2;
                }
            }
        } else for (n = 0; n < 4; n++) {
            c = r.charCodeAt(n);
            for (s = 0; s < 16; s++) {
                t = 1;
                for (l = 15; l > s; l--) t *= 2;
                a[16 * n + s] = parseInt(c / t) % 2;
            }
        }
        return a;
    }

    function a(r) {
        var e;
        switch (r) {
            case "0000":
                e = "0";
                break;

            case "0001":
                e = "1";
                break;

            case "0010":
                e = "2";
                break;

            case "0011":
                e = "3";
                break;

            case "0100":
                e = "4";
                break;

            case "0101":
                e = "5";
                break;

            case "0110":
                e = "6";
                break;

            case "0111":
                e = "7";
                break;

            case "1000":
                e = "8";
                break;

            case "1001":
                e = "9";
                break;

            case "1010":
                e = "A";
                break;

            case "1011":
                e = "B";
                break;

            case "1100":
                e = "C";
                break;

            case "1101":
                e = "D";
                break;

            case "1110":
                e = "E";
                break;

            case "1111":
                e = "F";
        }
        return e;
    }

    function n(r) {
        for (var e = "", n = 0; n < 16; n++) {
            for (var s = "", f = 0; f < 4; f++) s += r[4 * n + f];
            e += a(s);
        }
        return e;
    }

    function s(r, e) {
        var a = k(e), n = f(r), s = new Array(32), b = new Array(32), i = new Array(32), w = 0, v = 0, A = 0, y = 0, h = 0;
        for (A = 0; A < 32; A++) s[A] = n[A], b[A] = n[32 + A];
        for (w = 0; w < 16; w++) {
            for (v = 0; v < 32; v++) i[v] = s[v], s[v] = b[v];
            var g = new Array(48);
            for (y = 0; y < 48; y++) g[y] = a[w][y];
            var p = c(l(t(c(o(b), g))), i);
            for (h = 0; h < 32; h++) b[h] = p[h];
        }
        var I = new Array(64);
        for (w = 0; w < 32; w++) I[w] = b[w], I[32 + w] = s[w];
        return u(I);
    }

    function f(r) {
        for (var e = new Array(64), a = 0, n = 1, s = 0; a < 4; a++, n += 2, s += 2) for (var f = 7, o = 0; f >= 0; f--,
            o++) e[8 * a + o] = r[8 * f + n], e[8 * a + o + 32] = r[8 * f + s];
        return e;
    }

    function o(r) {
        for (var e = new Array(48), a = 0; a < 8; a++) e[6 * a + 0] = 0 == a ? r[31] : r[4 * a - 1],
            e[6 * a + 1] = r[4 * a + 0], e[6 * a + 2] = r[4 * a + 1], e[6 * a + 3] = r[4 * a + 2],
            e[6 * a + 4] = r[4 * a + 3], e[6 * a + 5] = 7 == a ? r[0] : r[4 * a + 4];
        return e;
    }

    function c(r, e) {
        for (var a = new Array(r.length), n = 0; n < r.length; n++) a[n] = r[n] ^ e[n];
        return a;
    }

    function t(r) {
        for (var e = new Array(32), a = "", n = [[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7], [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8], [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0], [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]], s = [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10], [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5], [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15], [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]], f = [[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8], [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1], [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7], [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]], o = [[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15], [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9], [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4], [3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]], c = [[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9], [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6], [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14], [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]], t = [[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11], [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8], [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6], [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]], l = [[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1], [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6], [1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2], [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]], u = [[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7], [1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2], [7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8], [2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]], k = 0; k < 8; k++) {
            var i, w;
            switch (i = 2 * r[6 * k + 0] + r[6 * k + 5], w = 2 * r[6 * k + 1] * 2 * 2 + 2 * r[6 * k + 2] * 2 + 2 * r[6 * k + 3] + r[6 * k + 4],
            k) {
                case 0:
                    a = b(n[i][w]);
                    break;

                case 1:
                    a = b(s[i][w]);
                    break;

                case 2:
                    a = b(f[i][w]);
                    break;

                case 3:
                    a = b(o[i][w]);
                    break;

                case 4:
                    a = b(c[i][w]);
                    break;

                case 5:
                    a = b(t[i][w]);
                    break;

                case 6:
                    a = b(l[i][w]);
                    break;

                case 7:
                    a = b(u[i][w]);
            }
            e[4 * k + 0] = parseInt(a.substring(0, 1)), e[4 * k + 1] = parseInt(a.substring(1, 2)),
                e[4 * k + 2] = parseInt(a.substring(2, 3)), e[4 * k + 3] = parseInt(a.substring(3, 4));
        }
        return e;
    }

    function l(r) {
        var e = new Array(32);
        return e[0] = r[15], e[1] = r[6], e[2] = r[19], e[3] = r[20], e[4] = r[28], e[5] = r[11],
            e[6] = r[27], e[7] = r[16], e[8] = r[0], e[9] = r[14], e[10] = r[22], e[11] = r[25],
            e[12] = r[4], e[13] = r[17], e[14] = r[30], e[15] = r[9], e[16] = r[1], e[17] = r[7],
            e[18] = r[23], e[19] = r[13], e[20] = r[31], e[21] = r[26], e[22] = r[2], e[23] = r[8],
            e[24] = r[18], e[25] = r[12], e[26] = r[29], e[27] = r[5], e[28] = r[21], e[29] = r[10],
            e[30] = r[3], e[31] = r[24], e;
    }

    function u(r) {
        var e = new Array(64);
        return e[0] = r[39], e[1] = r[7], e[2] = r[47], e[3] = r[15], e[4] = r[55], e[5] = r[23],
            e[6] = r[63], e[7] = r[31], e[8] = r[38], e[9] = r[6], e[10] = r[46], e[11] = r[14],
            e[12] = r[54], e[13] = r[22], e[14] = r[62], e[15] = r[30], e[16] = r[37], e[17] = r[5],
            e[18] = r[45], e[19] = r[13], e[20] = r[53], e[21] = r[21], e[22] = r[61], e[23] = r[29],
            e[24] = r[36], e[25] = r[4], e[26] = r[44], e[27] = r[12], e[28] = r[52], e[29] = r[20],
            e[30] = r[60], e[31] = r[28], e[32] = r[35], e[33] = r[3], e[34] = r[43], e[35] = r[11],
            e[36] = r[51], e[37] = r[19], e[38] = r[59], e[39] = r[27], e[40] = r[34], e[41] = r[2],
            e[42] = r[42], e[43] = r[10], e[44] = r[50], e[45] = r[18], e[46] = r[58], e[47] = r[26],
            e[48] = r[33], e[49] = r[1], e[50] = r[41], e[51] = r[9], e[52] = r[49], e[53] = r[17],
            e[54] = r[57], e[55] = r[25], e[56] = r[32], e[57] = r[0], e[58] = r[40], e[59] = r[8],
            e[60] = r[48], e[61] = r[16], e[62] = r[56], e[63] = r[24], e;
    }

    function b(r) {
        var e = "";
        switch (r) {
            case 0:
                e = "0000";
                break;

            case 1:
                e = "0001";
                break;

            case 2:
                e = "0010";
                break;

            case 3:
                e = "0011";
                break;

            case 4:
                e = "0100";
                break;

            case 5:
                e = "0101";
                break;

            case 6:
                e = "0110";
                break;

            case 7:
                e = "0111";
                break;

            case 8:
                e = "1000";
                break;

            case 9:
                e = "1001";
                break;

            case 10:
                e = "1010";
                break;

            case 11:
                e = "1011";
                break;

            case 12:
                e = "1100";
                break;

            case 13:
                e = "1101";
                break;

            case 14:
                e = "1110";
                break;

            case 15:
                e = "1111";
        }
        return e;
    }

    function k(r) {
        var e = new Array(56), a = new Array();
        a[0] = new Array(), a[1] = new Array(), a[2] = new Array(), a[3] = new Array(),
            a[4] = new Array(), a[5] = new Array(), a[6] = new Array(), a[7] = new Array(),
            a[8] = new Array(), a[9] = new Array(), a[10] = new Array(), a[11] = new Array(),
            a[12] = new Array(), a[13] = new Array(), a[14] = new Array(), a[15] = new Array();
        for (var n = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1], s = 0; s < 7; s++) for (var f = 0, o = 7; f < 8; f++,
            o--) e[8 * s + f] = r[8 * o + s];
        s = 0;
        for (s = 0; s < 16; s++) {
            var c = 0, t = 0;
            for (f = 0; f < n[s]; f++) {
                for (c = e[0], t = e[28], o = 0; o < 27; o++) e[o] = e[o + 1], e[28 + o] = e[29 + o];
                e[27] = c, e[55] = t;
            }
            var l = new Array(48);
            switch (l[0] = e[13], l[1] = e[16], l[2] = e[10], l[3] = e[23], l[4] = e[0], l[5] = e[4],
            l[6] = e[2], l[7] = e[27], l[8] = e[14], l[9] = e[5], l[10] = e[20], l[11] = e[9],
            l[12] = e[22], l[13] = e[18], l[14] = e[11], l[15] = e[3], l[16] = e[25], l[17] = e[7],
            l[18] = e[15], l[19] = e[6], l[20] = e[26], l[21] = e[19], l[22] = e[12], l[23] = e[1],
            l[24] = e[40], l[25] = e[51], l[26] = e[30], l[27] = e[36], l[28] = e[46], l[29] = e[54],
            l[30] = e[29], l[31] = e[39], l[32] = e[50], l[33] = e[44], l[34] = e[32], l[35] = e[47],
            l[36] = e[43], l[37] = e[48], l[38] = e[38], l[39] = e[55], l[40] = e[33], l[41] = e[52],
            l[42] = e[45], l[43] = e[41], l[44] = e[49], l[45] = e[35], l[46] = e[28], l[47] = e[31],
            s) {
                case 0:
                    for (var u = 0; u < 48; u++) a[0][u] = l[u];
                    break;

                case 1:
                    for (u = 0; u < 48; u++) a[1][u] = l[u];
                    break;

                case 2:
                    for (u = 0; u < 48; u++) a[2][u] = l[u];
                    break;

                case 3:
                    for (u = 0; u < 48; u++) a[3][u] = l[u];
                    break;

                case 4:
                    for (u = 0; u < 48; u++) a[4][u] = l[u];
                    break;

                case 5:
                    for (u = 0; u < 48; u++) a[5][u] = l[u];
                    break;

                case 6:
                    for (u = 0; u < 48; u++) a[6][u] = l[u];
                    break;

                case 7:
                    for (u = 0; u < 48; u++) a[7][u] = l[u];
                    break;

                case 8:
                    for (u = 0; u < 48; u++) a[8][u] = l[u];
                    break;

                case 9:
                    for (u = 0; u < 48; u++) a[9][u] = l[u];
                    break;

                case 10:
                    for (u = 0; u < 48; u++) a[10][u] = l[u];
                    break;

                case 11:
                    for (u = 0; u < 48; u++) a[11][u] = l[u];
                    break;

                case 12:
                    for (u = 0; u < 48; u++) a[12][u] = l[u];
                    break;

                case 13:
                    for (u = 0; u < 48; u++) a[13][u] = l[u];
                    break;

                case 14:
                    for (u = 0; u < 48; u++) a[14][u] = l[u];
                    break;

                case 15:
                    for (u = 0; u < 48; u++) a[15][u] = l[u];
            }
        }
        return a;
    }

    // module.exports = {
    function getTime() {
        return function (a, f, o, c) {
            var t, l, u, b, k, i, w = a.length, v = "";
            null != f && "" != f && (t = r(f), b = t.length);
            null != o && "" != o && (l = r(o), k = l.length);
            null != c && "" != c && (u = r(c), i = u.length);
            if (w > 0) if (w < 4) {
                var A = e(a);
                if (null != f && "" != f && null != o && "" != o && null != c && "" != c) {
                    for ($ = A, y = 0; y < b; y++) $ = s($, t[y]);
                    for (C = 0; C < k; C++) $ = s($, l[C]);
                    for (d = 0; d < i; d++) $ = s($, u[d]);
                    x = $;
                } else if (null != f && "" != f && null != o && "" != o) {
                    for ($ = A, y = 0; y < b; y++) $ = s($, t[y]);
                    for (C = 0; C < k; C++) $ = s($, l[C]);
                    x = $;
                } else if (null != f && "" != f) {
                    var y = 0;
                    for ($ = A, y = 0; y < b; y++) $ = s($, t[y]);
                    x = $;
                }
                v = n(x);
            } else {
                var h = parseInt(w / 4), g = w % 4, p = 0;
                for (p = 0; p < h; p++) {
                    var I = e(a.substring(4 * p + 0, 4 * p + 4));
                    if (null != f && "" != f && null != o && "" != o && null != c && "" != c) {
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        for (C = 0; C < k; C++) $ = s($, l[C]);
                        for (d = 0; d < i; d++) $ = s($, u[d]);
                        x = $;
                    } else if (null != f && "" != f && null != o && "" != o) {
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        for (C = 0; C < k; C++) $ = s($, l[C]);
                        x = $;
                    } else if (null != f && "" != f) {
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        x = $;
                    }
                    v += n(x);
                }
                if (g > 0) {
                    var x;
                    I = e(a.substring(4 * h + 0, w));
                    if (null != f && "" != f && null != o && "" != o && null != c && "" != c) {
                        var d;
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        for (C = 0; C < k; C++) $ = s($, l[C]);
                        for (d = 0; d < i; d++) $ = s($, u[d]);
                        x = $;
                    } else if (null != f && "" != f && null != o && "" != o) {
                        var C;
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        for (C = 0; C < k; C++) $ = s($, l[C]);
                        x = $;
                    } else if (null != f && "" != f) {
                        var $;
                        for ($ = I, y = 0; y < b; y++) $ = s($, t[y]);
                        x = $;
                    }
                    v += n(x);
                }
            }
            return v;
        }("saywash#" + new Date().valueOf(), "hlF#$1x)", "hlG#$2x)", "hlH#$3x)");
    }


function sign(e) {
    Array.prototype.indexVf = function (r) {
        for (var e = 0; e < this.length; e++) if (this[e] == r) return e;
    }
    var t = [], n = [], i = [];
    for (var s in e) t.push(s), i.push(s), n.push(e[s]);
    for (var o = i.sort(), u = "SING=HLYF", f = 0; f < o.length; f++) if ("tokenId" != o[f] && "ssid" != o[f] && "sign" != o[f]) {
        var a = t.indexVf(o[f]);
        "" != n[a] && null != n[a] && (u = u + "&" + o[f] + "=" + n[a]);
    }

    return "SING=HLYF" == (u = u.toUpperCase()) && (u = "SING=HLYF&"), u = md5(u);
}

function md5(string) {
    function md5_RotateLeft(lValue, iShiftBits) {
        return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
    }

    function md5_AddUnsigned(lX, lY) {
        var lX4, lY4, lX8, lY8, lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }

    function md5_F(x, y, z) {
        return (x & y) | ((~x) & z);
    }

    function md5_G(x, y, z) {
        return (x & z) | (y & (~z));
    }

    function md5_H(x, y, z) {
        return (x ^ y ^ z);
    }

    function md5_I(x, y, z) {
        return (y ^ (x | (~z)));
    }

    function md5_FF(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac));
        return md5_AddUnsigned(md5_RotateLeft(a, s), b);
    };

    function md5_GG(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac));
        return md5_AddUnsigned(md5_RotateLeft(a, s), b);
    };

    function md5_HH(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac));
        return md5_AddUnsigned(md5_RotateLeft(a, s), b);
    };

    function md5_II(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac));
        return md5_AddUnsigned(md5_RotateLeft(a, s), b);
    };

    function md5_ConvertToWordArray(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWords_temp1 = lMessageLength + 8;
        var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
        var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
        var lWordArray = Array(lNumberOfWords - 1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while (lByteCount < lMessageLength) {
            lWordCount = (lByteCount - (lByteCount % 4)) / 4;
            lBytePosition = (lByteCount % 4) * 8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount - (lByteCount % 4)) / 4;
        lBytePosition = (lByteCount % 4) * 8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
        lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
        lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
        return lWordArray;
    };

    function md5_WordToHex(lValue) {
        var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
        for (lCount = 0; lCount <= 3; lCount++) {
            lByte = (lValue >>> (lCount * 8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
        }
        return WordToHexValue;
    };

    function md5_Utf8Encode(string) {
        string = string.replace(/\r\n/g, "\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    };
    var x = Array();
    var k, AA, BB, CC, DD, a, b, c, d;
    var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
    var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
    var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
    var S41 = 6, S42 = 10, S43 = 15, S44 = 21;
    string = md5_Utf8Encode(string);
    x = md5_ConvertToWordArray(string);
    a = 0x67452301;
    b = 0xEFCDAB89;
    c = 0x98BADCFE;
    d = 0x10325476;
    for (k = 0; k < x.length; k += 16) {
        AA = a;
        BB = b;
        CC = c;
        DD = d;
        a = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
        d = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
        c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
        b = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
        a = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
        d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
        c = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
        b = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
        a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
        d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
        c = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
        b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
        a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
        d = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
        c = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
        b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
        a = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
        d = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
        c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
        b = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
        a = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
        d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453);
        c = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
        b = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
        a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
        d = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
        c = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
        b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
        a = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
        d = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
        c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
        b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
        a = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
        d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
        c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
        b = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
        a = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
        d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
        c = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
        b = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
        a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
        d = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
        c = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
        b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
        a = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
        d = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
        c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
        b = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
        a = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244);
        d = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
        c = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
        b = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
        a = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
        d = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
        c = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
        b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
        a = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
        d = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
        c = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314);
        b = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
        a = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
        d = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
        c = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
        b = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
        a = md5_AddUnsigned(a, AA);
        b = md5_AddUnsigned(b, BB);
        c = md5_AddUnsigned(c, CC);
        d = md5_AddUnsigned(d, DD);
    }
    return (md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase();
}

山西恒安刷课以及考试

软件正常无法抓包,简单绕过,无加密,整个流程可也说是设计得比较好,就是有点费服务器,斻多API,都是一条一条拉满了的,以下是python代码

考试

import requests, json



header={
    'Host': 'nazx.yunkeonline.cn',
    'content-type': 'application/json',
    'x-access-token': '8ECDCD1C5FCC04DE8E35C5255185385F7CFE78459FAE318A432E95140FC1CFFC',
    'app-version': '2.1.0',
    'app-os': 'ANDROID',
    'code-version': '2.1.1',
    'user-agent': 'okhttp/3.14.9',
}
def login(uname,pwd):

    headers = {
        'Host': 'nazx.yunkeonline.cn',
        'app-version': '2.1.0',
        'app-os': 'ANDROID',
        'code-version': '2.1.1',
        'content-type': 'application/json;charset=UTF-8',
        'user-agent': 'okhttp/3.14.9',
    }
    data = {"bindMobile":uname,"imageCode":"","password":pwd,"username":"","verifyCode":""}

    response = requests.post('https://nazx.yunkeonline.cn/c/user/login', headers=headers, json=data)
    print(response.text)
    return response.json()['result']['token']


def get_courseId():
    params = {
        'statusList': '1,2',
        'pageNo': '1',
        'pageSize': '3',
    }

    response = requests.get('https://nazx.yunkeonline.cn/c/trainPlan/getMyPlan', params=params, headers=header)
    classId=response.json()['result']['records'][0]['trainPlanId']
    params = {
        'classId': classId,
    }
    response = requests.get('https://nazx.yunkeonline.cn/c/trainPlan/getAppClassTaskList', params=params, headers=header)

    return response.json()['result']['trainPlanStageDetailDtos'][1]['planAppTaskListDtos'][0]['taskId']


def get_question_list(id):

    response = requests.get(f'https://nazx.yunkeonline.cn/c/exam/getQuestionList/{id}', headers=header)
    for i in response.json()['result']:

        with open('answer.json', 'r') as f:
            answers=json.load(f)

        for j in answers['result']:
            
            if j['id']==i['id']:
                print(j['analysis'],' ==> ',answer)
                answer=j['answer']
                answerQuestion(answer,id,j['id'])

                
    return response.json()['result']


def start_exam(id):

    response = requests.post(f'https://nazx.yunkeonline.cn/c/exam/startExam/{id}', headers=header)
    print(response.text)


def answerQuestion(answer,id,qid):
    data = {'answer':answer,'examinationId':id,'questionId':qid}
    response = requests.post('https://nazx.yunkeonline.cn/c/exam/answerQuestion', headers=header, json=data)


def submit_exam(id):

    response = requests.post(f'https://nazx.yunkeonline.cn/c/exam/submit/{id}/0', headers=header)
    print(response.text)
    print("考试完成")

def run():
    header['x-access-token']=login(phone,pwd)
    id=get_courseId()
    start_exam(id)
    get_question_list(id)

    submit_exam(id)


phone="150343xxxx"
pwd="xx"
run()

刷课, 只想到了多线程,异步没能实现,理论上可,但是失败了 开了36线程的线程池,10 ==>360秒,1分钟看36分钟,算总时常,异步理论上更佳,奈何实力不到

...

某h软件

Re

某个视频软件,我拿到最初的版本是有各类防护的(检测root,代理,抓包)

但是在网上找到一个版本好像都给干掉了,下面是用来刷vip的

ai


from hashlib import md5
import time
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64,json
import random
MODE = AES.MODE_ECB
PAD_STYLE = 'pkcs7'
ENCODING = 'UTF-8'
key='l8N2iooyp07M9IWa'
url='http://apichlove.com'
def encrypt(plaintext: str, key: str) -> str:
    key_bytes = key.encode(ENCODING)
    cipher = AES.new(key_bytes, MODE)
    plaintext_bytes = plaintext.encode(ENCODING)
    plaintext_bytes_padded = pad(plaintext_bytes, AES.block_size, PAD_STYLE)
    ciphertext_bytes = cipher.encrypt(plaintext_bytes_padded)
    ciphertext_base64_bytes = base64.b64encode(ciphertext_bytes) 
    ciphertext = ciphertext_base64_bytes.decode(ENCODING)
    return ciphertext
def decrypt(ciphertext: str, key: str) -> str:
    key_bytes = key.encode(ENCODING)
    decrypter = AES.new(key_bytes, MODE)
    ciphertext_base64_bytes = ciphertext.encode(ENCODING)
    ciphertext_bytes = base64.b64decode(ciphertext_base64_bytes)
    plaintext_bytes_padded = decrypter.decrypt(ciphertext_bytes)
    plaintext_bytes = unpad(plaintext_bytes_padded, AES.block_size, PAD_STYLE)
    plaintext = plaintext_bytes.decode(ENCODING)
    return plaintext
def x_t(url):
    a = []
    b = []
    # url = 'app/api/auth/login/device'
    v1 = str(int(time.time()))
    v2 = md5(v1.encode()).hexdigest()[:8]
    a.append('md5')
    a.append(key)
    a.append(v1)
    a.append(v2)
    a.append(url)
    v3 = '|'.join(a)
    v3 = md5(v3.encode()).hexdigest()
    b.append('md5')
    b.append(v1)
    b.append(v2)
    b.append(v3)
    return '|'.join(b)
def getRandom(randomlength=16):
    digits='0123456789'
    ascii_letters='abcdefghigklmnopqrstuvwxyz'
    str_list =[random.choice(digits +ascii_letters) for i in range(randomlength)]
    random_str =''.join(str_list)
    return random_str
def Token():
    device_id='b2ad30fc-0301-3d50-a97f-'+getRandom(12)
    data = json.dumps({"channel": "", "code": "", "device_no": device_id,"device_type": "A", "version": "1.0.0"})
    data={'data':encrypt(data,key),'handshake':'v20200429'}
    header = {'X-JSL-API-AUTH': x_t('/app/api/auth/login/device')}
    result = requests.post(url+'/app/api/auth/login/device', json=data, headers=header).json()
    msg=decrypt(result['data'],key)
    # print(msg)
    return json.loads(msg)['auth']['token'],device_id
def x_token(device_id,token):
    Json=json.dumps({"device_no":device_id,"device_type":"A","token":token,"version":"1.0.0"})
    return encrypt(Json,key)
def parent(code):
    token,device_id=Token()
    data={'data':encrypt(json.dumps({'code':code}),key),'handshake':'v20200429'}
    header={'X-JSL-API-AUTH':x_t('/app/api/user/bindcode'),'X-TOKEN':x_token(device_id=device_id,token=token)}
    result=requests.post(url+'/app/api/user/bindcode',json=data,headers=header).json()
    print(result)
    print(decrypt(result['data'],key))
    header['X-JSL-API-AUTH']=x_t('/app/api/user/info')
    # 你的X-TOKEN
    # header['X-TOKEN']='4LJnAngoza8TZIz2otKTe52PhqbrW8GULUYVUu87AjDKzXQWPzNCDiHTohcbTWRcJ5V+mdgxrLVskUbLae90njTJJk4bG8tqYcgDX/fhwwG0VkkB11CY0wLhlxPfSkfMSlqmArvVTbrJ7UiydzotGh9nUHVrBqxMbDy9+iuhq9pFmucuV1SRKd/1pGxDNI0UX9nA5mpYMfYih0N/vR3A6+AdHQASRqBpeXSfMj3M7fHY/5W4fj0esNHkw93KjsnWM2FJWdNCYrkZC3tHWipUqKTk7zvbx20zaWo/c78VuePh8OeiCV2Htt9ah8+MNvAu+o6TERNF13aavGJkxeptaZs/+PFbBa397NVD4zQ28QDhkuOthPwHbpvOL/cWm9rjoL7TH7BdKGqjbYzHTvUnpWHQtJhGTPXRdNdSklDv4UDW/nsKTVVcv1LQAU1Oo5EnMwfZF2wmTtIRMRTPIi9zYFVhTYlJeFroe2fWrl8H9afzxz+fP+tm5aGSa7Ll0RBitPmN364On3xaWrRIiYGvfYsqckb6+BRQyDMXI+nHUMOAR2EcT6U3BMUCN5VJnkX8atWL76jdqPlFZzS9zyo5yaeiNLnQzVYm9wxNPuzb9ZMgvRQ4TnXfBGE5t8BiE4jAPJczvQhvWseHNy3M3wCd5b7CavKAVznoovCoLaqJpRX+bOWnttUWMLqdYxBnweL3'
    # result=requests.post(url+'/app/api/user/info',data='{"handshake":"v20200429"}',headers=header).json()
    # print(json.loads(decrypt(result['data'],key))['vip_expired'])


# 邀请码
for i in range(5):
    parent('RWK6IF')

mls

...