1. 程式人生 > 其它 >【2020XCTF/華為杯】PYPY WriteUp

【2020XCTF/華為杯】PYPY WriteUp

技術標籤:CTF

題目是一個PYPY打包的elf程式,使用pygame寫了一個貪吃蛇遊戲,現有的pyinstaller的解包指令碼好像不太好使,那麼自己動手

根據輸出報錯資訊定位程式碼,這個qword_6077E0應該是反序列化pyc程式碼的函式,gdb斷在這裡,即可拿到對應的pyc檔案

這個函式會被執行4次,第4次是我們期望的程式碼,第四次斷下後使用 dump memory ./dmp $rdi $rdi+$rsi 拿到檔案,補上前8個位元組的檔案頭以後,加上.pyc字尾然後使用uncompyle6反編譯,得到原始碼

DEFAULT_KEY = 'Yó\x02Ã%\x9a\x820\x0b»%\x7f~;ÒÜ'
def rc4(msg, key=DEFAULT_KEY, skip=1024): barray = bytearray([i for i in range(256)]) curr = 0 for i in range(256): curr = (curr + barray[i] + ord(key[(i % len(key))])) % 256 t = barray[i] barray[i] = barray[curr] barray[curr] = t else: curr =
0 another = 0 blist = [] if skip > 0: for i in range(skip): curr = (curr + 1) % 256 another = (another + barray[curr]) % 256 barray[curr], barray[another] = barray[another], barray[curr] for j in msg: curr =
(curr + 1) % 256 another = (another + barray[curr]) % 256 barray[curr], barray[another] = barray[another], barray[curr] t = barray[((barray[curr] + barray[another]) % 256)] blist.append(chr(ord(j) ^ t)) else: return ''.join(blist) def func(): t = rc4('flag{this is a fake flag}') if t.encode( 'utf-8').hex() == '275b39c381c28b701ac3972338456022c2ba06c3b04f5501471c47c38ac380c29b72c3b5c38a7ec2a5c2a0': return 'YOU WIN' return 'YOU LOSE'

程式碼被混淆了,我重新命名了一下變數,提取了關鍵部分貼出來

發現是rc4加密,給了key和加密後的值,當你得到5192296858534827628530496329220096分以後,就會輸出YOU LOSE,如果想得到YOU WIN,則需要讓flag滿足上面的條件

和異或類似,rc4再加密一次就還原了

解密指令碼:

import binascii

msg = binascii.a2b_hex('275b39c381c28b701ac3972338456022c2ba06c3b04f5501471c47c38ac380c29b72c3b5c38a7ec2a5c2a0')
key = 'Yó\x02Ã%\x9a\x820\x0b»%\x7f~;ÒÜ'


def rc4(msg, skip=1024):
    barray = bytearray([i for i in range(256)])
    curr = 0
    for i in range(256):
        curr = (curr + barray[i] + ord(key[(i % len(key))])) % 256
        t = barray[i]
        barray[i] = barray[curr]
        barray[curr] = t
    else:
        curr = 0
        another = 0
        blist = []
        if skip > 0:
            for i in range(skip):
                curr = (curr + 1) % 256
                another = (another + barray[curr]) % 256
                barray[curr], barray[another] = barray[another], barray[curr]

        for j in msg:
            curr = (curr + 1) % 256
            another = (another + barray[curr]) % 256
            barray[curr], barray[another] = barray[another], barray[curr]
            t = barray[((barray[curr] + barray[another]) % 256)]
            blist.append(chr(ord(j) ^ t))
        else:
            return ''.join(blist)


print(rc4(str(msg, 'utf8')))

flag{snake_bao_is_really_lucky}