この大会は2022/10/9 2:00(JST)~2022/10/10 2:00(JST)に開催されました。
今回もチームで参戦。結果は200点で264チーム中163位でした。
自分で解けた問題をWriteupとして書いておきます。
REVMEPLX (rev, bby)
Ghidraでデコンパイルして、各関数を見てみる。
void print_dives(basic_string param_1) { __type _Var1; basic_ostream *pbVar2; undefined4 in_register_0000003c; basic_string *pbVar3; long in_FS_OFFSET; int local_8c; basic_string local_88 [8]; basic_string local_68 [8]; basic_string local_48 [10]; long local_20; pbVar3 = (basic_string *)CONCAT44(in_register_0000003c,param_1); local_20 = *(long *)(in_FS_OFFSET + 0x28); std::allocator<char>::allocator(); /* try { // try from 0010241a to 0010241e has its CatchHandler @ 00102619 */ std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>:: basic_string<std::allocator<char>> ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_88,"Jeremy", (allocator *)&local_8c); std::allocator<char>::~allocator((allocator<char> *)&local_8c); std::allocator<char>::allocator(); /* try { // try from 00102455 to 00102459 has its CatchHandler @ 00102636 */ std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>:: basic_string<std::allocator<char>> ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_68,"Simon", (allocator *)&local_8c); std::allocator<char>::~allocator((allocator<char> *)&local_8c); std::allocator<char>::allocator(); /* try { // try from 00102490 to 00102494 has its CatchHandler @ 0010264a */ std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>:: basic_string<std::allocator<char>> ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_48,"Adminiman", (allocator *)&local_8c); std::allocator<char>::~allocator((allocator<char> *)&local_8c); _Var1 = std::operator==(pbVar3,local_68); if ((char)_Var1 == '\0') { _Var1 = std::operator==(pbVar3,local_48); if ((char)_Var1 == '\0') { _Var1 = std::operator==(pbVar3,local_88); if ((char)_Var1 == '\0') { pbVar2 = std::operator<<((basic_ostream *)std::cout,"No diving recore of diver "); pbVar2 = std::operator<<(pbVar2,pbVar3); std::operator<<(pbVar2," found!\n"); } else { std::operator<<((basic_ostream *)std::cout,"Your dive count is: 0\n"); std::operator<<((basic_ostream *)std::cout, "To show today\'s drydock report, please enter passcode:\n"); std::basic_istream<char,std::char_traits<char>>::operator>> ((basic_istream<char,std::char_traits<char>> *)std::cin,&local_8c); door_lock(local_8c); } } else { std::operator<<((basic_ostream *)std::cout,"Welcome instructor!\n"); std::operator<<((basic_ostream *)std::cout,"Your dive count is: 410\n"); } } else { /* try { // try from 001024d2 to 001025e3 has its CatchHandler @ 0010265e */ std::operator<<((basic_ostream *)std::cout,"Your dive count is: 81\n"); } std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_48); std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_68); std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_88); if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; } void door_lock(int param_1) { basic_ostream *pbVar1; if (param_1 * 2 >> 8 == 0x539) { pbVar1 = std::operator<<((basic_ostream *)std::cout,"CSR{"); pbVar1 = (basic_ostream *) std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar1,param_1 % 0x25); pbVar1 = std::operator<<(pbVar1,"_submarines_"); pbVar1 = (basic_ostream *) std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar1,param_1 * 0x10c + -7); pbVar1 = std::operator<<(pbVar1,"_solved_n1c3!}"); std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar1, std::endl<char,std::char_traits<char>>); } return; }
door_lock関数を呼び出すためには、Diver Nameに"Jeremy"を指定する必要がある。さらにフラグを表示させるためには、passcodeにparam_1 * 2 >> 8 == 0x539を満たすparam_1を指定する必要がある。
>>> (0x539 << 8) // 2 171136
つまりpasscodeには"171136"を指定すればよい。
$ ./rev | >>> REEF RANGERS Dive Panel <<< | | ------------------------------- | | Please provide Diver Name: | Jeremy Your dive count is: 0 To show today's drydock report, please enter passcode: 171136 CSR{11_submarines_45864441_solved_n1c3!}
CSR{11_submarines_45864441_solved_n1c3!}
CRYMEPLX (cry, bby)
フラグと入力文字列で、同じ鍵、nonceでAES-CTR暗号化されるので、以下の計算で復号することができる。
flag = 入力平文 ^ 入力暗号 ^ flag暗号
#!/usr/bin/env python3 import socket from Crypto.Util.strxor import strxor def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('chall.rumble.host', 2734)) data = recvuntil(s, b'\n').rstrip() print(data) enc_flag = bytes.fromhex(data) pt = 'a' * len(enc_flag) data = recvuntil(s, b':') print(data + pt) s.sendall(pt.encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) ct = bytes.fromhex(data) flag = strxor(strxor(pt.encode(), ct), enc_flag).decode() print(flag)
実行結果は以下の通り。
c7342f6c143020c957fdf2dec8209e7aff7514072a511b162f Encrypt this string:aaaaaaaaaaaaaaaaaaaaaaaaa e5061c763b612fcb53efccdedb24a07deb7a131325560f1933 CSR{N0nces_are_funfunfun}
CSR{N0nces_are_funfunfun}