2020 AIS3 EOF Final - Extensive Flag Checker

Thu, Aug 26, 2021 2-minute read

題目:Extensive Flag Checker

2020 AIS3 EOF Final 的最後一題啦

Extensive Flag Checker (350)

Challenge Info

I found a flag checker from my grandma’s computer. Can you check it for me?

Download: https://drive.google.com/file/d/1S3ZQsug3-KtX_Ob-J0jH7GZA-xUXF47p/view?usp=sharing (de-compress password: notinfected)

Author: Inndy

ExtensiveFlagChecker.exe

Solution

實際執行,是個有 GUI 的 flag checker

輸入框在很下面,螢幕不夠大會看不到XD,需要的話可以把它移上面一點

.Net 老樣子丟 dnSpy,排除掉假 flag 跟明顯不可能的 hash 檢查,能追到一個 check function

它會先把使用者輸入寫進 "C:\\Windows\\Temp\\flag.txt",然後呼叫 CreateThread 執行 Resources 中的 shellcode(native_checker

shellcode 首先會做 decode(self modifying),對當前執行的 instruction 後面的所有內容 ^, +- 一個定值,總共 200 次,最後停在 base + 0x19c8(可以設定一個硬體斷點)

不想寫手動 decode 腳本,我的作法是用 x64dbg 先斷在 CreateThread,然後手動改 RIP 跳進 shellcode,再 F9 讓程式爛掉,就可以把完整的 shellcode dump 出來(不知道有沒有更好的方法)

decode 完之後會去爬 ntdll.dll 呼叫一些函式(沒仔細追XD),總之是把 "C:\\Windows\\Temp\\flag.txt" 讀進來

接下來是取輸入的 3 bytes 出來做 hash 然後檢查,總共 43 次(最後一次明顯是 \x00 不重要)

3 bytes 所以輕鬆爆破,寫腳本搞定:

 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
from string import printable
from itertools import product

hash_list = [0x3e40cb2f, 0xcc03266, 0xea7c6b98, 0xbcbb5310, 0xe9ea9a7f, 0x293f1b89, 0x3e82fdc7, 0x3cc88b88, 0x7e5f0a67, 0xbf8a3407, 0x6c2789c7, 0x5459d1df, 0xa26a4014, 0x7f9ec0d2, 0xde72e2db, 0xa5db9645, 0x2bc37848, 0x7f6f3d0a, 0x981ddff2, 0x5484ed19, 0x8676c0,
             0x6869caa9, 0x55be7aa8, 0xbb97a7ed, 0x972791be, 0xd4213c70, 0x38baafd, 0x15b2ca0e, 0xc81e938d, 0xc1497e5f, 0xd7a8eef4, 0x45080959, 0x39d213c6, 0xdbe05299, 0xa3564671, 0x17d4f44d, 0x9d0369f, 0x126b772f, 0xbcbb5310, 0x2fbe9d56, 0x5484ed19, 0xb5c06f98]
hash_set = set(hash_list)
hash_dict = dict()

X32_UINT_MAX = 0x100000000


def x32_uint(a):
    if a < 0:
        return x32_uint(a + X32_UINT_MAX)
    if a >= X32_UINT_MAX:
        return x32_uint(a & (X32_UINT_MAX - 1))
    return a


def mul(a, b):
    return x32_uint(a * b)


def minus(a, b):
    return x32_uint(a - b)


def xor(a, b):
    return x32_uint(a ^ b)


def gen_flag():
    flag = ''
    for h in hash_list:
        flag += hash_dict[h] if h in hash_dict.keys() else '___'
    return flag


def hash(data):
    cksm = 1
    for d in data:
        cksm = mul(0x314159, minus(cksm, ord(d)))
        cksm = xor(cksm, cksm >> 3)
    cksm -= len(data) + 1
    if cksm in hash_set:
        hash_dict[cksm] = ''.join(data)
        print(f"[+] Found: {hex(cksm)}\t'{hash_dict[cksm]}'\t'{gen_flag()}'")


for el in product(printable, repeat=3):
    hash(el)
    if len(hash_dict) == len(hash_set):
        break

Flag

AIS3{So you had some skill about reverse windows shellcode. Contact inndy.lin@cycarrier.com for an internship if you like. :D}

其實 ARAY4 還比較難(麻煩)一些,為什麼當初沒有解出來QQ