この大会は2017/11/10 21:00(JST)~2017/11/12 21:00(JST)に開催されました。
今回もチームで参戦。結果は317.63点で532チーム中62位でした。
自分で解けた問題をWriteupとして書いておきます。
easy_sign_in (Web)
問題のURLにアクセスすると、証明書の警告が表示される。
証明書を見ると、IPが123.206.81.217になっている。
http://123.206.81.217にアクセスすると、フラグが書いてある。
hctf{s00000_e4sy_sign_in}
babycrack (Web)
ソースを見ると、JavaScriptのコードが難読化されている。整形だけすると、次のようになる。
var _0x180a=['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); }(_0x180a, 0x1a2)); var _0xa180 = function(_0x5c351c, _0x2046d8) { _0x5c351c = _0x5c351c - 0x0; var _0x26f3b3 = _0x180a[_0x5c351c]; return _0x26f3b3; }; function check(_0x5b7c0c) { try { var _0x2e2f8d = ['code', _0xa180('0x0'), _0xa180('0x1'), _0xa180('0x2'), 'invalidMonetizationCode', _0xa180('0x3'), _0xa180('0x4'), _0xa180('0x5'), _0xa180('0x6'), _0xa180('0x7'), _0xa180('0x8'), _0xa180('0x9'), _0xa180('0xa'), _0xa180('0xb'), _0xa180('0xc'), _0xa180('0xd'), _0xa180('0xe'), _0xa180('0xf'), _0xa180('0x10'), _0xa180('0x11'), 'url', _0xa180('0x12'), _0xa180('0x13'), _0xa180('0x14'), _0xa180('0x15'), _0xa180('0x16'), _0xa180('0x17'), _0xa180('0x18'), 'tabs', _0xa180('0x19'), _0xa180('0x1a'), _0xa180('0x1b'), _0xa180('0x1c'), _0xa180('0x1d'), 'replace', _0xa180('0x1e'), _0xa180('0x1f'), 'includes', _0xa180('0x20'), 'length', _0xa180('0x21'), _0xa180('0x22'), _0xa180('0x23'), _0xa180('0x24'), _0xa180('0x25'), _0xa180('0x26'), _0xa180('0x27'), _0xa180('0x28'), _0xa180('0x29'), 'toString', _0xa180('0x2a'), 'split']; var _0x50559f = _0x5b7c0c[_0x2e2f8d[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 _0xa180('0x2b'); }; _0x46da6f = 0x1; }; while (_0x46da6f--) if (_0x802d91[_0x46da6f]) _0x200db2 = _0x200db2[_0xa180('0x2c')](new RegExp('\x5cb' + _0x2d59cf(_0x46da6f) + '\x5cb', 'g'), _0x802d91[_0x46da6f]); return _0x200db2; }(_0xa180('0x2d'), 0x11, 0x11, _0xa180('0x2e')['split']('|'), 0x0, {})); (function(_0x3291b7, _0xced890) { var _0xaed809 = function(_0x3aba26) { while (--_0x3aba26) { _0x3291b7[_0xa180('0x4')](_0x3291b7['shift']()); } }; _0xaed809(++_0xced890); }(_0x2e2f8d, _0x5cea12 % 0x7b)); var _0x43c8d1 = function(_0x3120e0) { var _0x3120e0 = parseInt(_0x3120e0, 0x10); var _0x3a882f = _0x2e2f8d[_0x3120e0]; return _0x3a882f; }; var _0x1c3854 = function(_0x52ba71) { var _0x52b956 = '0x'; for (var _0x59c050 = 0x0; _0x59c050 < _0x52ba71[_0x43c8d1(0x8)]; _0x59c050++) { _0x52b956 += _0x52ba71[_0x43c8d1('f')](_0x59c050)[_0x43c8d1(0xc)](0x10); } return _0x52b956; }; var _0x76e1e8 = _0x5b7c0c[_0x43c8d1(0xe)]('_'); var _0x34f55b = (_0x1c3854(_0x76e1e8[0x0][_0x43c8d1(0xd)](-0x2, 0x2)) ^ _0x1c3854(_0x76e1e8[0x0][_0x43c8d1(0xd)](0x4, 0x1))) % _0x76e1e8[0x0][_0x43c8d1(0x8)] == 0x5; if (!_0x34f55b) { return ![]; } b2c = function(_0x3f9bc5) { var _0x3c3bd8 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; var _0x4dc510 = []; var _0x4a199f = Math[_0xa180('0x25')](_0x3f9bc5[_0x43c8d1(0x8)] / 0x5); var _0x4ee491 = _0x3f9bc5[_0x43c8d1(0x8)] % 0x5; if (_0x4ee491 != 0x0) { for (var _0x1e1753 = 0x0; _0x1e1753 < 0x5 - _0x4ee491; _0x1e1753++) { _0x3f9bc5 += ''; } _0x4a199f += 0x1; } for (_0x1e1753 = 0x0; _0x1e1753 < _0x4a199f; _0x1e1753++) { _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')](_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5) >> 0x3)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5) & 0x7) << 0x2 | _0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x1) >> 0x6)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x1) & 0x3f) >> 0x1)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x1) & 0x1) << 0x4 | _0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x2) >> 0x4)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x2) & 0xf) << 0x1 | _0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x3) >> 0x7)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x3) & 0x7f) >> 0x2)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')]((_0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x3) & 0x3) << 0x3 | _0x3f9bc5[_0x43c8d1('f')](_0x1e1753 * 0x5 + 0x4) >> 0x5)); _0x4dc510[_0x43c8d1('1b')](_0x3c3bd8[_0x43c8d1('1d')](_0x3f9bc5[_0x43c8d1('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[_0xa180('0x2f')](); for (_0x1e1753 = 0x0; _0x1e1753 < _0x545c12; _0x1e1753++) _0x4dc510[_0x43c8d1('1b')]('='); (function() { (function _0x3c3bd8() { try { (function _0x4dc510(_0x460a91) { if (('' + _0x460a91 / _0x460a91)[_0xa180('0x30')] !== 0x1 || _0x460a91 % 0x14 === 0x0) { (function() {}['constructor']('debugger')()); } else { debugger; } _0x4dc510(++_0x460a91); }(0x0)); } catch (_0x30f185) { setTimeout(_0x3c3bd8, 0x1388); } }()); }()); return _0x4dc510[_0xa180('0x31')](''); }; e = _0x1c3854(b2c(_0x76e1e8[0x2])[_0x43c8d1(0xe)]('=')[0x0]) ^ 0x53a3f32; if (e != 0x4b7c0a73) { return ![]; } f = _0x1c3854(b2c(_0x76e1e8[0x3])[_0x43c8d1(0xe)]('=')[0x0]) ^ e; if (f != 0x4315332) { return ![]; } n = f * e * _0x76e1e8[0x0][_0x43c8d1(0x8)]; h = function(_0x4c466e, _0x28871) { var _0x3ea581 = ''; for (var _0x2fbf7a = 0x0; _0x2fbf7a < _0x4c466e[_0x43c8d1(0x8)]; _0x2fbf7a++) { _0x3ea581 += _0x28871(_0x4c466e[_0x2fbf7a]); } return _0x3ea581; }; j = _0x76e1e8[0x1][_0x43c8d1(0xe)]('3'); if (j[0x0][_0x43c8d1(0x8)] != j[0x1][_0x43c8d1(0x8)] || (_0x1c3854(j[0x0]) ^ _0x1c3854(j[0x1])) != 0x1613) { return ![]; } k = _0xffcc52 => _0xffcc52[_0x43c8d1('f')]() * _0x76e1e8[0x1][_0x43c8d1(0x8)]; l = h(j[0x0], k); if (l != 0x2f9b5072) { return ![]; } m = _0x1c3854(_0x76e1e8[0x4][_0x43c8d1(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][_0x43c8d1(0xd)](0x5, 0x1), 0x2) == _0x76e1e8[0x4][_0x43c8d1(0xd)](-0x5, 0x4) || _0x76e1e8[0x4][_0x43c8d1(0xd)](-0x2, 0x1) - _0x76e1e8[0x4][_0x43c8d1(0xd)](0x4, 0x1) != 0x1) { return ![]; } o = _0x1c3854(_0x76e1e8[0x4][_0x43c8d1(0xd)](0x6, 0x2))[_0x43c8d1(0xd)](0x2) == _0x76e1e8[0x4][_0x43c8d1(0xd)](0x6, 0x1)[_0x43c8d1('f')]() * _0x76e1e8[0x4][_0x43c8d1(0x8)] * 0x5; return o && _0x76e1e8[0x4][_0x43c8d1(0xd)](0x4, 0x1) == 0x2 && _0x76e1e8[0x4][_0x43c8d1(0xd)](0x6, 0x2) == _0x5a6d56(_0x76e1e8[0x4][_0x43c8d1(0xd)](0x7, 0x1), 0x2); } catch (_0x4cbb89) { console['log']('gg'); return ![]; } } function test() { var _0x5bf136 = document[_0xa180('0x32')](_0xa180('0x33'))['value']; if (_0x5bf136 == '') { console[_0xa180('0x34')](_0xa180('0x35')); return ![]; } var _0x4d0e29 = check(_0x5bf136); if (_0x4d0e29) { alert(_0xa180('0x36')); } else { alert(_0xa180('0x37')); } } window['onload'] = function() { setInterval(_0xa180('0x38'), 0x32); test(); };
Chromeのデベロッパーツールを使いながら、デバッグをして進める。詳細は省略するが、_区切りで各文字列について条件があるので、それを満たすように文字列を作り上げる必要がある。しかし、このコードだけでは一つのフラグにならないので、ヒントの情報を使って、フラグを求める。無理やりPythonのコードにすると次のようになる。
import base64 import hashlib e = 0x4b7c0a73 b16_2 = '%x' % (e ^ 0x53a3f32) b36_2 = b16_2.decode('hex') while True: if len(b36_2) % 8 != 0: b36_2 += '=' else: break flag2 = base64.b32decode(b36_2) f = 0x4315332 b16_3 = '%x' % (f ^ 0x4b7c0a73) b36_3 = b16_3.decode('hex') while True: if len(b36_3) % 8 != 0: b36_3 += '=' else: break flag3 = base64.b32decode(b36_3) l = 0x2f9b5072 len_flag1 = 7 len_flag1_1 = 3 str_code = str(l) flag1_1 = '' for i in range(len_flag1_1): code = int(str_code[i*3:i*3+3]) / len_flag1 flag1_1 += chr(code) b16_1_2 = '%x' % (int(flag1_1.encode('hex'), 16) ^ 0x1613) flag1_2 = b16_1_2.decode('hex') flag1 = flag1_1 + '3' + flag1_2 # JavaScript # length of flag1 = 7 len_flag1 = 7 # n % l rest = 529800962 b16_4_1 = '%x' % (rest + 0x48a05362) flag4_1 = b16_4_1.decode('hex') flag4_2 = '2' flag4_3 = '3' for length in range(1, 100): for i in range(20, 80): if int(str(i) + str(i)) == int(str(i), 16) * length * 0x5: flag4_4 = chr(int(str(i), 16)) * 2 len_flag4 = length flag4_5 = '333' flag4_6 = str(int(flag4_2) + 0x1) flag4_7 = '}' flag4 = flag4_1 + flag4_2 + flag4_3 + flag4_4 + flag4_5 + flag4_6 + flag4_7 h = 'd3f154b641251e319855a73b010309a168a12927f3873c97d2e5163ea5cbb443' for i in range(32, 127): for j in range(32, 127): if ((i * 256 + j) ^ ord('{')) % len_flag1 == 0x5: flag0 = 'hctf{' + chr(i) + chr(j) flag = flag0 + '_' + flag1 + '_' + flag2 + '_' + flag3 + '_' + flag4 if hashlib.sha256(flag).hexdigest() == h: print flag
hctf{j5_rev3rse_iz_s0_h4rd23ee3333}