首页 > 其他分享 >某省资源交易中心 (js逆向)

某省资源交易中心 (js逆向)

时间:2024-01-08 14:07:54浏览次数:32  
标签:逆向 15 CHARS HEX js 某省 var blocks 加密


该文章只是用于逆向学习,不得以商用或者是破坏他人利益的目的进行使用。如有侵权请联系作者。

网站链接:

bse64

aHR0cHM6Ly9nZ3p5ZncuZnVqaWFuLmdvdi5jbi9idXNpbmVzcy9saXN0Lw==

分析环节

进入网站 进行翻页请求时我们会发现改请求时ajax请求。

某省资源交易中心 (js逆向)_爬虫

这里,我们可以直接看一下请求参数和返回结果,以及表头携带。

请求参数

请求参数中不存在加密

某省资源交易中心 (js逆向)_爬虫_02

返回数据

data被加密了

某省资源交易中心 (js逆向)_i++_03

 请求头

请求头中存在一个加密参数

某省资源交易中心 (js逆向)_网络协议_04

此时我们换页,查看改参数是否改变

 

某省资源交易中心 (js逆向)_网络协议_05

发生改变,所以我们现在需要做的就是先找到请求头中的 portal-sign的加密位置。

由于数据加密的这个过程中我们并不知道再那个文件中,应为返回数据的话是已经得到加密头了,所以这里我们采用搜索关键字的方法来进行快速定位。这也是为什么我不直接使用xhr断点找加密的原因。

搜索关键词portal-sign

某省资源交易中心 (js逆向)_json_06

找到关键字,点击进入该js文件

打个断点待会好调试

某省资源交易中心 (js逆向)_json_07

现在我们已经找到加密的位置了,根据名字可以直接确定,这就是加密的赋值操作,现在开始调试,找到加密函数。

执行一步的时候我们发现他出现到这里了,结合上面的f.getsign(e)可以确定,这个过程是正确的

某省资源交易中心 (js逆向)_网络协议_08

那么,我们先不扣代码,先走一步看看,执行到这里的时候我们需要看一下这些参数是什么

某省资源交易中心 (js逆向)_js逆向_09

控制台输出一下r["a"]

 

某省资源交易中心 (js逆向)_i++_10

这个值先记录一下

输出l(t),我们可以确定的是,l(t)是一个加密的过程

某省资源交易中心 (js逆向)_爬虫_11

并且我们看参数t是一个对象

某省资源交易中心 (js逆向)_网络协议_12

 中间的ts是一个时间戳,带有请求的一些参数,这个先不管

现在继续进入,进入下图文件中。我们发现这个过程是创建了一个Md5对象并且调用了update方法,所以我们已经可以知道这个结果了,以防万一,我们直接跳过调试观察一下。可以验证个参数就是一个通过md5加密的一个过程,你现在可以采用md5加密验证也可以直接扣下来这段代码,我们使用平台是可以直接知道,这个加密就是MD5加密的一个过程,但是为了锻炼我的扣代码能力,我选择了硬扣。如果你不想查看这个过程的话,可以直接略过。

某省资源交易中心 (js逆向)_爬虫_13

js扣代码环节 

根据我们上边的一些记录我们现在需要做的是,刷新网页,重新打开浏览器,执行一遍这个过程,看看有哪些是固定的。

某省资源交易中心 (js逆向)_i++_14

可以确定r["a"]是没有改变,我们直接搜索这个值看一下有没有

某省资源交易中心 (js逆向)_网络协议_15

存在,所以现在我们就知道这个过程了,他是将一个请求头t当作参数传递给d在d函数中,通过一个常量和一个加密后的数据进行拼接,然后使用MD5进行加密。

现在开始着手扣第一步代码,得到加密后的n

