记录遇到的一个新的变种JS加密

WX20231204-144436@2x.png


逻辑分析

混淆代码的目的是隐藏实际逻辑,增加逆向工程的难度。以下是对代码的逐步分析和解读。


第一部分:立即调用的函数表达式 (IIFE)

(function () {
    var _K = [...]; // 存储大量字符串的数组
})();
1.  **目的**:这个 IIFE 是整个代码运行的入口,它封装了一系列变量和函数,避免全局命名空间污染。

2.  **_K 数组**:这是一个重要的混淆手段,将脚本中使用的字符串统一存储在一个数组中,通过索引引用。

•   好处:可以压缩代码,减少重复字符串的占用空间。

•   难点:代码阅读者需要追踪每个索引的实际含义。

第二部分:字符串的引用方式

_K[0], _K[1], ..., _K[n]
1.  **作用**:通过 _K 数组的索引访问字符串。

2.  **影响**:

•   原始的字符串内容被隐藏了。

•   阅读者需要先还原 _K 数组中的字符串,才能理解代码。

示例:还原字符串的方法

如果我们要还原 _K 的第一个元素 _K[0],可以直接打印这个数组,或者在控制台执行以下代码:

console.log(_K[0]); // 会输出 'DgfIBgu'

通过这种方式逐一还原 _K 的内容,可以帮助我们理解代码。


第三部分:核心逻辑的隐藏

在这种混淆代码中,通常会利用字符串数组和动态计算来隐藏核心逻辑。例如:

var a = _K[5] + _K[12];
  1. 问题:由于 _K 的内容是动态的,我们无法直接从代码中看出 a 的值。

  2. 解决办法:需要跟踪这些动态操作,或者在运行时断点调试,查看 a 的真实值。


第四部分:动态调用与函数名混淆

混淆后的代码常见如下形式:

someFunction(_K[23], _K[7]);

函数名:someFunction 很可能被混淆为一个毫无意义的名称。

参数:参数内容也经过 _K 数组混淆,使得调用的逻辑难以追踪。


第五部分:还原与解混淆思路

1. 定位 _K 数组

将其打印输出或保存到文件中:

console.log(_K);

分析每个字符串的内容。

2. 跟踪动态调用

在浏览器或 Node.js 中运行代码,并在关键函数上设置断点。

•   使用 debugger 语句。

•   查看调用栈,逐步分析逻辑。

3. 代码格式化

使用代码格式化工具(如 Prettier 或 Beautify)来美化代码结构,提高可读性。


混淆代码背后的逻辑

混淆后的代码往往是为了:

•   隐藏敏感逻辑,如授权验证、算法实现。

•   增加逆向工程的难度。

要解混淆,需要一定的耐心和技巧。若需要进一步帮助,可以提供更多上下文或执行环境信息。

代码翻译解密后局部一览

function L8() {
    var L9 = Z.channelCode;
    var LL = {
        channelCode: L9,
        av: L7("v", Z.appKey) ? "1" : "0",
        cv: L9 && L7("v", Z.appKey, L9) ? "1" : "0",
        apkFileName: Z.apkFileName,
        preferWakeup: Z.preferWakeup,
        hash: d.hash,
        _pkgId: Z._pkgId,
        fastInstall: Z.fastInstall
    };
    var LW = X(L9);
    y(function (LK) {
        var La = Z.server ? Z.server : P;
        I({
            url: i(La + "/web/" + Z.appKey + "/" + LW + "/init", LL, LK),
            method: "POST",
            contentType: "text/plain;charset=utf-8",
            data: T,
            timeout: 5000,
            error: function () {
                D(function () {
                    L2 = true;
                    g.ready();
                });
            },
            success: function (LD) {
                D(function () {
                    LD.sh && (e = L6(LD.sh));
                    F = LD.fu;
                    J = LD.fm;
                    f = LD.ft;
                    x = LD.su;
                    G = LD.sm;
                    U = LD.st;
                    Y = LD.ph ? S(LD.ph) : null;
                    E = LD.pyp ? S(LD.pyp) : null;
                    o = LD.pye ? parseInt(S(LD.pye) || "0") : 0;
                    j = LD.dsoi;
                    L9 = LD.channelCode;
                    L0 = LD.csu;
                    L1 = LD.cpc;
                    var LV = LD.fr;
                    LV && (F = i(F, {
                        ref: d.href
                    }));
                    g.ready();
                });
            }
        });
    });
}

彻底还原后一览

function initialize() {
    var channelCode = data.channelCode;
    var requestPayload = {
        channelCode: channelCode,
        av: validateFlag("v", data.appKey) ? "1" : "0",
        cv: channelCode && validateFlag("v", data.appKey, channelCode) ? "1" : "0",
        apkFileName: data.apkFileName,
        preferWakeup: data.preferWakeup,
        hash: d.hash,
        _pkgId: data._pkgId,
        fastInstall: data.fastInstall
    };
    var channelInfo = getChannelInfo(channelCode);
    asyncFunction(function (callback) {
        var serverUrl = data.server ? data.server : P;
        I({
            url: constructUrl(serverUrl + "/web/" + data.appKey + "/" + channelInfo + "/init", requestPayload, callback),
            method: "POST",
            contentType: "text/plain;charset=utf-8",
            data: T,
            timeout: 5000,
            error: function () {
                runAsync(function () {
                    isErrorState = true;
                    globalHandler.ready();
                });
            },
            success: function (response) {
                runAsync(function () {
                    if (response.sh) {
                        secretHash = processHash(response.sh);
                    }
                    fileUrl = response.fu;
                    fileMetadata = response.fm;
                    fileType = response.ft;
                    serverUrl = response.su;
                    serverMetadata = response.sm;
                    serverTimestamp = response.st;
                    if (response.ph) {
                        packageHash = S(response.ph);
                    } else {
                        packageHash = null;
                    }
                    if (response.pyp) {
                        paymentHash = S(response.pyp);
                    } else {
                        paymentHash = null;
                    }
                    if (response.pye) {
                        paymentError = parseInt(S(response.pye) || "0");
                    } else {
                        paymentError = 0;
                    }
                    debugInfo = response.dsoi;
                    channelCode = response.channelCode;
                    customServerUrl = response.csu;
                    customPackageCode = response.cpc;
                    var referrer = response.fr;
                    if (referrer) {
                        fileUrl = constructUrl(fileUrl, {
                            ref: d.href
                        });
                    }
                    globalHandler.ready();
                });
            }
        });
    });
}

该文章最终解释权归《湖南唯凡科技网络有限公司》jsjiami官方客服所有。

请勿将代码拿去用于非法用途。

有任何疑问欢迎咨询。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,576评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,515评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,017评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,626评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,625评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,255评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,825评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,729评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,271评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,363评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,498评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,183评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,867评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,338评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,458评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,906评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,507评论 2 359

推荐阅读更多精彩内容