# Pragyan CTF 2019 "EXORcism" writeup
## Description
My friend Alex needs your help very fast. He has been possessed by a ghost and the only way to save him is if you tell the flag to the ghost. Hurry up, time is running out!
## Solution
とりあえずテキストファイルの全体を見たいが、一文字ごとに改行されているのが厄介なので `tr -d '\r\n' `で取り払う。その結果を出力してエディタで開くと、0 がある決まった範囲に現れる事が分かる。
![a](a.png "a")
現れたパターンを観察していると、QRコードっぽいことが分かる。文字数を調べるとちょうど10,000文字であったので、とりあえず100文字ずつで改行した。
すると、このようになった。
![b](b.png "b.png")
確かにQRコードになっていることが分かる。これを画像に変換して読み取る。
画像変換はPythonでPILを用いた。[makeqr.py](makeqr.py)```pythonfrom PIL import Image, ImageDrawfrom pyzbar.pyzbar import decode
def xor_strings(s, t):    if isinstance(s, str):        return "".join(chr(ord(a) ^ ord(b)) for a, b in zip(s, t))    else:        return bytes([a ^ b for a, b in zip(s, t)])
with open('01qr', 'r') as f:    qr = f.read()    qr = qr.split('\n')    usepadding = False
    h, w = len(qr)-1,len(qr[0])    H, W = 500, 500
    image = Image.new('RGB', (H, W), (255,255,255))    black = Image.new('RGB', (5, 5), (255,255,255))    white = Image.new('RGB', (5, 5), (255,255,255))
    black_d = ImageDraw.Draw(black)    white_d = ImageDraw.Draw(white)    black_d.rectangle((0, 0, 5 ,5), fill=(0,0,0))    white_d.rectangle((0, 0, 5 ,5), fill=(255,255,255))
    if usepadding:        padding = (W-len(qr[0])*5)//2    else:        padding = 0
    for i in range(h):        for j in range(w):            if(qr[i][j] == '0'):                image.paste(black, (padding+j*5, padding+i*5))            else:                image.paste(white, (padding+j*5, padding+i*5))
    ans = ''    d = decode(image)[0][0].decode()    for a, b in zip(d[::2], d[1::2]):        ans += chr(int(a+b, 16))
    ans = ''.join(ans)    print(d)    print(ans)    print(xor_strings(ans, 'flagflagflagflagflagflagflagflag'))```
![qr](qr.png "qr")
読み取った結果は`160f15011d1b095339595138535f135613595e1a`
16進数→文字列の変換をするが、`9YQ8S_VY^` となり、ただ変換するだけでは意味のある文字列は得られなかった。ここで、問題名 EXORcism をヒントにXORを取るのだろうと予想したが、何とのXORを取ればよいかが分からない。復号結果は Flag になっているだろうと予想し、読み取った結果を文字列に直したときの先頭5文字と`pctf{`の5文字で試しにXORを取ってみた。すると`flagf`という文字列が得られた。`flagflagflagfl...`と続くと予想し、これとQRコードの復号結果のXORを取ると Flag が取れた。
```pythonfrom PIL import Imagefrom pyzbar.pyzbar import decode
def xor_strings(s, t):    if isinstance(s, str):        return "".join(chr(ord(a) ^ ord(b)) for a, b in zip(s, t))    else:        return bytes([a ^ b for a, b in zip(s, t)])
image = Image.open('qr.png')ans = ''d = decode(image)[0][0].decode()for a, b in zip(d[::2], d[1::2]):    ans += chr(int(a+b, 16))
ans = ''.join(ans)print(d)print(ans)print(xor_strings(ans, 'flagflagflagflagflagflagflagflag'))
```
Flag : `pctf{wh4_50_53r1u5?}`
