2021 AIS3 Pre Exam - COLORS

Sun, May 30, 2021 8-minute read

題目:COLORS

COLORS

209 points / 53 solves

Challenge Info

DeterminationPatienceBraveryIntegrityPerseveranceKindnessJusticeMore...

http://quiz.ais3.org:8888/

Author: artis24106

Step1 - Analysis

題目連結點開是一個網頁,說是要輸入 secret code 才能得到 flag

有個被混淆過的 encode.js,可以用 beautifier.io 等工具 format 一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const _0x3eb4 = ['repeat', '1YqKovX', ..., 'Backspace'];

function _0x4ebd(_0x532d69, _0x212ed3) {
    _0x532d69 = _0x532d69 - 0x1c6;
    let _0x3eb4a7 = _0x3eb4[_0x532d69];
    return _0x3eb4a7;
}(function(_0x496f79, _0x226742) {
    const _0x463eac = _0x4ebd;
    while (!![]) {
        try {
            const _0x12c745 = -parseInt(_0x463eac(0x1e6)) + parseInt(_0x463eac(0x1ce)) * -parseInt(_0x463eac(0x1de)) + -parseInt(_0x463eac(0x1db)) + -parseInt(_0x463eac(0x1e7)) * parseInt(_0x463eac(0x1d7)) + -parseInt(_0x463eac(0x1d5)) * parseInt(_0x463eac(0x1c9)) + parseInt(_0x463eac(0x1df)) * -parseInt(_0x463eac(0x1d2)) + parseInt(_0x463eac(0x1d9)) * parseInt(_0x463eac(0x1da));
            if (_0x12c745 === _0x226742) break;
            else _0x496f79['push'](_0x496f79['shift']());
        } catch (_0xe36f7) {
            _0x496f79['push'](_0x496f79['shift']());
        }
    }
}(_0x3eb4, 0x57a76), (() => {
    const _0x1cd51f = _0x4ebd,
        _0x54579e = _0x1cd51f(0x1d8),
        _0x78ed5a = _0x1cd51f(0x1ca),
        _0x24fcac = _0x1cd51f(0x1d4),
        _0x2a3765 = 0x8,
        _0x317b6e = 0xa;
    let _0x1e21d9, _0x179193 = 0x0;

    function _0xce93(_0x1b497a) {
        const _0x9fe181 = _0x1cd51f;
        if (!_0x1b497a[_0x9fe181(0x1d0)]) return '';
        let _0x4d62de = '',
            _0x23f867 = '',
            _0x5395cb = 0x0;
        for (let _0x6e40b4 = 0x0; _0x6e40b4 < _0x1b497a[_0x9fe181(0x1d0)]; _0x6e40b4++) _0x4d62de += _0x1b497a[_0x9fe181(0x1dc)](_0x6e40b4)['toString'](0x2)[_0x9fe181(0x1c6)](0x8, '0');
        _0x5395cb = _0x4d62de[_0x9fe181(0x1d0)] % _0x317b6e / 0x2 - 0x1;
        if (_0x5395cb != -0x1) _0x4d62de += '0' [_0x9fe181(0x1c8)](_0x317b6e - _0x4d62de[_0x9fe181(0x1d0)] % _0x317b6e);
        _0x4d62de = _0x4d62de[_0x9fe181(0x1e4)](/(.{1,10})/g);
        for (let _0x13c6bb of _0x4d62de) {
            let _0x192141 = parseInt(_0x13c6bb, 0x2);
            _0x23f867 += _0x9f530c(_0x192141 >> 0x6 & 0x7, _0x192141 >> 0x9, atob(_0x24fcac)[_0x192141 & 0x3f]);
        }
        for (; _0x5395cb > 0x0; _0x5395cb--) {
            _0x23f867 += _0x9f530c(_0x5395cb % _0x2a3765, 0x0, '=');
        }
        return _0x23f867;
    }
    let _0x9f530c = (_0xcc032b, _0x2a8089, _0x244c3a) => '<span><div\x20class=\x22c' + _0xcc032b + '\x20r' + _0x2a8089 + '\x22>' + _0x244c3a + '</div></span>',
        _0x1fdafa = _0x29e3ab => document[_0x1cd51f(0x1e2)](_0x1cd51f(0x1cc))['innerHTML'] = _0xce93(_0x29e3ab);
    document['addEventListener'](_0x1cd51f(0x1cf), _0x23e75c => {
        const _0x12b963 = _0x1cd51f;
        if (_0x23e75c[_0x12b963(0x1e5)] === _0x12b963(0x1c7) && _0x179193 == 0xa) _0x1e21d9[_0x12b963(0x1e3)] = _0x1e21d9['textContent'][_0x12b963(0x1cb)](0x0, _0x1e21d9['textContent'][_0x12b963(0x1d0)] - 0x1);
        else {
            if (_0x23e75c['key'] === _0x12b963(0x1d6) && !(_0x179193 >> 0x1)) return _0x179193 += 0x1;
            else {
                if (_0x23e75c[_0x12b963(0x1e5)] === 'ArrowDown' && !(_0x179193 >> 0x2)) return _0x179193 += 0x1;
                else {
                    if (_0x23e75c[_0x12b963(0x1e5)] === _0x12b963(0x1d3) && (_0x179193 == 0x4 || _0x179193 == 0x6)) return _0x179193 += 0x1;
                    else {
                        if (_0x23e75c[_0x12b963(0x1e5)] === 'ArrowRight' && (_0x179193 == 0x5 || _0x179193 == 0x7)) return _0x179193 += 0x1;
                        else {
                            if (_0x23e75c[_0x12b963(0x1e5)] === 'b' && _0x179193 == 0x8) return _0x179193 += 0x1;
                            else {
                                if (_0x23e75c['key'] === 'a' && _0x179193 == 0x9) return document[_0x12b963(0x1cd)](_0x12b963(0x1e0))[0x0]['innerHTML'] += atob(_0x54579e), _0x1e21d9 = document[_0x12b963(0x1e2)](_0x12b963(0x1e8)), _0x1e21d9[_0x12b963(0x1d1)] = '', document[_0x12b963(0x1e2)]('output')[_0x12b963(0x1d1)] = atob(_0x78ed5a)[_0x12b963(0x1e4)](/(.{1,3})/g)[_0x12b963(0x1e1)](_0x5efa9e => _0x9f530c(_0x5efa9e[0x0], _0x5efa9e[0x1], _0x5efa9e[0x2]))[_0x12b963(0x1dd)](''), _0x179193 += 0x1;
                                else {
                                    if (_0x23e75c[_0x12b963(0x1e5)][_0x12b963(0x1d0)] == 0x1 && _0x179193 == 0xa) _0x1e21d9[_0x12b963(0x1e3)] += String['fromCharCode'](_0x23e75c[_0x12b963(0x1e5)][_0x12b963(0x1dc)]());
                                    else return;
                                }
                            }
                        }
                    }
                }
            }
        }
        _0x1fdafa(_0x1e21d9[_0x12b963(0x1e3)]);
    });
})());

