Hack Dat Kiwi 2015 Writeup

この大会は2015/11/19 14:00(JST)~2015/11/21 14:00(JST)に開催されました。
予定では11/20の14:00~になっていましたが、1日遅れの開催です。
今回も個人で参戦。就業時間を含む平日の参戦でした。結果は285点で214位。
参加チームは401チームいたようですので、真ん中よりは下で残念な結果です。
それも平日の開催だから仕方がないと思うしかないか...。
解けた問題をWriteupとして書いておきます。

Phone Lock 1 (Web 50)

電話番号4桁を入れる画面。正しい番号を入れるとフラグが表示されるようだ。
HTMLソースを見ると、次のようになっている。

salt="bbf59674ad46586642e826d4947c913a";
valid="e518ffa4372b90c6b5f8e4a48eb77dbb";
      :
function buttonClick(e)
{
      :
    if (md5(salt+result)==valid)
    {
      alert("Flag is: "+md5(salt+result+result));
    }
      :

アクセスするたびに値は変わるが、間違えたりしなければ問題ない。
salt(固定)と番号4桁のmd5がvalid(固定)であるものを探せばよく、
この程度であれば、ブルートフォースで総当たりする。

import hashlib

salt = 'bbf59674ad46586642e826d4947c913a'
valid = 'e518ffa4372b90c6b5f8e4a48eb77dbb'

for i in range(0, 10000):
    number = str(i).zfill(4)
    if hashlib.md5(salt + number).hexdigest() == valid:
        print number
        break

この結果番号は8141であることがわかり、入力するとフラグが表示された。

dd4d33de57b584d4a8dd99eb1950841a

Vigenere 1 (Crypto 50)

タイトルからもわかるとおり、ヴィジュネル暗号の問題で、鍵がフラグになっている。
INPUTで適当にアルファベットを入れて、暗号結果を見ていく。

INPUT:AAAAAAAA
OUTPUT:KIWIK IKI

INPUT:AAAAAAAAAAAAAAAA
OUTPUT:KIWIK IKIWI KIKIW I

この暗号の場合、Aを入れたときの暗号文が鍵の繰り返しになるので、
繰り返しの単位になっている文字列を探せば、鍵はわかる。

KIWIKI

Vigenere 2 (Crypto 80)

この問題もヴィジュネル暗号の問題で、鍵がフラグになっている。
この問題は平文と暗号文が提示されているので、計算すれば簡単にわかる。
鍵の繰り返しを見るために、先頭50文字を見れば十分と考え、次のようなプログラムを作った。

fp = open('plain.txt')
plain = fp.read()
fp.close

fc = open('cipher.txt')
cipher = fc.read()
fc.close()

plain = plain.replace(' ', '')
cipher = cipher.replace(' ', '')

key_repeat = ""
for i in range(50):
    code = ord(cipher[i:i+1]) - ord(plain[i:i+1]) + ord('A')
    if code < 65:
        code = code + 26
    key_repeat += chr(code)

print key_repeat

実行すると、鍵の繰り返しが表示され、フラグがわかる。

XEROX

Gaychal (Reversing 80)

テキストファイルが与えられている。
内容は「<php eval(gzuncompress(base64_decode('」と「')));」で囲まれたかなり長い文字列のデータ。
データをbase64デコードした後、zlib解凍すると、またevalのテキストが表示される。
これは何重にもエンコード、圧縮を繰り返されたデータだと感じたので、プログラムを作成し、内容を調整しながら、復元していくことにした。

import base64
import zlib

f1 = open('gaychal.txt')
data = f1.read()
f1.close()

data = data.replace('<php ', '')

while True:
    if data.startswith('eval(pack(') == True:
        data = data[16:-4]
        data = data.decode('hex')
    elif data.startswith('eval(base64_decode(') == True:
        data = data[20:-4]
        data = data.decode('base64')
    elif data.startswith('eval(hex2bin(') == True:
        data = data[14:-4]
        data = data.decode('hex')
    elif data.startswith('eval(gzuncompress(base64_decode(') == True:
        data = data[33:-4]
        data = data.decode('base64')
        data = zlib.decompress(data)
    else:
        break

f2 = open('result.txt', 'w')
f2.write(data)
f2.close()

この結果得られたデータは、次のようになった。

echo "the flag is ".md5("5+5=9<-- fix this"),PHP_EOL;

これをそのままPHPで実行すると、次のようになる。

the flag is a8cc6eb651a10688e12779b1558193f8

しかし、これをsubmitしても通らない。
fix thisが指している数字を変更する必要がありそうだ。
そこで "5+5=10<-- fix this" として、そのmd5をsubmitしたら通った。

6523359abf1fc63b2bde16fefbc60bc1

Survey (25)

問題でなく、アンケートだった。
アンケートに答えると、フラグが表示された。
f:id:satou-y:20151121214759p:plain

hsABf8jG3VK93hQf