この大会は2018/5/5 13:00(JST)~2018/5/7 1:00(JST)に開催されました。
今回もチームで参戦。結果は451点で986チーム中68位でした。
自分で解けた問題をWriteupとして書いておきます。
macsh (Crypto 125)
'<|>'区切りで1個目がmac, 2個目がcmdline
$ nc macsh.chal.pwning.xxx 64791 |$|> aaa<|>ls macsh: bad tag |$|> aaa<|>oo macsh: oo: command not found |$|> aaa<|>tag echo 123 feb086773d17f6438c7630d7da1dba79 |$|> bbb<|>tag echo 123 feb086773d17f6438c7630d7da1dba79 |$|> aaa<|>tag echo 456 d610717ba31f48a0cbde88926e95bd82 |$|>
k0, k1はランダムな16バイト文字列でmtagを先頭につけたときはmacを表示してくれる。
k0の鍵を割り出そうと考えたが、それは難しい。よく見ると129ブロック目は1ブロック目から鍵を再度使うようになっている。このことを使い、例えば以下のように考える。
ブロック | データ1 | データ2 |
---|---|---|
1ブロック目 | echo 0123456789; | echo 0123456789; |
2ブロック目 | echo 0123456789; | echo 0123456789; |
: | : | : |
128ブロック目 | echo 0123456789; | echo 0123456789; |
129ブロック目 | echo | ls . |
130ブロック目 | コマンド長情報 | コマンド長情報 |
131ブロック目 | padding(\x10*16) | padding(\x10*16) |
こう考えると、データ1とデータ2の129ブロック以外の各ブロックの暗号化のXORは0となるため、echoコマンドとlsコマンドのmacのXORの値がわかる。さらに1ブロック目がechoコマンドの場合とXORを取れば1ブロック目がlsコマンドの場合のmacを取得できる。
lsコマンドでflag.txtがあることがわかるので、cat flag.txtでフラグが得られる。最終的なコードは以下の通り。
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('macsh.chal.pwning.xxx', 64791)) data = recvuntil(s, '|$|> ') print data cmd_head = 'a<|>tag ' #### ls exec #### cmd1 = 'echo 0123456789;' * 128 + 'echo' cmd = cmd_head + cmd1 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac1 = data.split('\n')[0] cmd2 = 'echo 0123456789;' * 128 + 'ls .' cmd = cmd_head + cmd2 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac2 = data.split('\n')[0] cmd3 = 'echo' cmd = cmd_head + cmd3 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac3 = data.split('\n')[0] mac_ls = '%032x' % (int(mac1, 16) ^ int(mac2, 16) ^ int(mac3, 16)) cmd_ls = mac_ls + '<|>ls .' print cmd_ls s.sendall(cmd_ls + '\n') data = recvuntil(s, '|$|> ') print data #### cat exec #### cmd1 = 'echo 0123456789;' * 128 + 'echo 0123456' cmd = cmd_head + cmd1 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac1 = data.split('\n')[0] cmd2 = 'echo 0123456789;' * 128 + 'cat flag.txt' cmd = cmd_head + cmd2 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac2 = data.split('\n')[0] cmd3 = 'echo 0123456' cmd = cmd_head + cmd3 print cmd s.sendall(cmd + '\n') data = recvuntil(s, '|$|> ') print data mac3 = data.split('\n')[0] mac_cat = '%032x' % (int(mac1, 16) ^ int(mac2, 16) ^ int(mac3, 16)) cmd_cat = mac_cat + '<|>cat flag.txt' print cmd_cat s.sendall(cmd_cat + '\n') data = recvuntil(s, '|$|> ') print data
実行結果は以下の通り。
: |$|> 9daabce6ee4c110034527e8a432abd26<|>ls . __pycache__ flag.txt fmac.py macsh.py .bashrc .bash_logout .profile : |$|> e04241a0f78ab714e517439cd7f8dccb<|>cat flag.txt PCTF{fmac_is_busted_use_PMAC_instead} |$|>
PCTF{fmac_is_busted_use_PMAC_instead}