Harekaze mini CTF 2020 Write-up
2020/12/26 10:00 JST - 12/27 10:00 JST (24H) に開催されたCTFのWrite-upです。チーム名: whitecatsで出場して378pt. 全体51位でした。
Easy Flag Checker [rev]
このバイナリに文字列を与えると、フラグであるかどうかチェックしてくれます。 This binary checks if the input is the flag.
フラグチェック処理のGhidraでの逆コンパイル部分。param_1
が入力文字列、param_2
がfakeflag{this_is_not_the_real_flag}
という文字列。
funcs
は、インデックス0~2でそれぞれadd
、sub
、xor
の処理をするだけの関数で、fakeflagとtable
というデータを順番に処理している。table
の中身は、ソルバーに記載。
undefined8 check(long param_1,long param_2) { char cVar1; int index; index = 0; while( true ) { if (0x22 < index) { return 0; } cVar1 = (**(code **)(funcs + (long)(index % 3) * 8)) ((int)*(char *)(param_2 + index),(int)(char)table[index]); if (cVar1 < *(char *)(param_1 + index)) break; if (*(char *)(param_1 + index) < cVar1) { return 0xffffffff; } index = index + 1; } return 1; }
ソルバーは、fakeflagとtableのデータを順番に処理するだけ。xorしたデータだけprintableの範囲を超えるので、最終的に128で割った余りにしている。
# -*- coding: utf-8 funcs = ['\x96\x11\x40\x00\x00\x00\x00\x00', # return a + b '\xb4\x11\x40\x00\x00\x00\x00\x00', # return a - b '\xd4\x11\x40\x00\x00\x00\x00\x00'] # return a ^ b # -> 0: add, 1: sub(), 3: xor() def add(i, j): return ord(i) + ord(j) def sub(i, j): return ord(i) - ord(j) def xor(i, j): return ord(i) ^ ord(j) functions = [add, sub, xor] ''' table XREF[3]: Entry Point(*), check:0040124f(*), check:00401256(R) 00404060 e2 00 19 undefine 00 fb 0d 19 02 38 00404060 e2 undefined1E2h [0] XREF[3]: Entry Point(*), check:0040124f(*), check:00401256(R) 00404061 00 undefined100h [1] 00404062 19 undefined119h [2] 00404063 00 undefined100h [3] 00404064 fb undefined1FBh [4] 00404065 0d undefined10Dh [5] 00404066 19 undefined119h [6] 00404067 02 undefined102h [7] 00404068 38 undefined138h [8] 00404069 e0 undefined1E0h [9] 0040406a 22 undefined122h [10] 0040406b 12 undefined112h [11] 0040406c bd undefined1BDh [12] 0040406d ed undefined1EDh [13] 0040406e 1d undefined11Dh [14] 0040406f f5 undefined1F5h [15] 00404070 2f undefined12Fh [16] 00404071 0a undefined10Ah [17] 00404072 c1 undefined1C1h [18] 00404073 fc undefined1FCh [19] 00404074 00 undefined100h [20] 00404075 f2 undefined1F2h [21] 00404076 fc undefined1FCh [22] 00404077 51 undefined151h [23] 00404078 08 undefined108h [24] 00404079 13 undefined113h [25] 0040407a 06 undefined106h [26] 0040407b 07 undefined107h [27] 0040407c 39 undefined139h [28] 0040407d 3c undefined13Ch [29] 0040407e 05 undefined105h [30] 0040407f 39 undefined139h [31] 00404080 13 undefined113h [32] 00404081 ba undefined1BAh [33] 00404082 00 undefined100h [34] ''' table = '\xe2\x00\x19\x00\xfb\x0d\x19\x02' table += '\x38\xe0\x22\x12\xbd\xed\x1d\xf5' table += '\x2f\x0a\xc1\xfc\x00\xf2\xfc\x51' table += '\x08\x13\x06\x07\x39\x3c\x05\x39' table += '\x13\xba\x00' fake_flag = "fakeflag{this_is_not_the_real_flag}" i = 0 cVal = [] for i in range(len(fake_flag)): param0 = fake_flag[i] param1 = table[i] cVal += [functions[i % 3](param0, param1)] cVal = list(map(lambda x: x % 128, cVal)) print(''.join(map(chr, cVal))) ''' $ python3 solve.py HarekazeCTF{0rth0d0x_fl4g_ch3ck3r!} '''
Flag: HarekazeCTF{0rth0d0x_fl4g_ch3ck3r!}
Wait [rev]
Please be patient. Brute-force attacks on the score server are prohibited.
実行すると、HINT: ^HarekazeCTF\{ID[A-Z]{4}X\}$
と出力される。求めるのは[A-Z]{4}
の4文字分。実行ファイルは、フラグチェック前に3秒のsleepが実行されるので、その処理を潰して実行ファイルに対してブルートフォースするか、チェック処理のところを解析して外部で処理するかの2択ぐらい。
sleep実行処理は、いろいろとチェック処理が入っていて潰すのが面倒くさそうだったので、後者でソルバーを作成。フラグのチェック処理は、HarekazeCTF\{ID[A-Z]{4}X\}$
とSALT\x00
という文字列を結合した文字列のSHA1ハッシュが1fcce7ec44beb72c994e2cd69c462916ca8ec810
になるかの確認だけ。(最初\x00
部分が抜けていて、ちょっと気づくのに時間がかかった)
# -*- coding: utf-8 -*- from hashlib import sha1 from itertools import product def main(): # HINT: ^HarekazeCTF\{ID[A-Z]{4}X\}$ ''' debug 'HarekazeCTF{IDZZZZX}' 0x7fffffffe100: 0xe9 0xcc 0x8d 0x45 0xa1 0x44 0x28 0xee 0x7fffffffe108: 0xd2 0xa2 0x2a 0xa8 0x2b 0xfc 0x36 0x80 0x7fffffffe110: 0xa9 0x37 0xae 0x7d 0x0 0x0 0x0 0x0 ''' ''' local_78[0] = '\x1f'; local_78[1] = 0xcc; local_78[2] = 0xe7; local_78[3] = 0xec; local_78[4] = 0x44; local_78[5] = 0xbe; local_78[6] = 0xb7; local_78[7] = 0x2c; local_78[8] = 0x99; local_78[9] = 0x4e; local_78[10] = 0x2c; local_78[11] = 0xd6; local_78[12] = 0x9c; local_78[13] = 0x46; local_78[14] = 0x29; local_78[15] = 0x16; local_78[16] = 0xca; local_78[17] = 0x8e; local_78[18] = 0xc8; local_78[19] = 0x10; ''' correct_sha1 = [0x1f, 0xcc, 0xe7, 0xec, 0x44, 0xbe, 0xb7, 0x2c, 0x99, 0x4e, 0x2c, 0xd6, 0x9c, 0x46, 0x29, 0x16, 0xca, 0x8e, 0xc8, 0x10] correct_sha1_md = ''.join(map(lambda x: x[2:], map(hex, correct_sha1))) seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' cnt = 0 for s in product(seed, repeat=4): FLAG = 'HarekazeCTF{ID' + ''.join(s) + 'X}' FLAG += 'SALT\x00' flag_sha1 = sha1(FLAG.encode('utf-8')) flag_md = flag_sha1.hexdigest() print(cnt, FLAG, ':', flag_md, correct_sha1_md) cnt += 1 if flag_md == correct_sha1_md: print('!!!! GET FLAG !!!!') break if __name__ == '__main__': main() ''' $ python3 solve.py : 298850 HarekazeCTF{IDRACGX}SALT : c539a4d9c7352680001a03046ad37c697e609d1b 1fcce7ec44beb72c994e2cd69c462916ca8ec810 298851 HarekazeCTF{IDRACHX}SALT : 917aeeb01e576f5c66bd61f86c96e685b9895abf 1fcce7ec44beb72c994e2cd69c462916ca8ec810 298852 HarekazeCTF{IDRACIX}SALT : 1fcce7ec44beb72c994e2cd69c462916ca8ec810 1fcce7ec44beb72c994e2cd69c462916ca8ec810 !!!! GET FLAG !!!! '''
Flag: HarekazeCTF{IDRACIX}
以上です。