我喜欢使用html来验证js代码是否完整,所以这里我使用的html讲解

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        
function s(t, e) {
    return t.toString().toUpperCase() > e.toString().toUpperCase() ? 1 : t.toString().toUpperCase() == e.toString().toUpperCase() ? 0 : -1
}
function l(t) {
    for (var e = Object.keys(t).sort(s), n = "", a = 0; a < e.length; a++)
        if (void 0 !== t[e[a]])
            if (t[e[a]] && t[e[a]]instanceof Object || t[e[a]]instanceof Array) {
                var i = JSON.stringify(t[e[a]]);
                n += e[a] + i
            } else
                n += e[a] + t[e[a]];
    return n
}
function d(t) {
    for (var e in t)
        "" !== t[e] && void 0 !== t[e] || delete t[e];
    var n = "B3978D054A72A7002063637CCDF6B2E5" + l(t);
    console.log(n)
    return u(n).toLocaleLowerCase()
}
t = {
    "ts": 1702288385369,
    "type": "12",
    "IS_IMPORT": 1,
    "pageSize": 3
}
d(t)
    </script>
</body>
</html>

某省资源交易中心 (js逆向)_网络协议_16

出现的错误是因为没有找到u(n),我们可以发现已经出现拼接好的n了,那么我们可以确定的是,代码已经成功了一步。

现在开始着手MD5加密环节

进入之后,会返回一个new对象,所以直接将u(n)部分替换

某省资源交易中心 (js逆向)_i++_17

替换的代码

function d(t) {
    for (var e in t)
        "" !== t[e] && void 0 !== t[e] || delete t[e];
    var n = "B3978D054A72A7002063637CCDF6B2E5" + l(t);
    console.log(n)
    return new Md5(!0).update(n)[t]()

 接下来就i是把整个md5扣下来了

某省资源交易中心 (js逆向)_js逆向_18

联立前面的代码,我们可以直接放到html中,观察。

这边md5我就不单独放出来了,不然我写着是真的卡

出现错误:找不到这个blocks,那么开始在代码中找这个定义

某省资源交易中心 (js逆向)_i++_19

 还顺带找到了buffers,直接拷贝到文件中。

某省资源交易中心 (js逆向)_网络协议_20

出现错误

某省资源交易中心 (js逆向)_爬虫_21

直接在浏览器中打印,是一个ture

某省资源交易中心 (js逆向)_json_22

直接填写,然后在代码中替换。

现在又出现缺少

某省资源交易中心 (js逆向)_网络协议_23

我们发现是创建函数出了问题,里面少了一个参数t,直接根据提示,发现是一个字符串,在代码中补全。

某省资源交易中心 (js逆向)_爬虫_24

现在缺少了一个EXTRA

某省资源交易中心 (js逆向)_网络协议_25

 

开始找位置,然后补全,在这个位置,直接复制下来

某省资源交易中心 (js逆向)_网络协议_26

继续找

某省资源交易中心 (js逆向)_爬虫_27

找到,然后复制下来。

某省资源交易中心 (js逆向)_js逆向_28

现在没有报错,我们试一下结果对不对。。

某省资源交易中心 (js逆向)_json_29

完美解决,所以此时我们已经得到了这个正确的js代码,只需要将参数中的ts更改成当前的请求时间戳就行,

某省资源交易中心 (js逆向)_i++_30

这里贴上html代码,你只需要把js部分复制修改即可

1

我们来处理一下此时的python请求,先把第一步确定好。

第一步请求的python代码

import requests
import execjs
ts = int(execjs.compile(open('D:/桌面/pythoncode/new.js', 'r', encoding='utf-8').read()).call('gettime'))

json_data = {
        'pageNo': 1,
        'pageSize': 40,
        'total': 5770,
        'AREACODE': '',
        'M_PROJECT_TYPE': '',
        'KIND': 'GCJS',
        'GGTYPE': '1',
        'PROTYPE': '',
        'timeType': '6',
        'BeginTime': '2022-07-18 00:00:00',
        'EndTime': '2023-01-18 23:59:59',
        'createTime': [],
        'ts': ts,
}
sign  = str(execjs.compile(open('D:/桌面/pythoncode/new.js', 'r', encoding='utf-8').read()).call('main',json_data))
print(sign)
headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json;charset=UTF-8',
        'Origin': 'https://ggzyfw.fujian.gov.cn',
        'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
        'portal-sign': sign,
        'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
    }

response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data).json()
print(response)

得到请求头加密参数

