【注意】このサイトに記載されていることを他人に試すことは「不正アクセス禁止法」に該当する場合があります。詳しくはこちらから

GDBで「論理的にExploitを組み立てる思考法」(最終回/全8回)

黒ネコと学ぶ、GDBを使ったエクスプロイト開発への第一歩

観測→仮説→検証→修正を回し、再現性を作る(Kali Linux)
 
ここまでで、「止める」「レジスタを見る」「スタックを見る」「メモリを覗く」を体験しました。
最終回は、GDBを使って「論理的に考える型」を完成させる回になります。
 
最終回のゴールは次の3つ。
・クラッシュや違和感を「情報」として扱える。
・「次に何を確認するか」を迷わず決められる。
・同じ現象を再現し、説明できる。
 
それと、まず結論:ここでやることは「実験」です。
・止める
実験を一時停止して、写真を撮れる状態にする。
・観測
その瞬間の「写真」を撮る。(RIP / 履歴 / スタック)
・少し進める
時間を少しだけ進める
・もう一度観測する
同じ角度でまた写真を撮る。
・写真の差分
何が変わったか確認する。(原因の手がかり)
 
よって、比較できることは、論理になるのです。
※イメージです。

Exploit開発(解析)は「推理」である。

Exploit開発や脆弱性解析は、感覚ゲームではなく推理です。
 
ブラックボックスからホワイトボックスへ
入力 →(中身が見えない)→ 結果
                ↑ここを見える化するのがGDB
 
論理的解析の基本ループ(これが最重要)
1.観測(事実を見る)
2.仮説(1つだけ立てる)
3.検証(GDBで確かめる)
4.修正(入力/停止点/観測点を変える)
 
そして、1に戻ります。
何度も繰り返し、「情報が増えた」かどうかだけを評価します。
 
 

観測点の優先順位(迷わないための地図)

 
初心者が迷うのは「どこを見ればいい?」です。
迷わないために、観測点を固定します。
 
観測の優先順位(上から順)とは
1.現在地:RIP(どこで止まった?)
2.現場:RSP 周辺(スタックに何がある?)
3.履歴:backtrace(どこから来た?)
4.変数:print(何が入っている?)※-g前提
 
クラッシュが起きたときの読み方としては
RIP / backtrace / RSP周辺を見て「どこで何が破綻したか」を確定します。
 
 

Kaliで手を動かす①:思考ループの「最小テンプレ」を回す

 
1.ソースを作成します。
nano gdb01-06.c
以下、ソース作成に不明な方はこちらをご覧ください。
 
2.ソース
-----
#include <stdio.h>
 
int add(int x, int y) {
    return x + y;
}
 
int main() {
    int a = 5;
    int b = 7;
    int c = add(a, b);
    printf("Result: %d\n", c);
    return 0;
}
-----
 
3.プログラム入力完了後
「Ctrl」+ o で、プログラムの書き込み
「Ctrl」+ x で、nanoエディター終了です。
 
4.コンパイルします。プログラミング
gcc -g gdb01-06.c -o gdb01-06
 
5.GDBを起動します。
gdb ./gdb01-06
  
6.まず止めて観測の起点を作ります。
break main
run
※これは「実験開始地点」を固定しています。
"break main":mainに入った瞬間で必ず止まる
"run":そこまで実行
毎回同じスタート地点から観測できるのがメリットになります。
 
7.観測(事実だけ取る:現在地・履歴・現場)
info registers rip rsp
backtrace
x/20gx $rsp
 
※ここは、今の状況を写真撮影する場面です。
それぞれ何の写真かというと、
"info registers rip rsp"
・RIP:今どこを実行中?(現在地)
・RSP:スタック現場はどこ?(机の一番上)
 
"backtrace"
どこから来たか(呼び出し履歴)
 
"x/20gx $rsp"
・スタックの中身を20個、8バイト単位で表示。
・それは、"今この瞬間”の内部状態を記録ことです。
 
8.仮説を1つ立てます。
例:「この関数呼び出しの前後で、スタックが変化するはず」
ここが重要で、仮説は「当てる」ためではなく、
「何を観測すればいいか」決めるために立てます。
 
9.検証。(少し進めて、同じ観測を繰り返す)
next
info registers rip rsp
x/20gx $rsp
 
・"next":C言語のソースの「次の行」へ進める。
・「時間を1コマだけ進める」感じ。
 
その後、また「検証」を実行します。
同じ角度で写真を2枚撮って比較するイメージになります。
 

ブレークポイント設計で推理を加速を噛み砕く

 1.関数入口で止めて比較(安全・万能)
break add
run
※以下の文章が表示された場合
The program being debugged has been started already.
Start it from the beginning? (y or n)
デバッグ対象のプログラムは既に起動しています。
最初から起動しますか?(yまたはn)
"y"を入力します。
 
※"break add":add関数に入った瞬間に止める。
→ 関数の中を観測したいときの鉄板ですね。
 
2.1回だけ止める(tbreak)
tbreak add
run
 
※"tbreak":1回止まったら自動で消えるブレーク命令。
何回も呼ばれる関数で、毎回止まると面倒。「最初の1回だけ観測したい」場合に利用します。
 
3.条件付きで止める。(見たい瞬間だけ)
break main if a==5
run
 
これは「条件が成立したときだけ止める」場合です。
たとえば、
・ループ100回のうち「99回目だけ」止めたい
・ある変数が特定の値になった瞬間だけ見たい
などに利用できます。
 
4.GDBを終了します。
continue
quit
 
 

GDBで「論理的にExploitを組み立てる思考法」のまとめ

 
GDBで論理的に解析(Exploit理解)する鍵は、コマンド暗記ではなく「観測→仮説→検証→修正」の思考ループを回すことです。
まずブレークポイントで時間を止め、RIPで現在地、backtraceで履歴、RSP周辺のメモリで現場を確認し、事実を集めます。次に仮説は1つだけ立て、"next/step"や"ni/si"で少し進めて同じ観測を繰り返し、差分から仮説を判定します。
止める場所は関数入口、怪しい処理の直前、クラッシュ直前が鉄板で、"tbreak"や条件付きブレークを使うと推理が加速します。
成功/失敗ではなく「情報が増えたか」を評価することで、クラッシュは恐怖からヒントに変わり、再現性のある理解としてブログに言語化できるようになりますよ。
 
「黒ネコと学ぶ、GDBを使ったエクスプロイト開発への第一歩(全8回)」ご覧いただいてありがとうございました。