觀察到 _0x4ebd = _0x1cd51f = _0x9fe181 = _0x12b963 這個 function 被大量使用。_0x4ebd 是全域變數,可以直接在 console 呼叫,比如說 _0x12b963(0x1e5) = "key", _0x4ebd(0x1cf) = "keydown",所以把所有值取出來手動還原程式碼,順便重命名其他變數跟函數名稱。

還原完的程式碼

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const _0x3eb4 = ['repeat', '1YqKovX', 'NDBCMjBnMzBpNTFKNjA2MDFcMzB3NDAxMzBBNDFqNDBcNDExMzBnNzB1MzBpMTBrMzBsNDA3NjB4NTBpNTBYMTBLMTBJNDBoNTBYMDBLNDFpNTFsNzA2NzBmNDBvMTA2NTA1NzBLMTFuNTE4NzA3NDFCNTAtMTE4NDB3MzFhMTByNDF6NzBLMzA9MjA9MTA9', 'substr', 'output', 'getElementsByTagName', '65022JgPEZp', 'keydown', 'length', 'innerHTML', '677PRUQAU', 'ArrowLeft', 'QWxTM3tCYXNFNjRfaTUrYjByTkluZ35cUXdvLy14SDhXekNqN3ZGRDJleVZrdHFPTDFHaEtZdWZtWmRKcFg5fQ==', '133781JKLWBV', 'ArrowUp', '90407czXCgh', 'PGRpdiBzdHlsZT0id2lkdGg6IDM1MHB4OyBwb3NpdGlvbjogYWJzb2x1dGU7IGJvdHRvbTogMHB4OyBsZWZ0OiAwcHg7Ij48ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7IGFuaW1hdGlvbjogcmFpbmJvdyAycyBsaW5lYXIgMHMgaW5maW5pdGUgbm9ybWFsOyBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogLTEwcHg7IGxlZnQ6IDUwJTsgZm9udC1zaXplOiAyMHB4OyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7IHdpZHRoOiAzNTBweDsiPkhlcmUgaXMgeW91cjxicj4iZW5jb2RlZCIgZmxhZyw8YnI+aW5wdXQgdG8gZW5jb2RlIHNvbWV0aGluZyBlbHNlITwvZGl2PiA8c3ZnIGlkPSLwn5CIIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGlkPSJib2R5Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJmaWxsIiBkdXI9IjUwMG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIga2V5VGltZXM9IjA7MC4xOzAuMjswLjM7MC40OzAuNTswLjY7MC43OzAuODswLjk7MSIgdmFsdWVzPSIgI2ZmOGQ4YjsgI2ZlZDY4OTsgIzg4ZmY4OTsgIzg3ZmZmZjsgIzhiYjVmZTsgI2Q3OGNmZjsgI2ZmOGNmZjsgI2ZmNjhmNzsgI2ZlNmNiNzsgI2ZmNjk2ODsgI2ZmOGQ4YiAiPjwvYW5pbWF0ZT48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJkIiBkdXI9IjUwMG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIga2V5VGltZXM9IjA7MC4xOzAuMjswLjM7MC40OzAuNTswLjY7MC43OzAuODswLjk7MSIgdmFsdWVzPSIgTTY3LjEsMTA5LjVjLTkuNiwwLTIzLjYtOC44LTIzLjYtMjRjMC0xMi4xLDE3LjgtNDEsMzcuNS00MWMxNS42LDAsMjMuMywxMC42LDI1LjEsMjAuNSBjMS45LDEwLjcsMy45LDguMiwzLjksMTkuNWMwLDguMi0zLjgsMTctMy44LDIyLjNjMCwzLjksMS40LDcuNCwyLjksMTAuNWMxLjcsMy41LDIuNCw2LjYsMi40LDkuMkg5LjVjMC0xMy43LDEwLjgtMTQsMjEuMS0yMyBjNS42LTQuOSwxMS0xMi40LDE0LjUtMjY7IE01Ni4xLDEwNy41Yy05LjYsMC0yNC42LTEzLjgtMjQuNi0yOWMwLTE2LjIsMTMtNDIsMzMuNS00MmMxNy44LDAsMjIuMywxMS42LDI2LjEsMjIuNSBjMy42LDEwLjMsOS45LDkuMiw5LjksMjAuNWMwLDguMi0xLjgsNy0xLjgsMTIuM2MwLDQuNSwzLjQsOC4yLDYuNCwxNC4xYzIuNSw0LjgsNC44LDExLjIsNC44LDIwLjZoLTk5YzAtMTIuMSw3LjItMTcuNiwxNC43LTI0LjMgYzMuMi0yLjksNi41LTUuOSw5LjItOS44OyBNNDUuMSwxMDkuNWMtNS41LTAuMi0yNy42LTguNC0yNy42LTI3YzAtMTcuOSwxNC44LTQyLDMyLjUtNDJjMTUuNCwwLDI0LDEwLjQsMjYuMSwyMS41IGMxLjMsNi43LDkuOSw5LjgsOS45LDIxLjVjMCw4LjItMC44LDYtMC44LDExLjNjMCw3LjcsMTIuOCw5LDIwLjgsMTVjNy43LDUuOCwxNS41LDE2LjcsMTUuNSwxNi43aC0xMTBjMC00LjgsMS43LTExLjMsNS0xNiBjMy4yLTQuNSw0LjUtOC4zLDUtMTU7IE0zNiwxMjBjLTUuNS0wLjItMjguNS0xMS45LTI4LjUtMzAuNWMwLTE2LjIsMTIuNS00MiwzMy00MmMxNy44LDAsMjEuOCw5LjYsMjUuNiwyMC41IEM2OS43LDc4LjMsNzYsNzguMiw3Niw4OS41YzAsOC4yLTAuOCw0LTAuOCw5LjNjMCw1LjksMTYuNSw3LjgsMjguNCwxNS45YzgsNS41LDE3LjksMTEuOCwxNy45LDExLjhoLTExMGMwLTIuMS0xLjItNS4yLTEuOS0xNC41IGMtMC4zLTMuNi0wLjUtOC4xLTAuNS0xMy45OyBNMzcsMTE5LjVjLTE1LDAuMS0zMy41LTEyLjctMzMuNS0zMEMzLjUsNzMuMywxNiw0NywzNi41LDQ3YzE3LjgsMCwyMi44LDExLDI2LDIyIEM2NS42LDc5LjQsNzMsNzkuMiw3Myw5MC41YzAsNC0xLjgsNi42LTEuOCw4LjNjMCw1LjksMTQuMiw2LjQsMjYuNCwxNS45YzcuNyw2LDEzLjksMTEuOCwxMy45LDExLjhINy41Yy0xLjItMy40LTEuOC03LjMtMS45LTExLjIgYy0wLjItNS4xLDAuMy0xMC4xLDAuOS0xMy43OyBNNDAuNSwxMjEuNWMtMTIuNiwwLTMwLTEzLjQtMzAtMjlDMTAuNSw3Ni4zLDIzLDUzLDQzLjUsNTNjMTQuNSwwLDIyLjgsOS42LDI1LDIyIGMxLjIsNi45LDEwLDkuMiwxMCwyMC41YzAsNCwwLDUuNiwwLDcuM2MwLDQuOSw2LjEsNy41LDExLjIsMTEuOWM1LjgsNSw3LjIsMTEuOCw3LjIsMTEuOEg4LjVjMC0xLjUtMC42LTYuMSwwLjQtMTEuOCBjMC42LTMuNSwxLjktNy41LDQuMy0xMS42OyBNNDguNSwxMjEuNWMtMTIuNiwwLTI1LTYuMy0yNS0xOGMwLTE2LjIsMTMuNy00NywzNi00N2MxNS42LDAsMjQuOCw5LjEsMjcsMjEuNSBjMS4yLDYuOSw3LDkuMiw3LDE4LjVjMCw5LjUtNCwxMS00LDIyYzAsNC4xLDAuNSw1LDEsNmMwLjUsMS4yLDEsMiwxLDJoLTgxYzAtNS4zLDMuMS04LjMsNi4zLTExLjVjMi42LTIuNiw1LjQtNS4zLDYuNy05LjU7IE02OC41LDEyMS41Yy0xMi42LDAtMzMtNS44LTMzLTIzYzAtOS4yLDExLjgtMzYsMzctMzZjMTUuNiwwLDI1LjgsOC4xLDI4LDIwLjUgYzEuMiw2LjksNCw2LjIsNCwxNS41YzAsOS41LTUsMTUuMS01LDIxYzAsMS45LDEsMi4zLDEsNWMwLDEuMiwwLDIsMCwyaC05MWMwLjUtNy42LDcuMS0xMS4xLDEzLjctMTUuN2M0LjktMy40LDkuOS03LjUsMTIuMy0xNC4zOyBNNzMuNSwxMTcuNWMtMTIuNiwwLTMwLTYuMi0zMC0yNWMwLTE0LjIsMjAuOS0zNywzOC0zN2MxNy42LDAsMjUuOCwxMS4xLDI4LDIzLjUgYzEuMiw2LjksMyw3LjIsMywxNi41YzAsMTIuMS02LDE2LjEtNiwyMmMwLDQuMiwyLDUuMywyLDhjMCwxLjIsMCwxLDAsMUg3LjVjMi4xLTkuNCwxMC40LTEzLjMsMTkuMi0xOS40IGM3LjEtNSwxNC40LTExLjUsMTguOC0yMy42OyBNODAuNSwxMTUuNWMtMTIuNiwwLTMyLTkuMi0zMi0yOGMwLTE0LjIsMjIuOS0zNSw0MC0zNWMxNy42LDAsMjUuOCwxMi4xLDI4LDI0LjUgYzEuMiw2LjksMyw2LjIsMywxNS41YzAsMTIuMS02LDE5LjEtNiwyNWMwLDQuMiwyLDUuMywyLDhjMCwxLjIsMCwxLDAsMWgtMTAyYzIuMy04LjcsMTEuNi0xMS43LDIwLjgtMjAuMSBjNS4zLTQuOCwxMC41LTExLjQsMTQuMi0yMS45OyBNNjcuMSwxMDkuNWMtOS42LDAtMjMuNi04LjgtMjMuNi0yNGMwLTEyLjEsMTcuOC00MSwzNy41LTQxYzE1LjYsMCwyMy4zLDEwLjYsMjUuMSwyMC41IGMxLjksMTAuNywzLjksOC4yLDMuOSwxOS41YzAsOC4yLTMuOCwxNy0zLjgsMjIuM2MwLDMuOSwxLjQsNy40LDIuOSwxMC41YzEuNywzLjUsMi40LDYuNiwyLjQsOS4ySDkuNWMwLTEzLjcsMTAuOC0xNCwyMS4xLTIzIGM1LjYtNC45LDExLTEyLjQsMTQuNS0yNiAiPjwvYW5pbWF0ZT48L3BhdGg+PHBhdGggaWQ9ImJlYWsiIGZpbGw9IiM3YjhjNjgiPjxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9ImQiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IiBNNzguMjksNzBjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzc4LjI5LDg1LjUsNzguMjksNzBaOyBNNjIuMjksNjRjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzYyLjI5LDc5LjUsNjIuMjksNjRaOyBNNDguMjksNjdjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzQ4LjI5LDgyLjUsNDguMjksNjdaOyBNMzYuMjksNzNjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzM2LjI5LDg4LjUsMzYuMjksNzNaOyBNMzUuMjksNzVjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzM1LjI5LDkwLjUsMzUuMjksNzVaOyBNNDEuMjksODFjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzQxLjI5LDk2LjUsNDEuMjksODFaOyBNNTkuMjksODRjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzU5LjI5LDk5LjUsNTkuMjksODRaOyBNNzIuMjksODljMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzcyLjI5LDEwNC41LDcyLjI5LDg5WjsgTTgwLjI5LDgyYzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M4MC4yOSw5Ny41LDgwLjI5LDgyWjsgTTg3LjI5LDc4YzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M4Ny4yOSw5My41LDg3LjI5LDc4WjsgTTc4LjI5LDcwYzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M3OC4yOSw4NS41LDc4LjI5LDcwWiAiPjwvYW5pbWF0ZT48L3BhdGg+PGVsbGlwc2UgaWQ9ImV5ZS1yaWdodCIgcng9IjMiIHJ5PSI0Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeCIgZHVyPSI1MDBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGtleVRpbWVzPSIwOzAuMTswLjI7MC4zOzAuNDswLjU7MC42OzAuNzswLjg7MC45OzEiIHZhbHVlcz0iMTAwOzg0OzcwOzU4OzU3OzYzOzgxOzk0OzEwMjsxMDk7MTAwIj48L2FuaW1hdGU+PGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IjYyOzU2OzU5OzY1OzY3OzczOzc2OzgxOzc0OzcwOzYyIj48L2FuaW1hdGU+PC9lbGxpcHNlPjxlbGxpcHNlIGlkPSJleWUtbGVmdCIgcng9IjMiIHJ5PSI0Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeCIgZHVyPSI1MDBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGtleVRpbWVzPSIwOzAuMTswLjI7MC4zOzAuNDswLjU7MC42OzAuNzswLjg7MC45OzEiIHZhbHVlcz0iNjcuNTs1MS41OzM3LjU7MjUuNTsyNC41OzMwLjU7NDguNTs2MS41OzY5LjU7NzYuNTs2Ny41Ij48L2FuaW1hdGU+PGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IjYyOzU2OzU5OzY1OzY3OzczOzc2OzgxOzc0OzcwOzYyIj48L2FuaW1hdGU+PC9lbGxpcHNlPjwvc3ZnPjwvZGl2Pg==', '131837PcDnWL', '19pQimXL', '623605MIswVM', 'charCodeAt', 'join', '4WsUYDr', '686oWrfyq', 'body', 'map', 'getElementById', 'textContent', 'match', 'key', '302349wKdZHP', '4OYJFlQ', 'input', 'padStart', 'Backspace'];

