2015年12月7日月曜日

SECCON 2015 Online CTF write-up

はじめに

ロボコン屋がチームTonkatsuNabeに入ってお茶汲み枠でCTF出ようと思ったら すでにいたので文鎮枠で出たお話を書きます。

ぼくが解けた問題

(null)

ぼくが解けそうだった問題

Reverse-Engineering Hardware 1

もうやられてるだろうと思って寝てたら誰もやってなかったので昼前に起きて朝飯食べて そこから始めました。

どんな問題だったのか

写真を見て、回路を想像し、シミュレートするだけの問題です。やるだけの問題ですが、 写真を見るのがとにかくめんどくさかったので400点問題だったのでしょう。 写真でなく回路図やネットリストだったなら50点くらいの問題でした。

おそらくシミュレート方法くらいしか解けたチームのやり方に違いはないはずです。

ICとトランジスタとダイオードと

IC

ICの型番は写真をクワッと目をみると74HC74と書いてあります。7474ですよ皆さん! D-FlipFlopが2つ入ってるだけです。CLKも同じ所につながっています。 何もむずかしいことはありません。

トランジスタとダイオード

おそらくこの問題の唯一の教養部分でしょう。工学系、情報系なら1年生でお話されるはずです。

トランジスタとダイオードをは以下の図の様につながっており、これでOR+NOTでNOR回路となっています。 型番は推測ですが2SC1815と1N4148だったのではないでしょうか。 最初、これはトランジスタかFETどっちかなとか、 日本で一般的なECB配列か海外でありがちなEBC配列のどっちかなとかいろいろ悩みましたが、 ダイオードから伸びている抵抗の接続を見て、まあECB配列のNPNトランジスタかなと決定しました。

LEDですが問題を解くために必要ないので特に考えなくてよいでしょう。 多分NANDの出力にでもつながっていたのでしょう。

そういえば東工5類のAOでこのような問題が出たと聞いたことがあります。 最近の情報系の常識になるべきなのでしょう。

シミュレーション方針1:うおおおん俺はExcel戦士だ

最初、脳筋WindowsマンのぼくはExcelを開き、x方向に論理回路を、y方向に時間をとり、 ベーっと引っ張ってデータをぺっと貼ってシミュレートしようとしました。 ネットリストから想像した論理回路はこの時点で実装されました。 その後、Pythonのコードを読み始めたところ、素直に何かのコードに起こしたほうが楽やなって なったのでこの方法は流れてしまいました。ジャバーッ

シミュレーション方針2:Python書けねぇ

降ってきたぱいてょんのコードを元に、C言語でぱぱっと書きました。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

char c = '@', flag[334];
int x1, x2, x3, x4, x5, x6, DA, DB, FF1, FF2;

static inline int nor(int a, int b){
    return !(a | b);
}

void set_FF(void){
    FF1 = DA;
    FF2 = DB;
}

void set_gpio(void){
    int nor_out1 = nor(DA, !FF2);
    int nor_out2 = nor(nor_out1, !FF1);
    int nor_out3 = nor(DB, FF2);
    int nor_out4 = nor(!FF2, !FF1);
    int nor_out5 = nor(nor_out4, !FF1);
    int nor_out6 = nor(!FF2, nor_out4);
    int nor_out7 = nor(nor_out5, nor_out6);
    x1 = nor_out7;
    x2 = nor_out3;
    x3 = nor_out2;
    x4 = nor_out1;
    x5 = FF2;
    x6 = FF1;
}

char encoder(void){
    set_gpio();
    char v = x1;
    v = 2 * v + x2;
    v = 2 * v + x3;
    v = 2 * v + x4;
    v = 2 * v + x5;
    v = 2 * v + x6;
    return v;
}

int main(void){

    for(int i = 0; i < 10; i++){
        if(c == 'Y'){
            DA = false;
            DB = true;
        }else{
            if((i & 1) == 0)DA = false;
            else DA = true;
            if((i & 2) == 0)DB = false;
            else DB = true;
        }

        c = encoder() + 32;
        flag[i * 2] = c;

        set_FF();

        flag[i * 2 + 1] = encoder() + 32;
    }

    printf("The flag is SECCON{%s}", flag);

}

頭悪そう。

FFのナンバリングはIC内のナンバリングに対応しています。 NORは左上にあるほど番号が若くなっています。 先に来ているのが基本的に左側のダイオード入力(なはず)です。

で、実行すると

The flag is SECCON{PPP9)&"KGPP9)&"KGPP9}

よしもらったぁッ!

>>>Incorrect<<<

ンゴオオオオオオオオオオオオオオオオ

この後、頭を抱えて1時間がすぎ、無事終了を迎えましたとさ。

ちなみに間違えはset_GPIO関数の後半部分で、以下のように直すと正しい答えが得られます

x6 = nor_out7;
x5 = nor_out3;
x4 = nor_out2;
x3 = nor_out1;
x2 = FF2;
x1 = FF1;

noob...

おわりに

0 件のコメント:

コメントを投稿