tkbctf1 writeup

tkbctf1にikachanとして参加してきました。こういったCTFに参加するのは初めてでしたが、とても楽しめました。
運営の皆様大変お疲れ様でした。

Good Old Days (Challenge 7)

個人的にツボでした。問題文はこちら。

[ADVANCED]
I need the "Message" to continue my game but I forgot the secret command!!!
Can you get the "Message"? I remember that the "Message" was alphanumeric characters.

渡されたファイルの中身はなんとファミコンのROMでした。

% file cb0c3d0f55b9b627b831f4fbbc153846
cb0c3d0f55b9b627b831f4fbbc153846: iNES ROM dump, 2x16k PRG, 1x8k CHR, [Vert.], [SRAM]

f:id:akiym:20130506005116j:plain
キー入力ができるようになっていて、それに対して出力される文字が変化する。
f:id:akiym:20130506005224j:plain
f:id:akiym:20130506005240j:plain
おもむろにデバッガ起動。
f:id:akiym:20130506005811j:plain
ブレークポイントを設定、上方向キーを入力。
f:id:akiym:20130506005838j:plain
f:id:akiym:20130506005906j:plain
上方向キーを入力した場合、0xC9でXORされていますね。すべてのキーで調べたところ、

A: 0x36でXOR
B: 0x5CでXOR
↑: 0xC9でXOR
↓: 0xA3でXOR
←: 左ローテート
→: 右ローテート

となっていることがわかりました。
$6000-$6007が順番にキーの入力によって変わるみたいですね。
f:id:akiym:20130506010239j:plain
キー入力後:
f:id:akiym:20130506005347j:plain
大体のことは分かったので、ちょろっとスクリプトを書きます。条件として、メッセージは英数字なのである程度の見当はつくはずです。

use strict;
use warnings;
use utf8;

my %control = (
    a     => sub { $_[0] ^ 0x36 },
    b     => sub { $_[0] ^ 0x5c },
    up    => sub { $_[0] ^ 0xc9 },
    down  => sub { $_[0] ^ 0xa3 },
    left  => sub { $_[0] << 1 },
    right => sub { $_[0] >> 1 },
);

for my $c (0xbe, 0x60, 0xa4, 0xa5, 0x88, 0x64, 0x03, 0x6a) {
    for my $key (keys %control) {
        my $output = chr($control{$key}->($c));
        if ($output =~ /^[A-Za-z0-9]$/) {
            print "$key\t: $output\n";
        }
    }
    print "\n";
}

実行すると、いくつか候補が出てくるのでいい感じに組み合わせると "w0RlD256" がflagだとわかります。
f:id:akiym:20130506010152j:plain