function _0x4ebd(_0x532d69, _0x212ed3) {
    _0x532d69 = _0x532d69 - 0x1c6;
    let _0x3eb4a7 = _0x3eb4[_0x532d69];
    return _0x3eb4a7;
} (function (_0x496f79, _0x226742) {
    const _0x463eac = _0x4ebd;
    while (!![]) {
        try {
            const _0x12c745 = -parseInt(_0x463eac(0x1e6)) + parseInt(_0x463eac(0x1ce)) * -parseInt(_0x463eac(0x1de)) + -parseInt(_0x463eac(0x1db)) + -parseInt(_0x463eac(0x1e7)) * parseInt(_0x463eac(0x1d7)) + -parseInt(_0x463eac(0x1d5)) * parseInt(_0x463eac(0x1c9)) + parseInt(_0x463eac(0x1df)) * -parseInt(_0x463eac(0x1d2)) + parseInt(_0x463eac(0x1d9)) * parseInt(_0x463eac(0x1da));
            if (_0x12c745 === _0x226742) break;
            else _0x496f79['push'](_0x496f79['shift']());
        } catch (_0xe36f7) {
            _0x496f79['push'](_0x496f79['shift']());
        }
    }
}(_0x3eb4, 0x57a76), (() => {
    const _0x1cd51f = _0x4ebd,
        base64FlagHint = "PGRpdiBzdHlsZT0id2lkdGg6IDM1MHB4OyBwb3NpdGlvbjogYWJzb2x1dGU7IGJvdHRvbTogMHB4OyBsZWZ0OiAwcHg7Ij48ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7IGFuaW1hdGlvbjogcmFpbmJvdyAycyBsaW5lYXIgMHMgaW5maW5pdGUgbm9ybWFsOyBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogLTEwcHg7IGxlZnQ6IDUwJTsgZm9udC1zaXplOiAyMHB4OyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7IHdpZHRoOiAzNTBweDsiPkhlcmUgaXMgeW91cjxicj4iZW5jb2RlZCIgZmxhZyw8YnI+aW5wdXQgdG8gZW5jb2RlIHNvbWV0aGluZyBlbHNlITwvZGl2PiA8c3ZnIGlkPSLwn5CIIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGlkPSJib2R5Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJmaWxsIiBkdXI9IjUwMG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIga2V5VGltZXM9IjA7MC4xOzAuMjswLjM7MC40OzAuNTswLjY7MC43OzAuODswLjk7MSIgdmFsdWVzPSIgI2ZmOGQ4YjsgI2ZlZDY4OTsgIzg4ZmY4OTsgIzg3ZmZmZjsgIzhiYjVmZTsgI2Q3OGNmZjsgI2ZmOGNmZjsgI2ZmNjhmNzsgI2ZlNmNiNzsgI2ZmNjk2ODsgI2ZmOGQ4YiAiPjwvYW5pbWF0ZT48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJkIiBkdXI9IjUwMG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIga2V5VGltZXM9IjA7MC4xOzAuMjswLjM7MC40OzAuNTswLjY7MC43OzAuODswLjk7MSIgdmFsdWVzPSIgTTY3LjEsMTA5LjVjLTkuNiwwLTIzLjYtOC44LTIzLjYtMjRjMC0xMi4xLDE3LjgtNDEsMzcuNS00MWMxNS42LDAsMjMuMywxMC42LDI1LjEsMjAuNSBjMS45LDEwLjcsMy45LDguMiwzLjksMTkuNWMwLDguMi0zLjgsMTctMy44LDIyLjNjMCwzLjksMS40LDcuNCwyLjksMTAuNWMxLjcsMy41LDIuNCw2LjYsMi40LDkuMkg5LjVjMC0xMy43LDEwLjgtMTQsMjEuMS0yMyBjNS42LTQuOSwxMS0xMi40LDE0LjUtMjY7IE01Ni4xLDEwNy41Yy05LjYsMC0yNC42LTEzLjgtMjQuNi0yOWMwLTE2LjIsMTMtNDIsMzMuNS00MmMxNy44LDAsMjIuMywxMS42LDI2LjEsMjIuNSBjMy42LDEwLjMsOS45LDkuMiw5LjksMjAuNWMwLDguMi0xLjgsNy0xLjgsMTIuM2MwLDQuNSwzLjQsOC4yLDYuNCwxNC4xYzIuNSw0LjgsNC44LDExLjIsNC44LDIwLjZoLTk5YzAtMTIuMSw3LjItMTcuNiwxNC43LTI0LjMgYzMuMi0yLjksNi41LTUuOSw5LjItOS44OyBNNDUuMSwxMDkuNWMtNS41LTAuMi0yNy42LTguNC0yNy42LTI3YzAtMTcuOSwxNC44LTQyLDMyLjUtNDJjMTUuNCwwLDI0LDEwLjQsMjYuMSwyMS41IGMxLjMsNi43LDkuOSw5LjgsOS45LDIxLjVjMCw4LjItMC44LDYtMC44LDExLjNjMCw3LjcsMTIuOCw5LDIwLjgsMTVjNy43LDUuOCwxNS41LDE2LjcsMTUuNSwxNi43aC0xMTBjMC00LjgsMS43LTExLjMsNS0xNiBjMy4yLTQuNSw0LjUtOC4zLDUtMTU7IE0zNiwxMjBjLTUuNS0wLjItMjguNS0xMS45LTI4LjUtMzAuNWMwLTE2LjIsMTIuNS00MiwzMy00MmMxNy44LDAsMjEuOCw5LjYsMjUuNiwyMC41IEM2OS43LDc4LjMsNzYsNzguMiw3Niw4OS41YzAsOC4yLTAuOCw0LTAuOCw5LjNjMCw1LjksMTYuNSw3LjgsMjguNCwxNS45YzgsNS41LDE3LjksMTEuOCwxNy45LDExLjhoLTExMGMwLTIuMS0xLjItNS4yLTEuOS0xNC41IGMtMC4zLTMuNi0wLjUtOC4xLTAuNS0xMy45OyBNMzcsMTE5LjVjLTE1LDAuMS0zMy41LTEyLjctMzMuNS0zMEMzLjUsNzMuMywxNiw0NywzNi41LDQ3YzE3LjgsMCwyMi44LDExLDI2LDIyIEM2NS42LDc5LjQsNzMsNzkuMiw3Myw5MC41YzAsNC0xLjgsNi42LTEuOCw4LjNjMCw1LjksMTQuMiw2LjQsMjYuNCwxNS45YzcuNyw2LDEzLjksMTEuOCwxMy45LDExLjhINy41Yy0xLjItMy40LTEuOC03LjMtMS45LTExLjIgYy0wLjItNS4xLDAuMy0xMC4xLDAuOS0xMy43OyBNNDAuNSwxMjEuNWMtMTIuNiwwLTMwLTEzLjQtMzAtMjlDMTAuNSw3Ni4zLDIzLDUzLDQzLjUsNTNjMTQuNSwwLDIyLjgsOS42LDI1LDIyIGMxLjIsNi45LDEwLDkuMiwxMCwyMC41YzAsNCwwLDUuNiwwLDcuM2MwLDQuOSw2LjEsNy41LDExLjIsMTEuOWM1LjgsNSw3LjIsMTEuOCw3LjIsMTEuOEg4LjVjMC0xLjUtMC42LTYuMSwwLjQtMTEuOCBjMC42LTMuNSwxLjktNy41LDQuMy0xMS42OyBNNDguNSwxMjEuNWMtMTIuNiwwLTI1LTYuMy0yNS0xOGMwLTE2LjIsMTMuNy00NywzNi00N2MxNS42LDAsMjQuOCw5LjEsMjcsMjEuNSBjMS4yLDYuOSw3LDkuMiw3LDE4LjVjMCw5LjUtNCwxMS00LDIyYzAsNC4xLDAuNSw1LDEsNmMwLjUsMS4yLDEsMiwxLDJoLTgxYzAtNS4zLDMuMS04LjMsNi4zLTExLjVjMi42LTIuNiw1LjQtNS4zLDYuNy05LjU7IE02OC41LDEyMS41Yy0xMi42LDAtMzMtNS44LTMzLTIzYzAtOS4yLDExLjgtMzYsMzctMzZjMTUuNiwwLDI1LjgsOC4xLDI4LDIwLjUgYzEuMiw2LjksNCw2LjIsNCwxNS41YzAsOS41LTUsMTUuMS01LDIxYzAsMS45LDEsMi4zLDEsNWMwLDEuMiwwLDIsMCwyaC05MWMwLjUtNy42LDcuMS0xMS4xLDEzLjctMTUuN2M0LjktMy40LDkuOS03LjUsMTIuMy0xNC4zOyBNNzMuNSwxMTcuNWMtMTIuNiwwLTMwLTYuMi0zMC0yNWMwLTE0LjIsMjAuOS0zNywzOC0zN2MxNy42LDAsMjUuOCwxMS4xLDI4LDIzLjUgYzEuMiw2LjksMyw3LjIsMywxNi41YzAsMTIuMS02LDE2LjEtNiwyMmMwLDQuMiwyLDUuMywyLDhjMCwxLjIsMCwxLDAsMUg3LjVjMi4xLTkuNCwxMC40LTEzLjMsMTkuMi0xOS40IGM3LjEtNSwxNC40LTExLjUsMTguOC0yMy42OyBNODAuNSwxMTUuNWMtMTIuNiwwLTMyLTkuMi0zMi0yOGMwLTE0LjIsMjIuOS0zNSw0MC0zNWMxNy42LDAsMjUuOCwxMi4xLDI4LDI0LjUgYzEuMiw2LjksMyw2LjIsMywxNS41YzAsMTIuMS02LDE5LjEtNiwyNWMwLDQuMiwyLDUuMywyLDhjMCwxLjIsMCwxLDAsMWgtMTAyYzIuMy04LjcsMTEuNi0xMS43LDIwLjgtMjAuMSBjNS4zLTQuOCwxMC41LTExLjQsMTQuMi0yMS45OyBNNjcuMSwxMDkuNWMtOS42LDAtMjMuNi04LjgtMjMuNi0yNGMwLTEyLjEsMTcuOC00MSwzNy41LTQxYzE1LjYsMCwyMy4zLDEwLjYsMjUuMSwyMC41IGMxLjksMTAuNywzLjksOC4yLDMuOSwxOS41YzAsOC4yLTMuOCwxNy0zLjgsMjIuM2MwLDMuOSwxLjQsNy40LDIuOSwxMC41YzEuNywzLjUsMi40LDYuNiwyLjQsOS4ySDkuNWMwLTEzLjcsMTAuOC0xNCwyMS4xLTIzIGM1LjYtNC45LDExLTEyLjQsMTQuNS0yNiAiPjwvYW5pbWF0ZT48L3BhdGg+PHBhdGggaWQ9ImJlYWsiIGZpbGw9IiM3YjhjNjgiPjxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9ImQiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IiBNNzguMjksNzBjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzc4LjI5LDg1LjUsNzguMjksNzBaOyBNNjIuMjksNjRjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzYyLjI5LDc5LjUsNjIuMjksNjRaOyBNNDguMjksNjdjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzQ4LjI5LDgyLjUsNDguMjksNjdaOyBNMzYuMjksNzNjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzM2LjI5LDg4LjUsMzYuMjksNzNaOyBNMzUuMjksNzVjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzM1LjI5LDkwLjUsMzUuMjksNzVaOyBNNDEuMjksODFjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzQxLjI5LDk2LjUsNDEuMjksODFaOyBNNTkuMjksODRjMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzU5LjI5LDk5LjUsNTkuMjksODRaOyBNNzIuMjksODljMC05LjkyLDIuNS0xNCw4LTE0czgsMi4xNyw4LDEwLjY3YzAsMTUuOTItNywyNi4zMy03LDI2LjMzUzcyLjI5LDEwNC41LDcyLjI5LDg5WjsgTTgwLjI5LDgyYzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M4MC4yOSw5Ny41LDgwLjI5LDgyWjsgTTg3LjI5LDc4YzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M4Ny4yOSw5My41LDg3LjI5LDc4WjsgTTc4LjI5LDcwYzAtOS45MiwyLjUtMTQsOC0xNHM4LDIuMTcsOCwxMC42N2MwLDE1LjkyLTcsMjYuMzMtNywyNi4zM1M3OC4yOSw4NS41LDc4LjI5LDcwWiAiPjwvYW5pbWF0ZT48L3BhdGg+PGVsbGlwc2UgaWQ9ImV5ZS1yaWdodCIgcng9IjMiIHJ5PSI0Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeCIgZHVyPSI1MDBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGtleVRpbWVzPSIwOzAuMTswLjI7MC4zOzAuNDswLjU7MC42OzAuNzswLjg7MC45OzEiIHZhbHVlcz0iMTAwOzg0OzcwOzU4OzU3OzYzOzgxOzk0OzEwMjsxMDk7MTAwIj48L2FuaW1hdGU+PGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IjYyOzU2OzU5OzY1OzY3OzczOzc2OzgxOzc0OzcwOzYyIj48L2FuaW1hdGU+PC9lbGxpcHNlPjxlbGxpcHNlIGlkPSJleWUtbGVmdCIgcng9IjMiIHJ5PSI0Ij48YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeCIgZHVyPSI1MDBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGtleVRpbWVzPSIwOzAuMTswLjI7MC4zOzAuNDswLjU7MC42OzAuNzswLjg7MC45OzEiIHZhbHVlcz0iNjcuNTs1MS41OzM3LjU7MjUuNTsyNC41OzMwLjU7NDguNTs2MS41OzY5LjU7NzYuNTs2Ny41Ij48L2FuaW1hdGU+PGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiIGR1cj0iNTAwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBrZXlUaW1lcz0iMDswLjE7MC4yOzAuMzswLjQ7MC41OzAuNjswLjc7MC44OzAuOTsxIiB2YWx1ZXM9IjYyOzU2OzU5OzY1OzY3OzczOzc2OzgxOzc0OzcwOzYyIj48L2FuaW1hdGU+PC9lbGxpcHNlPjwvc3ZnPjwvZGl2Pg==",
        base64EncodedFlag = "NDBCMjBnMzBpNTFKNjA2MDFcMzB3NDAxMzBBNDFqNDBcNDExMzBnNzB1MzBpMTBrMzBsNDA3NjB4NTBpNTBYMTBLMTBJNDBoNTBYMDBLNDFpNTFsNzA2NzBmNDBvMTA2NTA1NzBLMTFuNTE4NzA3NDFCNTAtMTE4NDB3MzFhMTByNDF6NzBLMzA9MjA9MTA9",
        base64FakeFlag = "QWxTM3tCYXNFNjRfaTUrYjByTkluZ35cUXdvLy14SDhXekNqN3ZGRDJleVZrdHFPTDFHaEtZdWZtWmRKcFg5fQ==",
        const_8 = 0x8,
        const_10 = 0xa;
    let inputEl, state = 0x0;

    function encode(textContent) {
        const _0x9fe181 = _0x1cd51f;
        if (!textContent["length"]) return '';
        let binary_str = '',
            ret_str = '',
            countPadding = 0x0;
        for (let i = 0x0; i < textContent["length"]; i++) binary_str += textContent["charCodeAt"](i)['toString'](0x2)["padStart"](0x8, '0');
        countPadding = binary_str["length"] % const_10 / 0x2 - 0x1;
        if (countPadding != -0x1) binary_str += '0'["repeat"](const_10 - binary_str["length"] % const_10);
        binary_str = binary_str["match"](/(.{1,10})/g);
        for (let _0x13c6bb of binary_str) {
            let number = parseInt(_0x13c6bb, 0x2);
            ret_str += makeHTML(number >> 0x6 & 0x7, number >> 0x9, atob(base64FakeFlag)[number & 0x3f]);
        }
        for (; countPadding > 0x0; countPadding--) {
            ret_str += makeHTML(countPadding % const_8, 0x0, '=');
        }
        return ret_str;
    }
    let makeHTML = (para1, para2, para3) => '<span><div\x20class=\x22c' + para1 + '\x20r' + para2 + '\x22>' + para3 + '</div></span>',
        setOutputHTML = textContent => document["getElementById"]("output")['innerHTML'] = encode(textContent);
    document['addEventListener']("keydown", event => {
        const _0x12b963 = _0x1cd51f;
        if (event["key"] === "Backspace" && state == 0xa) inputEl["textContent"] = inputEl['textContent']["substr"](0x0, inputEl['textContent']["length"] - 0x1);
        else {
            if (event['key'] === "ArrowUp" && !(state >> 0x1)) return state += 0x1;
            else {
                if (event["key"] === 'ArrowDown' && !(state >> 0x2)) return state += 0x1;
                else {
                    if (event["key"] === "ArrowLeft" && (state == 0x4 || state == 0x6)) return state += 0x1;
                    else {
                        if (event["key"] === 'ArrowRight' && (state == 0x5 || state == 0x7)) return state += 0x1;
                        else {
                            if (event["key"] === 'b' && state == 0x8) return state += 0x1;
                            else {
                                if (event['key'] === 'a' && state == 0x9) return document["getElementsByTagName"]("body")[0x0]['innerHTML'] += atob(base64FlagHint),
                                    inputEl = document["getElementById"]("input"),
                                    inputEl["innerHTML"] = '',
                                    document["getElementById"]('output')["innerHTML"] = atob(base64EncodedFlag)["match"](/(.{1,3})/g)["map"](result =>
                                        makeHTML(result[0x0], result[0x1], result[0x2])
                                    )["join"](''),
                                    state += 0x1;
                                else {
                                    if (event["key"]["length"] == 0x1 && state == 0xa) inputEl["textContent"] += String['fromCharCode'](event["key"]["charCodeAt"]());
                                    else return;
                                }
                            }
                        }
                    }
                }
            }
        }
        setOutputHTML(inputEl["textContent"]);
    });
})());

