【2020-12-23】JS逆向之某在線監測分析平臺

聲明:本文只作學習研究,禁止用於非法用途,否則後果自負,如有侵權,請告知刪除,謝謝!




前言

目標網站:aHR0cHM6Ly93d3cuYXFpc3R1ZHkuY24v
反爬類型:無限debugger、禁止F12調試
加密類型:JS混淆、AES、DES、BASE64


一、頁面分析

1.1 解決無限debugger

進入網頁按F12,出現下圖
在這裏插入圖片描述
解決辦法:在行數旁邊點擊右鍵,點擊紅框內容,輸入false,點擊運行即可

在這裏插入圖片描述

1.2 解決禁止調試

解決無限debugger後,又不給調試了,如下圖,咋解決呢??
在這裏插入圖片描述
解決辦法:主要是下面兩個函數在搞事情熬,用fiddler中間人改寫,咋改寫自己去搜吧,這裏就不描述了

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
弄好之後就可以調試了!!
在這裏插入圖片描述


二、加密解密破解

獲取如下數據
在這裏插入圖片描述

加密參數是請求時傳入的參數
在這裏插入圖片描述
解密參數就是響應的數據
在這裏插入圖片描述


2.1 請求參數數破解

直接下XHR斷點,找到請求參數的加密位置,這個文件的JS是https://www.aqistudy.cn/js/encrypt_eZMqs7H0RJRS.min.js?t=1603351502,扣下來放本地可以調試用
在這裏插入圖片描述

在這裏插入圖片描述

這裏的加密方法是pNg63WJXHfm8r,可以在扣下的JS代碼裏看出主要的加密方式MD5和BASE64,這裏就不用源碼的加密方式了,直接用CryptoJS加密包
在這裏插入圖片描述

源碼的加密函數都在這個混淆的JS裏面
在這裏插入圖片描述

改寫好代碼後就可以破解請求參數的加密方式了,應爲裏面的時間戳不一樣,所以有部分差異,用來發請求是完全沒問題的

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2.2 返回參數解密

解密的函數位置在這裏,也在之前扣下來的JS函數裏

在這裏插入圖片描述

裏面是這幾個加密方法
在這裏插入圖片描述

自己用加密包改寫一下就可以實現解密了

在這裏插入圖片描述


三、JS源碼

var CryptoJS = require('crypto-js');

