コース目次 / 第1章
クラックミーを、自分でビルドする
合言葉を判定するC言語のクラックミーをビルドし、動かしてみます。総当たりでは現実的な時間で解けないことを確認し、読み解く必要性を体感します。
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章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。