Step2 - Input Secret Code

先看 event handler

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
let makeHTML = (para1, para2, para3) => '<span><div\x20class=\x22c' + para1 + '\x20r' + para2 + '\x22>' + para3 + '</div></span>',
    setOutputHTML = textContent => document["getElementById"]("output")['innerHTML'] = encode(textContent);
document['addEventListener']("keydown", event => {
    const _0x12b963 = _0x1cd51f;
    if (event["key"] === "Backspace" && state == 0xa) inputEl["textContent"] = inputEl['textContent']["substr"](0x0, inputEl['textContent']["length"] - 0x1);
    else {
        if (event['key'] === "ArrowUp" && !(state >> 0x1)) return state += 0x1;
        else {
            if (event["key"] === 'ArrowDown' && !(state >> 0x2)) return state += 0x1;
            else {
                if (event["key"] === "ArrowLeft" && (state == 0x4 || state == 0x6)) return state += 0x1;
                else {
                    if (event["key"] === 'ArrowRight' && (state == 0x5 || state == 0x7)) return state += 0x1;
                    else {
                        if (event["key"] === 'b' && state == 0x8) return state += 0x1;
                        else {
                            if (event['key'] === 'a' && state == 0x9) return document["getElementsByTagName"]("body")[0x0]['innerHTML'] += atob(base64FlagHint),
                                inputEl = document["getElementById"]("input"),
                                inputEl["innerHTML"] = '',
                                document["getElementById"]('output')["innerHTML"] = atob(base64EncodedFlag)["match"](/(.{1,3})/g)["map"](result =>
                                    makeHTML(result[0x0], result[0x1], result[0x2])
                                )["join"](''),
                                state += 0x1;
                            else {
                                if (event["key"]["length"] == 0x1 && state == 0xa) inputEl["textContent"] += String['fromCharCode'](event["key"]["charCodeAt"]());
                                else return;
                            }
                        }
                    }
                }
            }
        }
    }
    setOutputHTML(inputEl["textContent"]);
});

