プログラム内のデータと何らか計算したデータを比較する場合、 プログラム内のデータを楽に取得できるGhidra Scriptを使って解くのが便利。 ということでGhidra Scriptを使ったWriteup
とはいっても、Ghidra特有の部分はtoAddrとgetBytesくらい
nostrings
Ghidraで見ると入力した文字列に対して、DAT__00104020の、計算した値と比較していることがわかる。

Flagに使用される文字列はアルファベット大文字小文字、数字、_?!{}くらいであろうことが、stringsの一覧からわかるので
Ghidra Scriptを作成する。
import string
flag_ch = string.ascii_letters + string.digits + '_?!{}'
print(flag_ch)
flag = ''
for i in range(0x40):
for c in flag_ch:
tmp = chr(getBytes(toAddr(0x104020 + (ord(c) * 0x7f + i)),1)[0])
if tmp == c:
flag += c
break
print(flag)
# CakeCTF{th3_b357_p14c3_70_hid3_4_f14g_i5_in_4_f14g_f0r357}
CakeCTF{th3_b357_p14c3_70_hid3_4_f14g_i5_in_4_f14g_f0r357}
Hash browns
こちらも読んでみると入力された文字列の奇数番目のmd5の先頭10桁と偶数番目のsha256の先頭10桁を比較していることがわかる。

md5の比較する対象のデータは順番通りだが、sha256の比較する対象のデータはf関数で順番がいじってある。
今回は使われる文字列がわからないので、記号はstring.punctuationを使用した。
import string
import hashlib
flag_ch = string.ascii_letters + string.digits + flag.punctuation
flag = ''
def f(a,b):
if b == 0:
return 1,0
else:
d, c = f(b, a % b)
d = d - (c * (a // b))
return c,d
for i in range(0x25):
k = f(i,0x25)[0]
if k < 0:
k = k + 0x25
for c in flag_ch:
md5 = hashlib.md5(c).hexdigest()[:10]
calc_val = ''.join([chr(j) for j in getBytes(toAddr(0x1020a0 + (0xb * i)),0xa)])
if md5 == calc_val:
flag += c
break
for c in flag_ch:
sha256= hashlib.sha256(c).hexdigest()[:10]
calc_val = ''.join([chr(j) for j in getBytes(toAddr(0x102240 + (0xb * k)), 0xa)])
if sha256 == calc_val:
flag += c
break
print(flag)
# CakeCTF{(^o^)==(-p-)~~(=_=)~~~POTATOOOO~~~(^@^)++(-_-)**(^o-)_486512778b4}
CakeCTF{(^o^)==(-p-)~~(=_=)~~~POTATOOOO~~~(^@^)++(-_-)**(^o-)_486512778b4}
おわりに
気づいたのが8/29 13時頃だったのが一番の反省。