HEX_CHARS = "0123456789abcdef".split("")
EXTRA = [128, 32768, 8388608, -2147483648]
var buffer = new ArrayBuffer(68);
buffer8 = new Uint8Array(buffer),
blocks = new Uint32Array(buffer)
function Md5(t) {
    if (t)
        blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0,
            this.blocks = blocks,
            this.buffer8 = buffer8;
    else if (true) {
        var n = new ArrayBuffer(68);
        this.buffer8 = new Uint8Array(n),
            this.blocks = new Uint32Array(n)
    } else
        this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0,
        this.finalized = this.hashed = !1,
        this.first = !0
}
Md5.prototype.update = function (t) {
    if (!this.finalized) {
        var n, e = typeof t;
        if ("string" !== e) {
            if ("object" !== e)
                throw ERROR;
            if (null === t)
                throw ERROR;
            if (true && t.constructor === ArrayBuffer)
                t = new Uint8Array(t);
            else if (!Array.isArray(t) && (!true || !ArrayBuffer.isView(t)))
                throw ERROR;
            n = !0
        }
        var r, i, o = 0, c = t.length, A = this.blocks, a = this.buffer8;
        while (o < c) {
            if (this.hashed && (this.hashed = !1,
                A[0] = A[16],
                A[16] = A[1] = A[2] = A[3] = A[4] = A[5] = A[6] = A[7] = A[8] = A[9] = A[10] = A[11] = A[12] = A[13] = A[14] = A[15] = 0),
                n)
                if (true)
                    for (i = this.start; o < c && i < 64; ++o)
                        a[i++] = t[o];
                else
                    for (i = this.start; o < c && i < 64; ++o)
                        A[i >> 2] |= t[o] << SHIFT[3 & i++];
            else if (true)
                for (i = this.start; o < c && i < 64; ++o)
                    r = t.charCodeAt(o),
                        r < 128 ? a[i++] = r : r < 2048 ? (a[i++] = 192 | r >> 6,
                            a[i++] = 128 | 63 & r) : r < 55296 || r >= 57344 ? (a[i++] = 224 | r >> 12,
                                a[i++] = 128 | r >> 6 & 63,
                                a[i++] = 128 | 63 & r) : (r = 65536 + ((1023 & r) << 10 | 1023 & t.charCodeAt(++o)),
                                    a[i++] = 240 | r >> 18,
                                    a[i++] = 128 | r >> 12 & 63,
                                    a[i++] = 128 | r >> 6 & 63,
                                    a[i++] = 128 | 63 & r);
            else
                for (i = this.start; o < c && i < 64; ++o)
                    r = t.charCodeAt(o),
                        r < 128 ? A[i >> 2] |= r << SHIFT[3 & i++] : r < 2048 ? (A[i >> 2] |= (192 | r >> 6) << SHIFT[3 & i++],
                            A[i >> 2] |= (128 | 63 & r) << SHIFT[3 & i++]) : r < 55296 || r >= 57344 ? (A[i >> 2] |= (224 | r >> 12) << SHIFT[3 & i++],
                                A[i >> 2] |= (128 | r >> 6 & 63) << SHIFT[3 & i++],
                                A[i >> 2] |= (128 | 63 & r) << SHIFT[3 & i++]) : (r = 65536 + ((1023 & r) << 10 | 1023 & t.charCodeAt(++o)),
                                    A[i >> 2] |= (240 | r >> 18) << SHIFT[3 & i++],
                                    A[i >> 2] |= (128 | r >> 12 & 63) << SHIFT[3 & i++],
                                    A[i >> 2] |= (128 | r >> 6 & 63) << SHIFT[3 & i++],
                                    A[i >> 2] |= (128 | 63 & r) << SHIFT[3 & i++]);
            this.lastByteIndex = i,
                this.bytes += i - this.start,
                i >= 64 ? (this.start = i - 64,
                    this.hash(),
                    this.hashed = !0) : this.start = i
        }
        return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0,
            this.bytes = this.bytes % 4294967296),
            this
    }
}
    ,
    Md5.prototype.finalize = function () {
        if (!this.finalized) {
            this.finalized = !0;
            var t = this.blocks
                , n = this.lastByteIndex;
            t[n >> 2] |= EXTRA[3 & n],
                n >= 56 && (this.hashed || this.hash(),
                    t[0] = t[16],
                    t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0),
                t[14] = this.bytes << 3,
                t[15] = this.hBytes << 3 | this.bytes >>> 29,
                this.hash()
        }
    }
    ,
    Md5.prototype.hash = function () {
        var t, n, e, r, i, o, c = this.blocks;
        this.first ? (t = c[0] - 680876937,
            t = (t << 7 | t >>> 25) - 271733879 << 0,
            r = (-1732584194 ^ 2004318071 & t) + c[1] - 117830708,
            r = (r << 12 | r >>> 20) + t << 0,
            e = (-271733879 ^ r & (-271733879 ^ t)) + c[2] - 1126478375,
            e = (e << 17 | e >>> 15) + r << 0,
            n = (t ^ e & (r ^ t)) + c[3] - 1316259209,
            n = (n << 22 | n >>> 10) + e << 0) : (t = this.h0,
                n = this.h1,
                e = this.h2,
                r = this.h3,
                t += (r ^ n & (e ^ r)) + c[0] - 680876936,
                t = (t << 7 | t >>> 25) + n << 0,
                r += (e ^ t & (n ^ e)) + c[1] - 389564586,
                r = (r << 12 | r >>> 20) + t << 0,
                e += (n ^ r & (t ^ n)) + c[2] + 606105819,
                e = (e << 17 | e >>> 15) + r << 0,
                n += (t ^ e & (r ^ t)) + c[3] - 1044525330,
                n = (n << 22 | n >>> 10) + e << 0),
            t += (r ^ n & (e ^ r)) + c[4] - 176418897,
            t = (t << 7 | t >>> 25) + n << 0,
            r += (e ^ t & (n ^ e)) + c[5] + 1200080426,
            r = (r << 12 | r >>> 20) + t << 0,
            e += (n ^ r & (t ^ n)) + c[6] - 1473231341,
            e = (e << 17 | e >>> 15) + r << 0,
            n += (t ^ e & (r ^ t)) + c[7] - 45705983,
            n = (n << 22 | n >>> 10) + e << 0,
            t += (r ^ n & (e ^ r)) + c[8] + 1770035416,
            t = (t << 7 | t >>> 25) + n << 0,
            r += (e ^ t & (n ^ e)) + c[9] - 1958414417,
            r = (r << 12 | r >>> 20) + t << 0,
            e += (n ^ r & (t ^ n)) + c[10] - 42063,
            e = (e << 17 | e >>> 15) + r << 0,
            n += (t ^ e & (r ^ t)) + c[11] - 1990404162,
            n = (n << 22 | n >>> 10) + e << 0,
            t += (r ^ n & (e ^ r)) + c[12] + 1804603682,
            t = (t << 7 | t >>> 25) + n << 0,
            r += (e ^ t & (n ^ e)) + c[13] - 40341101,
            r = (r << 12 | r >>> 20) + t << 0,
            e += (n ^ r & (t ^ n)) + c[14] - 1502002290,
            e = (e << 17 | e >>> 15) + r << 0,
            n += (t ^ e & (r ^ t)) + c[15] + 1236535329,
            n = (n << 22 | n >>> 10) + e << 0,
            t += (e ^ r & (n ^ e)) + c[1] - 165796510,
            t = (t << 5 | t >>> 27) + n << 0,
            r += (n ^ e & (t ^ n)) + c[6] - 1069501632,
            r = (r << 9 | r >>> 23) + t << 0,
            e += (t ^ n & (r ^ t)) + c[11] + 643717713,
            e = (e << 14 | e >>> 18) + r << 0,
            n += (r ^ t & (e ^ r)) + c[0] - 373897302,
            n = (n << 20 | n >>> 12) + e << 0,
            t += (e ^ r & (n ^ e)) + c[5] - 701558691,
            t = (t << 5 | t >>> 27) + n << 0,
            r += (n ^ e & (t ^ n)) + c[10] + 38016083,
            r = (r << 9 | r >>> 23) + t << 0,
            e += (t ^ n & (r ^ t)) + c[15] - 660478335,
            e = (e << 14 | e >>> 18) + r << 0,
            n += (r ^ t & (e ^ r)) + c[4] - 405537848,
            n = (n << 20 | n >>> 12) + e << 0,
            t += (e ^ r & (n ^ e)) + c[9] + 568446438,
            t = (t << 5 | t >>> 27) + n << 0,
            r += (n ^ e & (t ^ n)) + c[14] - 1019803690,
            r = (r << 9 | r >>> 23) + t << 0,
            e += (t ^ n & (r ^ t)) + c[3] - 187363961,
            e = (e << 14 | e >>> 18) + r << 0,
            n += (r ^ t & (e ^ r)) + c[8] + 1163531501,
            n = (n << 20 | n >>> 12) + e << 0,
            t += (e ^ r & (n ^ e)) + c[13] - 1444681467,
            t = (t << 5 | t >>> 27) + n << 0,
            r += (n ^ e & (t ^ n)) + c[2] - 51403784,
            r = (r << 9 | r >>> 23) + t << 0,
            e += (t ^ n & (r ^ t)) + c[7] + 1735328473,
            e = (e << 14 | e >>> 18) + r << 0,
            n += (r ^ t & (e ^ r)) + c[12] - 1926607734,
            n = (n << 20 | n >>> 12) + e << 0,
            i = n ^ e,
            t += (i ^ r) + c[5] - 378558,
            t = (t << 4 | t >>> 28) + n << 0,
            r += (i ^ t) + c[8] - 2022574463,
            r = (r << 11 | r >>> 21) + t << 0,
            o = r ^ t,
            e += (o ^ n) + c[11] + 1839030562,
            e = (e << 16 | e >>> 16) + r << 0,
            n += (o ^ e) + c[14] - 35309556,
            n = (n << 23 | n >>> 9) + e << 0,
            i = n ^ e,
            t += (i ^ r) + c[1] - 1530992060,
            t = (t << 4 | t >>> 28) + n << 0,
            r += (i ^ t) + c[4] + 1272893353,
            r = (r << 11 | r >>> 21) + t << 0,
            o = r ^ t,
            e += (o ^ n) + c[7] - 155497632,
            e = (e << 16 | e >>> 16) + r << 0,
            n += (o ^ e) + c[10] - 1094730640,
            n = (n << 23 | n >>> 9) + e << 0,
            i = n ^ e,
            t += (i ^ r) + c[13] + 681279174,
            t = (t << 4 | t >>> 28) + n << 0,
            r += (i ^ t) + c[0] - 358537222,
            r = (r << 11 | r >>> 21) + t << 0,
            o = r ^ t,
            e += (o ^ n) + c[3] - 722521979,
            e = (e << 16 | e >>> 16) + r << 0,
            n += (o ^ e) + c[6] + 76029189,
            n = (n << 23 | n >>> 9) + e << 0,
            i = n ^ e,
            t += (i ^ r) + c[9] - 640364487,
            t = (t << 4 | t >>> 28) + n << 0,
            r += (i ^ t) + c[12] - 421815835,
            r = (r << 11 | r >>> 21) + t << 0,
            o = r ^ t,
            e += (o ^ n) + c[15] + 530742520,
            e = (e << 16 | e >>> 16) + r << 0,
            n += (o ^ e) + c[2] - 995338651,
            n = (n << 23 | n >>> 9) + e << 0,
            t += (e ^ (n | ~r)) + c[0] - 198630844,
            t = (t << 6 | t >>> 26) + n << 0,
            r += (n ^ (t | ~e)) + c[7] + 1126891415,
            r = (r << 10 | r >>> 22) + t << 0,
            e += (t ^ (r | ~n)) + c[14] - 1416354905,
            e = (e << 15 | e >>> 17) + r << 0,
            n += (r ^ (e | ~t)) + c[5] - 57434055,
            n = (n << 21 | n >>> 11) + e << 0,
            t += (e ^ (n | ~r)) + c[12] + 1700485571,
            t = (t << 6 | t >>> 26) + n << 0,
            r += (n ^ (t | ~e)) + c[3] - 1894986606,
            r = (r << 10 | r >>> 22) + t << 0,
            e += (t ^ (r | ~n)) + c[10] - 1051523,
            e = (e << 15 | e >>> 17) + r << 0,
            n += (r ^ (e | ~t)) + c[1] - 2054922799,
            n = (n << 21 | n >>> 11) + e << 0,
            t += (e ^ (n | ~r)) + c[8] + 1873313359,
            t = (t << 6 | t >>> 26) + n << 0,
            r += (n ^ (t | ~e)) + c[15] - 30611744,
            r = (r << 10 | r >>> 22) + t << 0,
            e += (t ^ (r | ~n)) + c[6] - 1560198380,
            e = (e << 15 | e >>> 17) + r << 0,
            n += (r ^ (e | ~t)) + c[13] + 1309151649,
            n = (n << 21 | n >>> 11) + e << 0,
            t += (e ^ (n | ~r)) + c[4] - 145523070,
            t = (t << 6 | t >>> 26) + n << 0,
            r += (n ^ (t | ~e)) + c[11] - 1120210379,
            r = (r << 10 | r >>> 22) + t << 0,
            e += (t ^ (r | ~n)) + c[2] + 718787259,
            e = (e << 15 | e >>> 17) + r << 0,
            n += (r ^ (e | ~t)) + c[9] - 343485551,
            n = (n << 21 | n >>> 11) + e << 0,
            this.first ? (this.h0 = t + 1732584193 << 0,
                this.h1 = n - 271733879 << 0,
                this.h2 = e - 1732584194 << 0,
                this.h3 = r + 271733878 << 0,
                this.first = !1) : (this.h0 = this.h0 + t << 0,
                    this.h1 = this.h1 + n << 0,
                    this.h2 = this.h2 + e << 0,
                    this.h3 = this.h3 + r << 0)
    }
    ,
    Md5.prototype.hex = function () {
        this.finalize();
        var t = this.h0
            , n = this.h1
            , e = this.h2
            , r = this.h3;
        return HEX_CHARS[t >> 4 & 15] + HEX_CHARS[15 & t] + HEX_CHARS[t >> 12 & 15] + HEX_CHARS[t >> 8 & 15] + HEX_CHARS[t >> 20 & 15] + HEX_CHARS[t >> 16 & 15] + HEX_CHARS[t >> 28 & 15] + HEX_CHARS[t >> 24 & 15] + HEX_CHARS[n >> 4 & 15] + HEX_CHARS[15 & n] + HEX_CHARS[n >> 12 & 15] + HEX_CHARS[n >> 8 & 15] + HEX_CHARS[n >> 20 & 15] + HEX_CHARS[n >> 16 & 15] + HEX_CHARS[n >> 28 & 15] + HEX_CHARS[n >> 24 & 15] + HEX_CHARS[e >> 4 & 15] + HEX_CHARS[15 & e] + HEX_CHARS[e >> 12 & 15] + HEX_CHARS[e >> 8 & 15] + HEX_CHARS[e >> 20 & 15] + HEX_CHARS[e >> 16 & 15] + HEX_CHARS[e >> 28 & 15] + HEX_CHARS[e >> 24 & 15] + HEX_CHARS[r >> 4 & 15] + HEX_CHARS[15 & r] + HEX_CHARS[r >> 12 & 15] + HEX_CHARS[r >> 8 & 15] + HEX_CHARS[r >> 20 & 15] + HEX_CHARS[r >> 16 & 15] + HEX_CHARS[r >> 28 & 15] + HEX_CHARS[r >> 24 & 15]
    }
    ,
    Md5.prototype.toString = Md5.prototype.hex,
    Md5.prototype.digest = function () {
        this.finalize();
        var t = this.h0
            , n = this.h1
            , e = this.h2
            , r = this.h3;
        return [255 & t, t >> 8 & 255, t >> 16 & 255, t >> 24 & 255, 255 & n, n >> 8 & 255, n >> 16 & 255, n >> 24 & 255, 255 & e, e >> 8 & 255, e >> 16 & 255, e >> 24 & 255, 255 & r, r >> 8 & 255, r >> 16 & 255, r >> 24 & 255]
    }
    ,
    Md5.prototype.array = Md5.prototype.digest,
    Md5.prototype.arrayBuffer = function () {
        this.finalize();
        var t = new ArrayBuffer(16)
            , n = new Uint32Array(t);
        return n[0] = this.h0,
            n[1] = this.h1,
            n[2] = this.h2,
            n[3] = this.h3,
            t
    }
    ,
    Md5.prototype.buffer = Md5.prototype.arrayBuffer,
    Md5.prototype.base64 = function () {
        for (var t, n, e, r = "", i = this.array(), o = 0; o < 15;)
            t = i[o++],
                n = i[o++],
                e = i[o++],
                r += BASE64_ENCODE_CHAR[t >>> 2] + BASE64_ENCODE_CHAR[63 & (t << 4 | n >>> 4)] + BASE64_ENCODE_CHAR[63 & (n << 2 | e >>> 6)] + BASE64_ENCODE_CHAR[63 & e];
        return t = i[o],
            r += BASE64_ENCODE_CHAR[t >>> 2] + BASE64_ENCODE_CHAR[t << 4 & 63] + "==",
            r
    }