可以知道在正確的 state 按特定鍵會讓 state + 1,也就是要輸入 Konami Code(上上下下左右左右ba)作為 secret code。輸入之後出現一隻彩虹迷因鸚鵡,並且提示網頁上的是 encode 過的 flag。

從 65~66 行可以知道 encoded flag 是 base64EncodedFlag 在 base64 decode 之後,每三個字元切開並呼叫 makeHTML 的結果。

接下來可以任意輸入,會將輸入存在 inputEl["textContent"],並且呼叫 setOutputHTML(inputEl["textContent"]);,然後因為 setOutputHTML 裡面會呼叫 encode,所以接下來看 encode function。

Step3 - How To Encode?

直接把 encode 在做什麼寫在註解裡面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function encode(textContent) {
    const _0x9fe181 = _0x1cd51f;
    if (!textContent["length"]) return '';
    let binary_str = '',
        ret_str = '',
        countPadding = 0x0;

    // 將每個字元轉換成長度 8 的二進位字串,並且存在 `binary_str`
    for (let i = 0x0; i < textContent["length"]; i++) binary_str += textContent["charCodeAt"](i)['toString'](0x2)["padStart"](0x8, '0');

    // 計算 padding
    countPadding = binary_str["length"] % const_10 / 0x2 - 0x1; 
    if (countPadding != -0x1) binary_str += '0'["repeat"](const_10 - binary_str["length"] % const_10);

    // 將 `binary_str` 每 10 個切開
    binary_str = binary_str["match"](/(.{1,10})/g);
    for (let el of binary_str) {
        let number = parseInt(el, 0x2); // 將 `el` 轉換成 integer
        ret_str += makeHTML(number >> 0x6 & 0x7, number >> 0x9, atob(base64FakeFlag)[number & 0x3f]);
        // 呼叫 `makeHTML`,其中:
        // number >> 0x6 & 0x7 -> number 第 2-4 bits
        // number >> 0x9 -> number 第 1 bit
        // number & 0x3f -> number 第 5-10 bits
        // atob(base64FakeFlag) = "AlS3{BasE64_i5+b0rNIng~\Qwo/-xH8WzCj7vFD2eyVktqOL1GhKYufmZdJpX9}"
    }

    // 補 `countPadding` 個 '=' 
    for (; countPadding > 0x0; countPadding--) {
        ret_str += makeHTML(countPadding % const_8, 0x0, '=');
    }
    return ret_str;
}

