コース目次 / 第1章

クラックミーを、自分でビルドする

合言葉を判定するC言語のクラックミーをビルドし、動かしてみます。総当たりでは現実的な時間で解けないことを確認し、読み解く必要性を体感します。

第1章 / 全4章目安 約8分この章のゴール: クラックミーを自分でビルドし、実行して挙動を確認できるようになる

crackme.c として保存します。合言葉を入力させ、正しければ flag{…} を表示するプログラムです。

#include <stdio.h>
#include <string.h>

int check(const char *input) {
    const unsigned char target[] = {0x1a, 0x0e, 0x02, 0x0c, 0x08, 0x0f};
    unsigned char key = 0x55;
    if (strlen(input) != sizeof(target)) return 0;
    for (size_t i = 0; i < sizeof(target); i++) {
        if ((input[i] ^ key) != target[i]) return 0;
    }
    return 1;
}

int main(void) {
    char buf[64];
    printf("合言葉を入力してください: ");
    fflush(stdout);
    if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
    buf[strcspn(buf, "\n")] = 0;
    if (check(buf)) {
        printf("正解! flag{%s_verified}\n", buf);
    } else {
        printf("違います。\n");
    }
    return 0;
}

ビルドする

-g はデバッグシンボルを付けるオプションです。クラッキング対策としては本来外すべきですが、今回は「読み方」を学ぶ教材なので、あえて付けたままにします(最適化を無効化する -O0 も、読みやすさのためです)。

gcc -O0 -g -o crackme crackme.c

動かしてみる

echo "abcdef" | ./crackme
合言葉を入力してください: 違います。

適当な入力では、当然弾かれます。target は6バイトなので、6文字の合言葉が必要そうです。

総当たりは、現実的か

6文字といっても、入力は印字可能なASCII文字であれば何でもよく、組み合わせは膨大です(印字可能文字だけでも約 956 ≈ 7,350億通り)。1回の実行に数ミリ秒かかるとしても、総当たりで解くのは現実的ではありません。入力を変えて試す代わりに、プログラム自身が「何と比較しているか」を読みに行きます。それが次の章です。

こうなっていればOK

卒業まであと2章です。

この章はまだ完了していません。