萬達影視JS逆向分析

滲透逆向 · 11 天前 · 7 人浏览

這裏headers頭部有個參數需要分析,然後去搜索定位:
2025-05-20T09:03:33.png
2025-05-20T09:04:42.png
a.default來自t函數,t又是r的構造函數,複製這個r,把new a.default改成 new r到本地
2025-05-20T09:06:14.png
完整逆向代碼:

// 导入 Node.js 内置的 crypto 模块
const crypto = require('crypto');

/**
 * 使用 MD5 对字符串进行哈希加密,返回十六进制字符串。
 * @param {string} inputString - 要加密的字符串。
 * @returns {string} MD5 哈希的十六进制表示。
 */
function md5Encrypt(inputString) {
    // 1. 创建一个 MD5 哈希对象
    const hash = crypto.createHash('md5');

    // 2. 更新哈希对象的数据
    // inputString 必须是字符串或 Buffer。如果 inputString 是字符串,默认使用 UTF-8 编码。
    hash.update(inputString);

    // 3. 计算哈希值并以十六进制格式输出
    return hash.digest('hex');
}

r = function () {
    function t(t) {
        this.clientKey = "B3AA12B0145E1982F282BEDD8A3305B89A9811280C0B8CC3A6A60D81022E4903",
            this.saleSubjectCode = "Wanda",
            this.cCode = "1_3",
            this.mxAPIVer = "v1.0.0",
            this.method = "GET",
            this.appId = "3"
    }
    return t.prototype.generateSignature = function (t, e, i) {
        var n = "";
        return n += this.saleSubjectCode,
            n += this.cCode,
            n += this.clientKey,
            n += t,
            "POST" === this.method ? (n += e,
                n += i) : (n += e,
                    i && (n += "?",
                        n += i)),
            md5Encrypt(n)
    }
        ,
        t.prototype.setPostData = function (t) {
            var e = [];
            for (var i in t)
                "POST" === this.method ? "object" == typeof t[i] ? e.push(this.flatParamObjectValue(i, t[i])) : e.push(i + "=" + this.urlEncodeUnicode(t[i])) : e.push(i + "=" + encodeURIComponent(t[i]));
            return e.join("&")
        }
        ,
        t.prototype.setMxHead = function (t, e, i) {
            var n = {
                ver: "v1.0.0",
                sCode: this.saleSubjectCode,
                _mi_: t,
                width: 1280,
                json: !0,
                cCode: this.cCode,
                check: i,
                ts: e,
                heigth: 720,
                appId: this.appId
            };
            return JSON.stringify(n)
        }
        ,
        t.prototype.flatParamObjectValue = function (t, e) {
            var i = [];
            for (var n in e)
                "object" == typeof e[n] ? i.push(this.flatParamObjectValue(t + "[" + n + "]", e[n])) : i.push(t + "[" + n + "]=" + this.urlEncodeUnicode(e[n]));
            return i.join("&")
        }
        ,
        t.prototype.urlEncodeUnicode = function (t) {
            "string" != typeof t && (t += "");
            for (var e = t.length, i = [], n = 0; n < e; n++) {
                var o = t.charAt(n)
                    , a = t.charCodeAt(n);
                a > 0 && a < 255 ? this.isSafe(o) ? i.push(o) : " " === o ? i.push("+") : (i.push("%"),
                    i.push(this.intToHex(a >> 4 & 15)),
                    i.push(this.intToHex(15 & a))) : (i.push("%u"),
                        i.push(this.intToHex(a >> 12 & 15)),
                        i.push(this.intToHex(a >> 8 & 15)),
                        i.push(this.intToHex(a >> 4 & 15)),
                        i.push(this.intToHex(15 & a)))
            }
            return i.join("")
        }
        ,
        t.prototype.intToHex = function (t) {
            return t <= 9 ? String.fromCharCode(t + 48) : String.fromCharCode(t - 10 + 97)
        }
        ,
        t.prototype.isSafe = function (t) {
            if (t >= "a" && t <= "z" || t >= "A" && t <= "Z" || t >= "0" && t <= "9")
                return !0;
            switch (t) {
                case "'":
                case "(":
                case ")":
                case "*":
                case "-":
                case ".":
                case "_":
                case "!":
                    return !0
            }
            return !1
        }
        ,
        t
}()

function Get_MX_API(timestamp) {
    t = {
        "baseUrl": "api/proxy/content",
        "path": "/pc/command/commendDatas.api",
        "method": "get",
        "data": {
            "pageSymbol": "pc_index",
            "areaSymbol": "pc_index_1",
            "json": "true",
            "tt": timestamp
        }
    }
    var i, c = new r(t.method), A = (new Date).getTime(), p = c.setPostData(t.data), d = c.generateSignature(A, t.path, p), u = "";
    i = c.setMxHead(u, A, d)
    return i
}

然後是Python調用:

import time

import requests
import execjs
def runJS(filePath, funcName, *args):
    with open(filePath, 'r', encoding='utf-8') as f:
        jscode = f.read()

    ctx = execjs.compile(jscode)
    res = ctx.call(funcName, *args)
    return res

t = int(time.time() * 1000)
MX_API = runJS('万达影院在线.js', 'Get_MX_API', t)
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Language': 'zh-TW,zh;q=0.9',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'MX-API': MX_API,
    'Pragma': 'no-cache',
    'Referer': 'https://www.wandacinemas.com/',
    '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/136.0.0.0 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
    'sec-ch-ua': '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
}

params = {
    'tt': t,
}

response = requests.get(
    'https://www.wandacinemas.com/api/proxy/content/pc/movie/coming.api',
    params=params,
    headers=headers,
)
print(response.text)


本站立足于美利堅合衆國,請讀者自覺遵守當地法律!如有違規,本站不承擔任何法律責任! This site is based in the United States of America, readers are requested to abide by local laws! If there are any violations, this site does not bear any legal responsibility! Theme Jasmine by Kent Liao