const askCju6cmMLz = "apAteRdhDd5i5n74";
const asieXomd2dAl = "bN8izWwuwRjjA0pH";
const ackWpSYGqWDU = "dOzNkylRKkmvJ8WP";
const aciPXJAqV8bc = "fS6yu6Kz72UWOqLm";
const dskq6mV934LL = "hY8XWvmotJ7yhyBV";
const dsi68kk2Mig9 = "xCYtuanHBbJFWlKg";
const dckmQMBceyd6 = "ougX3aSyswLitv49";
const dciNka5Pmv4x = "pebJx2rKU7WTkBP6";
const aes_local_key = 'emhlbnFpcGFsbWtleQ==';
const aes_local_iv = 'emhlbnFpcGFsbWl2';
var BASE64 = {
   
         
    encrypt: function (text) {
   
         
        // var b = new Base64();
        // return b.encode(text)
        var wordArray = CryptoJS.enc.Utf8.parse(text);
        return CryptoJS.enc.Base64.stringify(wordArray)
    }, decrypt: function (text) {
   
         
        // var b = new Base64();
        // return b.decode(text)
        var parsedWordArray = CryptoJS.enc.Base64.parse(text);
        return parsedWordArray.toString(CryptoJS.enc.Utf8)
    }
};
var DES = {
   
         
    encrypt: function (text, key, iv) {
   
         
        var secretkey = (CryptoJS.MD5(key).toString()).substr(0, 16);
        var secretiv = (CryptoJS.MD5(iv).toString()).substr(24, 8);
        secretkey = CryptoJS.enc.Utf8.parse(secretkey);
        secretiv = CryptoJS.enc.Utf8.parse(secretiv);
        var result = CryptoJS.DES.encrypt(text, secretkey, {
   
         
            iv: secretiv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return result.toString()
    }, decrypt: function (text, key, iv) {
   
         
        var secretkey = (CryptoJS.MD5(key).toString()).substr(0, 16);
        var secretiv = (CryptoJS.MD5(iv).toString()).substr(24, 8);
        secretkey = CryptoJS.enc.Utf8.parse(secretkey);
        secretiv = CryptoJS.enc.Utf8.parse(secretiv);
        var result = CryptoJS.DES.decrypt(text, secretkey, {
   
         
            iv: secretiv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return result.toString(CryptoJS.enc.Utf8)
    }
};
var AES = {
   
         
    encrypt: function (text, key, iv) {
   
         
        var secretkey = (CryptoJS.MD5(key).toString()).substr(16, 16);
        var secretiv = (CryptoJS.MD5(iv).toString()).substr(0, 16);
        secretkey = CryptoJS.enc.Utf8.parse(secretkey);
        secretiv = CryptoJS.enc.Utf8.parse(secretiv);
        var result = CryptoJS.AES.encrypt(text, secretkey, {
   
         
            iv: secretiv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return result.toString()
    }, decrypt: function (text, key, iv) {
   
         
        var secretkey = (CryptoJS.MD5(key).toString()).substr(16, 16);
        var secretiv = (CryptoJS.MD5(iv).toString()).substr(0, 16);
        secretkey = CryptoJS.enc.Utf8.parse(secretkey);
        secretiv = CryptoJS.enc.Utf8.parse(secretiv);
        var result = CryptoJS.AES.decrypt(text, secretkey, {
   
         
            iv: secretiv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return result.toString(CryptoJS.enc.Utf8)
    }
};
var localStorageUtil = {
   
         
    save: function (name, value) {
   
         
        var text = JSON.stringify(value);
        text = BASE64.encrypt(text);
        text = AES.encrypt(text, aes_local_key, aes_local_iv);
        try {
   
         
            localStorage.setItem(name, text)
        } catch (oException) {
   
         
            if (oException.name === 'QuotaExceededError') {
   
         
                console.log('超出本地存儲限額!');
                localStorage.clear();
                localStorage.setItem(name, text)
            }
        }
    }, check: function (name) {
   
         
        return localStorage.getItem(name)
    }, getValue: function (name) {
   
         
        var text = localStorage.getItem(name);
        var result = null;
        if (text) {
   
         
            text = AES.decrypt(text, aes_local_key, aes_local_iv);
            text = BASE64.decrypt(text);
            result = JSON.parse(text)
        }
        return result
    }, remove: function (name) {
   
         
        localStorage.removeItem(name)
    }
};

function getDataFromLocalStorage(key, period) {
   
         
    if (typeof period === 'undefined') {
   
         
        period = 0
    }
    var d = DES.encrypt(key);
    d = BASE64.encrypt(key);
    var data = localStorageUtil.getValue(key);
    if (data) {
   
         
        const time = data.time;
        const current = new Date().getTime();
        if (new Date().getHours() >= 0 && new Date().getHours() < 5 && period > 1) {
   
         
            period = 1
        }
        if (current - (period * 60 * 60 * 1000) > time) {
   
         
            data = null
        }
        if (new Date().getHours() >= 5 && new Date(time).getDate() !== new Date().getDate() && period === 24) {
   
         
            data = null
        }
    }
    return data
}

function ObjectSort(obj) {
   
         
    var newObject = {
   
         };
    Object.keys(obj).sort().map(function (key) {
   
         
        newObject[key] = obj[key]
    });
    return newObject
}

function dX506x9jVK3vuMMhoz6ZXx(data) {
   
         
    data = AES.decrypt(data, askCju6cmMLz, asieXomd2dAl);
    data = DES.decrypt(data, dskq6mV934LL, dsi68kk2Mig9);
    data = BASE64.decrypt(data);
    return data
}

var pNg63WJXHfm8r = (function () {
   
         
    function ObjectSort(obj) {
   
         
        var newObject = {
   
         };
        Object.keys(obj).sort().map(function (key) {
   
         
            newObject[key] = obj[key]
        });
        return newObject
    }

    return function (method, obj) {
   
         
        var appId = 'baec98a73c1bff796603cb2fa9d6d449';
        var clienttype = 'WEB';
        var timestamp = new Date().getTime();
        var param = {
   
         
            appId: appId,
            method: method,
            timestamp: timestamp,
            clienttype: clienttype,
            object: obj,
            // secret: hex_md5(appId + method + timestamp + clienttype + JSON.stringify(ObjectSort(obj)))
            secret: CryptoJS.MD5(appId + method + timestamp + clienttype + JSON.stringify(ObjectSort(obj))).toString()
        };
        param = BASE64.encrypt(JSON.stringify(param));
        return param
    }
})();

function sJwf3VwkSgqmf0Ddr92K(method, object, callback, period) {
   
         
    const key = hex_md5(method + JSON.stringify(object));
    const data = getDataFromLocalStorage(key, period);
    if (!data) {
   
         
        var param = pNg63WJXHfm8r(method, object);
        $.ajax({
   
         
            url: '../apinew/aqistudyapi.php', data: {
   
         h0lgYxgR3: param}, type: "post", success: function (data) {
   
         
                data = dX506x9jVK3vuMMhoz6ZXx(data);
                obj = JSON.parse(data);
                if (obj.success) {
   
         
                    if (period > 0) {
   
         
                        obj.result.time = new Date().getTime();
                        localStorageUtil.save(key, obj.result)
                    }
                    callback(obj.result)
                } else {
   
         
                    console.log(obj.errcode, obj.errmsg)
                }
            }
        })
    } else {
   
         
        callback(data)
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章