止めれば実行中の値が読める
gdb は、プログラムを途中で止めて、メモリとレジスタの中身を見せるデバッガです。実行中にしか存在しない値も、止めれば読めます。たとえば、計算で作った合言葉です。
ファイルを調べるだけの strings では、そのような値は見えません。
このレッスンのゴール
メモ
gdb でプログラムを止め、比べている文字列を読める。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| デバッガ | プログラムを止めて、中身を見せる道具 | gdb |
| ブレークポイント | 実行をそこで止める印 | break strcmp |
| 引数 | 関数に渡す値。1番目は rdi、2番目は rsi | |
| x/s | アドレスの先にある文字列を見せるコマンド | |
| ローダー | 実行の前に、必要な部品をつなぐ部分 |
学生が入力するセルは、このプレビューでは空白です。
strings で見つからない合言葉
次の練習用プログラムは、合言葉を実行中に作ります。snprintf が、名前の kaede と数の 26 をつなげて、kaede26 にします。
ファイルの中にあるのは、kaede と、つなぎ方の %s%d だけです。完成した合言葉は、メモリの中にしかありません。
ソースを書く
printf '%s\n' '#include <stdio.h>' '#include <string.h>' 'int main(int c, char **v) {' ' char key[32];' ' snprintf(key, sizeof key, "%s%d", "kaede", 26);' ' if (c == 2) {' ' if (strcmp(v[1], key) == 0) { puts("OK"); return 0; }' ' }' ' puts("NG");' ' return 1;' '}' > /tmp/rev4.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
プログラムを作る
gcc -O0 -no-pie -o /tmp/rev4 /tmp/rev4.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ソースを消す
rm /tmp/rev4.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
strings で探す
strings /tmp/rev4 | grep -E "kaede|%s"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ブレークポイントで止める
break strcmp は、strcmp を呼ぶ直前で止める印です。止まった瞬間、rdi と rsi が、比べる2つの文字列の場所を指しています。
x/s $rdi は、rdi が指す先の文字列を見せます。x/s $rsi は、2つ目です。
最初に覚える gdb のコマンド
| コマンド | 意味 |
|---|---|
| break 名前 | その関数で止める印をつける |
| run | プログラムを動かし始める |
| continue | 止まったところから続ける |
| x/s アドレス | その場所の文字列を見る |
| info registers | レジスタの値を一覧にする |
| bt | どの関数から呼ばれたかをたどる |
| quit | gdb を終わる |
学生が入力するセルは、このプレビューでは空白です。
なぜ main で一度止めるのか
ローダーも、関数の名前をつなぐために、strcmp を使います。だから、最初から break strcmp だけだと、その呼び出しで止まります。
LD_BIND_NOW=1 で名前を先にすべてつなぎ、break main で main まで進めます。それから break strcmp と continue で、自分の呼び出しで止めます。
間違えた合言葉で止める
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex run -ex 'break strcmp' -ex continue -ex 'x/s $rdi' -ex 'x/s $rsi' --args /tmp/rev4 hoge 2>&1 | grep '^0x' | cut -f2ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
読んだ合言葉で止める
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex run -ex 'break strcmp' -ex continue -ex 'x/s $rdi' -ex 'x/s $rsi' --args /tmp/rev4 kaede26 2>&1 | grep '^0x' | cut -f2ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
読んだ合言葉で実行
/tmp/rev4 kaede26ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
最初に止まった strcmp が、自分のプログラムの比較だと思いがちです。実際は、ローダーやライブラリの比較で止まることもあります。止まったら x/s で中身を見て、自分が入力した文字が出ているか確かめましょう。