function s(t, e) {
    return t.toString().toUpperCase() > e.toString().toUpperCase() ? 1 : t.toString().toUpperCase() == e.toString().toUpperCase() ? 0 : -1
}
function l(t) {
    for (var e = Object.keys(t).sort(s), n = "", a = 0; a < e.length; a++)
        if (void 0 !== t[e[a]])
            if (t[e[a]] && t[e[a]] instanceof Object || t[e[a]] instanceof Array) {
                var i = JSON.stringify(t[e[a]]);
                n += e[a] + i
            } else
                n += e[a] + t[e[a]];
    return n
}
function d(t) {
    for (var e in t)
        "" !== t[e] && void 0 !== t[e] || delete t[e];
    var n = "B3978D054A72A7002063637CCDF6B2E5" + l(t);
    return new Md5(!0).update(n)['hex']()
}
function gettime(){
    d1 = ((new Date).getTime())
    return d1
}

function main(dictData) {
    return d(dictData)
}

准备解决得到的加密数据。

这个纯靠经验,直接搜索,decrypt(),这个东西是js的一种解密的密钥

某省资源交易中心 (js逆向)_js逆向_31

出现两个,我们现在先看第一个。

某省资源交易中心 (js逆向)_js逆向_32

打断点调试

某省资源交易中心 (js逆向)_js逆向_33

执行到这个位置的时候,我们输出一下a.tostring(),主要还是t的数据格式格式跟返回的data太像了

某省资源交易中心 (js逆向)_爬虫_34

发现,这个结果是我们需要的数据

某省资源交易中心 (js逆向)_js逆向_35

直接复制这段函数,使用crypto-js,来模拟一下检查是不是aes的(名字中存在)

将缺少的参数补上,这里还是控制台输出r["e"] r["j"]

返回参数解密

const Crypto = require('crypto-js')

var c = 'EB444973714E4A40876CE66BE45D5930'
var b = 'B5A8904209931867'
function decrypt(t) {
    var e = Crypto.enc.Utf8.parse(c)
      , n = Crypto.enc.Utf8.parse(b)
      , a = Crypto.AES.decrypt(t, e, {
        iv: n,
        mode: Crypto.mode.CBC,
        padding: Crypto.pad.Pkcs7
    });
    return a.toString(Crypto.enc.Utf8)
}

我们可以发现返回值符合预期结果,所以这个js文件处理加密的数据是正确的

最终的py代码

import requests
import execjs
ts = int(execjs.compile(open('D:\桌面\pythoncode\得到加密参数.js', 'r', encoding='utf-8').read()).call('gettime'))

json_data = {
        'pageNo': 1,
        'pageSize': 40,
        'total': 5770,
        'AREACODE': '',
        'M_PROJECT_TYPE': '',
        'KIND': 'GCJS',
        'GGTYPE': '1',
        'PROTYPE': '',
        'timeType': '6',
        'BeginTime': '2022-07-18 00:00:00',
        'EndTime': '2023-01-18 23:59:59',
        'createTime': [],
        'ts': ts,
}
sign  = str(execjs.compile(open('D:\桌面\pythoncode\得到加密参数.js', 'r', encoding='utf-8').read()).call('main',json_data))
print(sign)
headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json;charset=UTF-8',
        'Origin': 'https://ggzyfw.fujian.gov.cn',
        'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
        'portal-sign': sign,
        'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
    }

response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data).json()
data = response["Data"]
ctx = execjs.compile(open('D:\桌面\pythoncode\解密得到的数据.js', 'r', encoding='utf-8').read()).call('decrypt', data)
print(ctx)

效果展示

某省资源交易中心 (js逆向)_i++_36

批量下载只需要修改参数即可,留个赞!

标签:逆向,15,CHARS,HEX,js,某省,var,blocks,加密
From: https://blog.51cto.com/u_16426526/9143890

相关文章