ソースがなくても中身は読める
リバースエンジニアリングとは、完成したプログラムそのものから、しくみを読み取る作業です。ソースコードがなくても、実行する前に分かることがたくさんあります。
使ってよいのは、ラボ用に作ったプログラムと、自分のコピーだけです。他人のソフトの保護やライセンス、ゲームには、決して使いません。
このレッスンのゴール
メモ
プログラムを実行せずに、file、strings、objdump で調べられる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| バイナリ | 機械語の命令が入った、実行できるファイル | /tmp/rev1 |
| ELF | Linux のプログラムのファイル形式 | |
| 文字列 | プログラムの中に入っている、読める文字の並び | momiji |
| 逆アセンブル | 機械語の命令を、読めるアセンブリに戻すこと | |
| シンボル | 関数などにつけた名前 | |
| ストリップ | シンボルを消すこと。命令は残る |
学生が入力するセルは、このプレビューでは空白です。
このモジュールの約束
重要
目的は、欠陥がどう見えるかを知り、見つけて直せるようになることです。対象は、ラボ用のプログラムと、自分の練習用のプログラムだけです。他人のソフト、ライセンス、ゲーム、保護の仕組みは、決して対象にしません。
練習用のプログラムを作る
まず、合言葉を調べる短い C のプログラムを自分で作ります。ソースは作ったあとすぐ消し、バイナリだけを調べます。
合言葉は、あなた自身が決めた momiji です。ラボの5つのプログラムの鍵とは、関係がありません。
ソースを書く
printf '%s\n' '#include <stdio.h>' '#include <string.h>' 'int main(int c, char **v) {' ' if (c == 2) {' ' if (strcmp(v[1], "momiji") == 0) { puts("OK"); return 0; }' ' }' ' puts("NG");' ' return 1;' '}' > /tmp/rev1.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
プログラムを作る
gcc -O0 -no-pie -o /tmp/rev1 /tmp/rev1.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ソースを消す
rm /tmp/rev1.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
file はファイルの種類を答える
file は、ファイルの先頭を読んで、種類を答えます。プログラムは実行しません。
答えには、形式、プロセッサ、シンボルが残っているかが入ります。ELF は Linux のプログラムの形式です。
ファイルの種類を見る
file /tmp/rev1ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
strings は読める文字を取り出す
プログラムは、画面に出す言葉や比べる言葉を、そのままの文字で中に持っています。strings は、読める文字が4つ以上続く部分を、順に出します。
短い2文字の OK や NG は、初期設定では出ません。下の grep は、その長い出力から momiji だけを残します。
小さな strings を読む
# 小さな strings: 読める文字が4つ以上続くところを取り出します。
data = "\x00\x01momiji\x00NG\x00\x02hello"
found = []
now = ""
for ch in data:
if " " <= ch <= "~":
now = now + ch
else:
if len(now) >= 4:
found.append(now)
now = ""
if len(now) >= 4:
found.append(now)
print(found)
# 4 を 2 に変えて、もう一度実行しましょう。
合言葉を探す
strings /tmp/rev1 | grep momijiここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
objdump は命令を読める形にする
objdump -d は、機械語の命令をアセンブリに戻して、1行に1命令で見せます。--disassemble=main で、main だけに絞れます。
call は、別の関数を呼ぶ命令です。cmp は、2つの値を比べる命令です。次のレッスンで、読み方を学びます。
call と cmp を探す
objdump -d -M intel --no-show-raw-insn /tmp/rev1 --disassemble=main | grep -E "call|cmp"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
調べる道具と分かること
| 道具 | 実行する? | 分かること |
|---|---|---|
| file | しない | 種類、プロセッサ、シンボルの有無 |
| strings | しない | 中に入っている読める文字 |
| objdump -d | しない | 命令の並びと、呼んでいる関数 |
| プログラム自身 | する | 入力に対する答え。ただし中身は見えない |
学生が入力するセルは、このプレビューでは空白です。
よくある間違い
注意
ソースを消してコンパイルすれば、中身は隠れると思いがちです。実際は、文字列も呼ぶ関数の名前も、命令の順番も残ります。プログラムが動くために知るべきことは、読む人にも読めます。秘密を中に持たせてはいけません。
間違えた合言葉で実行
/tmp/rev1 hogeここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
見つけた合言葉で実行
/tmp/rev1 momijiここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。