靜態分析
無殼 PE 文件,拖入 IDA 反匯編,結構如下:
主函數
12 和 26 行的sub_403CF8
顯然是輸出函數,21 - 25 行的while()
是字符串比較的過程,
看來還是一個輸入 flag 加密驗證正確性的模型
容易發現19行的sub_401080
是加密函數,進入分析:
sub_401080
主體的代碼比較熟悉,是base64加密算法,但在加密前執行了sub_401000()
,這是一個改變密鑰對應表的函數
byte_40E0A0
和byte_40E0AA
看起來是兩個數組,其實都是一個字符串上(即密鑰表串)的地址,
所以這個子函數的功能就是把一個字符串上的范圍內的字符按偏移索引(result)兩兩交換
在操作后,base64 的加密規則未變,但是部分字符的意義發生了變化
在寫逆向腳本代碼的時候可以用 python 的字典構造原密鑰與改過的密鑰的對應關系
在加密后,該函數又調用了sub_401030
sub_401030
不難看出這個子函數把字符串每個英文字符進行了大小寫轉換,最后形成數據段保存的密碼byte_40E0E4
逆向代碼
該程序進行了多重加密,在取出密碼之后首先要進行大小寫轉換,令其出於 base64(更改密鑰表后)加密后的形態
第二步是還原經 base64(更改密鑰表后)加密字符的原含義,還原規則即sub_401000()
的交換
最后得到了真實的nbase64n加密字符串,解密即可得到flag{bAse64_h2s_a_Surprise}
代碼如下:
import base64
flag = ''; dict = {}; offset = 10
orgin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for i in range(len(orgin)):
dict[orgin[i]] = orgin[i]
for i in range(6, 15): #sub_401000()
dict[orgin[i]] , dict[orgin[i+offset]] = dict[orgin[i+offset]] , dict[orgin[i]] # 恢復base64密鑰表
secret = 'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase() #sub_401030()
for i in range(len(secret)):
flag += dict[secret[i]]
flag = base64.b64decode(flag)
print(flag)