簡單來說 encode 的方法是:

  1. 將輸入每個字元轉換成 8 bits 二進位字串接在一起
  2. 補上 “00000000”,直到二進位字串長度為 40 的倍數
  3. 每 10 bits 一組做成 '<span><div class="c' + para1 + ' r' + para2 + '">' + para3 + '</div></span>' 接在一起
    • para1 = 第 2-4 bits,也就是 class c0~c7,控制字元顏色
    • para2 = 第 1 bit,也就是 class r0~r1,控制字元是否要水平翻轉
    • para3 = atob(base64FakeFlag)[idx],從 AlS3{BasE64_i5+b0rNIng~\Qwo/-xH8WzCj7vFD2eyVktqOL1GhKYufmZdJpX9} 中選第 idx 個字元
      • idx = 第 5-10 bits
      • atob(base64FakeFlag) = AlS3{BasE64_i5+b0rNIng~\Qwo/-xH8WzCj7vFD2eyVktqOL1GhKYufmZdJpX9}
  4. 補上 padding

也就是說它是 base64 的變體

附上 encode "HA" 的圖解

輸出為(使用 Rubik Mono One 字體,所以看不出大小寫)

Step4 - Decode Encoded Flag

最後附上解碼腳本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re
from base64 import b64decode


base64FakeFlag = "QWxTM3tCYXNFNjRfaTUrYjByTkluZ35cUXdvLy14SDhXekNqN3ZGRDJleVZrdHFPTDFHaEtZdWZtWmRKcFg5fQ=="
base64EncodedFlag = "NDBCMjBnMzBpNTFKNjA2MDFcMzB3NDAxMzBBNDFqNDBcNDExMzBnNzB1MzBpMTBrMzBsNDA3NjB4NTBpNTBYMTBLMTBJNDBoNTBYMDBLNDFpNTFsNzA2NzBmNDBvMTA2NTA1NzBLMTFuNTE4NzA3NDFCNTAtMTE4NDB3MzFhMTByNDF6NzBLMzA9MjA9MTA9"

# AlS3{BasE64_i5+b0rNIng~\x5cQwo/-xH8WzCj7vFD2eyVktqOL1GhKYufmZdJpX9}
base1024_table = b64decode(base64FakeFlag).decode()
encoded_flag = b64decode(base64EncodedFlag).decode()
data = ''

for el in re.findall(r'\d\d.', encoded_flag):
    if el[2] == '=':
        data += '0' * 8
        continue
    data += el[1]
    data += '{0:03b}'.format(int(el[0]))
    data += '{0:06b}'.format(base1024_table.index(el[2]))


for i in range(0, len(data), 8):
    print(chr(int(data[i:i+8], 2)), end='')
print()

Flag

AIS3{base1024_15_c0l0RFuL_GAM3_CL3Ar_thIS_IS_y0Ur_FlaG!}