來源:http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=45
python ByteCode
請看這裡: http://pan.baidu.com/s/1jGpB8DS
下載後是一個名為 crackme.pyc檔案
python逆向基礎資源: 用 Python 反編譯 Python 軟體:http://bbs.pediy.com/archive/index.php?t-111428.html 工具uncompyle2:https://github.com/wibiti/uncompyle2
本題分析:
1.話說用python中的dis模組可以自己編個反編譯器,但是我目前不會,就不羅嗦了。下載uncompyle2後,可以在終端進入uncompyle2目錄下,找到setup.py,就可運行下列命令執行安裝:
python setup.py install
如果要反編譯*.pyc程式,可以運行下列命令:
python C:\Python27\Scripts\uncompyle2 crackme.pyc > crackme.py
其他用法
Examples: uncompyle2 foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout uncompyle2 -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis uncompyle2 -o /tmp /usr/lib/python1.5 # decompile whole library
然後在同目錄下開啟產生的crackme.py
我反編譯出來的內容如下:
# 2016.06.30 18:21:49 中國標準時間#Embedded file name: d:/idf.pydef encrypt(key, seed, string): rst = [] for v in string: rst.append((ord(v) + seed ^ ord(key[seed])) % 255) seed = (seed + 1) % len(key) return rstif __name__ == '__main__': print "Welcome to idf's python crackme" flag = input('Enter the Flag: ') KEY1 = 'Maybe you are good at decryptint Byte Code, have a try!' KEY2 = [124, 48, 52, 59, 164, 50, 37, 62, 67, 52, 48, 6, 1, 122, 3, 22, 72, 1, 1, 14, 46, 27, 232] en_out = encrypt(KEY1, 5, flag) if KEY2 == en_out: print 'You Win' else: print 'Try Again !'+++ okay decompyling crackme.pyc # decompiled 1 files: 1 okay, 0 failed, 0 verify failed# 2016.06.30 18:21:50 中國標準時間
2.從程式看,KEY2內的整數似乎像ascii數值,但數字和英文字元少,直接轉換意義不大。關鍵在於分析encrypt(KEY1, 5, flag)。
3.對encrypt函數的分析:使用者輸入一個字串(ascii值必小於128),然後取出每個字元求其ascii值,加上seed,然後用其和與KEY1中一字元的ascii進行異或(算符^,注意+比^的優先順序高),然後對255求餘。
4.編寫解密程式。顯然正確的密碼字串加密後結果為KEY2,那麼逆向分析編碼即可。程式如下:
#python scriptKEY2 = [124, 48, 52, 59, 164, 50, 37, 62, 67, 52, 48, 6, 1, 122, 3, 22, 72, 1, 1, 14, 46, 27, 232]KEY1 = 'Maybe you are good at decryptint Byte Code, have a try!'def encrypt(key, seed, string): rst = [] for v in string: rst.append((ord(v) + seed ^ ord(key[seed])) % 255) seed = (seed + 1) % len(key) return rstdef decrypt(key,seed,en_out ): string = '' for i in en_out : v = (i ^ ord(key[seed]))-seed seed = (seed + 1) % len(key) if v > 0: string += chr(v) return string if __name__ == '__main__': print decrypt(KEY1,5,KEY2)
答案:WCTF{ILOVEPYTHONSOMUCH}