【2021春节】解题领红包之番外篇分析

  • A+
所属分类:逆向工程

作者坛账号:周易


【2021春节】解题领红包之番外篇分析

番外篇一

解压文件,得到番外篇.js。打开文件,如图所示。由题目描述或de4js易得此为JSFuck处理过的。

【2021春节】解题领红包之番外篇分析

番外篇一很简单,直接使用de4js或利用控制台即可还原。
还原后代码如下:

 复制代码 隐藏代码
function _52pojie_MMXXI_(t) {
    let e = [];
    for (let f of t) {
        let t = f.codePointAt(0),
            h = 0;
        t -= 0x1d4 << 0x1c8, "bkd0egfw002whccadqf6gm0q3mi2".match(/../g).forEach(f => {
            f = parseInt(f, 0x24), t >= f && t < f + 0x1A && e.push(h % 7), h++
        })
    }
    let f = [];
    for (; e.length >= 3;) {
        let t = 0x31 * e.shift();
        if (t += 7 * e.shift(), (t += e.shift()) > 0xff) break;
        f.push(t)
    }
    return new Uint8Array(f);
    const flag1 = 'n0w_wh3r3_1s_th3_c1ph3rt3xt?'
}

容易看出flag1为n0w_wh3r3_1s_th3_c1ph3rt3xt?

番外篇二

我们分析函数_52pojie_MMXXI_,不难发现上半部分使用到了Unicode字符。不妨改造代码将其打印,结果如下:

 复制代码 隐藏代码
t = 0x1d4 << 0x1c8, "bkd0egfw002whccadqf6gm0q3mi2".match(/../g).forEach(f => {
    f = parseInt(f, 0x24);
    for (let i = 0; i < 26; i++) {
        document.write(String.fromCodePoint(t + f + i))
    }
    document.write('<br>')
})
 复制代码 隐藏代码
𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭
𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡
𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕
𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙
𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁
𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉
𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓
𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇
𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻
𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯
𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳
𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛
𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣

很明显,我们应该找到一段Unicode原文作为参数,才能得到flag2。但是参数在哪里?这里感谢逍遥一仙给了思路。
在JavaScript中,有一个函数负责将Unicode转为ANSI。这就是String.prototype.normalize()。
因此不妨重载该函数,得到参数。

 复制代码 隐藏代码
(function() {
    var oldString_prototype_normalize = String.prototype.normalize;
    String.prototype.normalize = function() {
        console.log(this.toString() + 'n');
        for (let a of arguments) {
            console.log(a.toString() + 'n');
        }
        return oldString_prototype_normalize.apply(this, arguments);
    }
})();

首先在控制台中运行如上代码,然后再次运行题目,得到结果如下。

【2021春节】解题领红包之番外篇分析

 复制代码 隐藏代码
𝗋𝐞𝚝𝐮𝚛𝘯 𝙛𝘂𝙣𝙘𝗍𝘪𝙤𝐧 _52𝐩𝐨𝐣𝘪𝘦_𝐌𝙈𝙓𝐗𝘐_(𝐭){𝚕𝘦𝙩 𝗲=[];𝙛𝙤𝗋(𝙡𝘦𝒕 𝐟 𝐨𝚏 𝘵){𝙡𝗲𝙩 𝙩=𝖿.𝙘𝘰𝒅𝒆𝐏𝚘𝘪𝙣𝘁𝘼𝙩(0),𝗁=0;𝗍-=0𝙭1𝖽4<<0𝒙1𝐜8,"𝐛𝘬𝘥0𝐞𝐠𝙛𝗐002𝚠𝐡𝐜𝗰𝙖𝐝𝚚𝘧6𝐠𝙢0𝐪3𝚖𝘪2".𝙢𝗮𝙩𝙘𝗁(/../𝗴).𝙛𝙤𝙧𝐄𝐚𝘤𝘩(𝒇=>{𝖿=𝘱𝒂𝙧𝐬𝐞𝗜𝙣𝒕(𝖿,0𝙭24),𝘁>=𝘧&&𝐭<𝚏+0𝘹1𝘼&&𝗲.𝙥𝙪𝗌𝙝(𝙝%7),𝗁++})}𝗹𝐞𝚝 𝘧=[];𝙛𝗼𝙧(;𝙚.𝗅𝙚𝘯𝒈𝐭𝐡>=3;){𝐥𝘦𝘵 𝒕=0𝗑31*𝘦.𝒔𝘩𝗂𝐟𝚝();𝗂𝚏(𝐭+=7*𝘦.𝘀𝒉𝘪𝗳𝚝(),(𝘵+=𝘦.𝘴𝘩𝗶𝐟𝘁())>0𝚡𝚏𝘧)𝗯𝙧𝘦𝗮𝗄;𝘧.𝙥𝙪𝘴𝗁(𝙩)}𝗋𝒆𝒕𝗎𝒓𝐧 𝗻𝐞𝘄 𝗨𝙞𝗇𝘁8𝘼𝒓𝗿𝘢𝒚(𝖿);𝒄𝐨𝗇𝒔𝚝 𝚏𝒍𝐚𝗀1='𝐧0𝗐_𝙬𝗁3𝚛3_1𝘴_𝒕𝐡3_𝙘1𝙥𝗵3𝘳𝒕3𝙭𝘵?'}

这就是我们期待已久的参数了。
重新利用原来的_52pojie_MMXXI_函数,得到数组。我们将其写入文件,不难发现又是JavaScript代码。

 复制代码 隐藏代码
"𝕳ⁱ𝖉𝖊𝓘ₙᵁ𝔫ⅈᶜ𝖔𝖉ⅇ".normalize('NFKD')

在控制台中运行即可得到flag2为HideInUnicode

【2021春节】解题领红包之番外篇分析

后记

此题考查Unicode编码在JavaScript中的应用。

  • 关于乱码的问题
    原始函数返回的是数组。当然也可以进行修改使其打印到控制台中,但有可能出现乱码。解题过程中使用了C写入到文件,并使用文本编辑器打开,没有出现乱码。若使用JavaScript直接打印,则需要使用String.fromCodePoint()

     复制代码 隐藏代码
    #include<stdio.h>
    unsigned char a[] = {
    /* JavaScript中返回的数组 */
    };
    int main() {
    FILE * fp = fopen("out.js", "wb");
    fwrite(a, sizeof(a), 1, fp);
    }
  • 关于如何想出重载
    在JavaScript中,重载一些函数可以使分析更为便捷。常用的重载有eval()Function构造函数等。
    在此题中,重载eval()也能得到结果。

--

www.52pojie.cn


--

pojie_52

本文始发于微信公众号(吾爱破解论坛):【2021春节】解题领红包之番外篇分析

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: