GDBは何を見ているのか(第2回/全8回)
第1回で「GDBは止めて観測する道具」として体験しましたね。
第2回は次の2点を「感覚でつかむ」回になります。
・CPUは何を覚えて動いているのか?(レジスタ)
・メモリのどこを見ればよいのか?(スタック中心)
この記事のゴールは、RIP/RSP/RBP と「スタック=現場」を理解することです。
※イメージです。
GDBが見ている対象は「CPU+メモリ」
GDBはプログラムの「外側」(入力と出力)ではなく、「内側」(動作中の状態)を見ます。
超ざっくりと説明しますと、
[CPU] いま何を実行する? → レジスタを見る
[メモリ] データはどこ? → スタック/ヒープを見る
まず、私たちが最初に見るべきレジスタは「RIP」「RSP」「RBP」になります。
1.RIP(x86-64では、Register Instruction Pointerと呼ばれます。)
・何をしている?
CPUが「次に実行する命令の場所(住所)」を覚えているレジスタです。
※簡単に説明すると、RIPは「カーナビの現在地マーク」です。
「次はこの交差点を曲がるよ」という「次の行動」を決める場所がRIPです。
RIPが変な場所を指すと、道に迷う=クラッシュする可能性があります。
2.RSP(Stack Pointer Register)
・何をしている?
スタックという「積み重ねメモ」のいちばん上(先頭)を指しているレジスタです。
※簡単に説明すると、RSPは「プリントの山の一番上を指す指」です。
新しいプリントを置く場所も、取り出す場所も「一番上」からです。
その「一番上の位置」を指しているのがRSPです。
3.RBP(Base Pointer Register x86-64では Frame Pointer として使われることが多いです。)
・何をしている?
今の関数(作業)のスタック範囲を考えるための「基準点(目印)」です。
※簡単に説明すると、RBPは机に貼った「ここが0番」シール。
机の上にプリント(スタック)が積まれても、
「このシールから上に〇枚目が×××」みたいに位置を数えやすくするための基準がRBPです。
4.3つのレジスタを一言でまとめると
・RIPは、CPUの「次の一手」の住所。(現在地)
・RSPは、スタックの「一番上」。(現場の先頭)
・RBPは、スタックフレームの「基準点」。(目印)
となります。
難しいですね。最初は「RIP」だけでもOKです。。
「今どこを実行しようとしているか」が分かると、メモリの世界?が変わります。
メモリは4部屋。でも最初は「スタック」だけでいい
メモリ全体は、このように分かれます。
[text] 命令(プログラム本体)
[data] グローバル変数
[heap] 動的確保(後で)
[stack] 関数の作業場(最重要)
なぜ「スタック」が重要なのか。
関数を呼ぶ → stackに「作業セット情報(ローカル変数/戻り先など)」が積まれる
エクスプロイト開発の入口(BOFなど)は、この「積み上げ」が壊れるところから始まります。
だからGDB学習も、まずスタック中心でOKです。
Kaliで手を動かす①:RIP/RSP/RBPを実際に見てみる
第1回で作った “gdb01.c" を使います。
※無ければ、こちらを御覧いただき作成してください。
C言語のソースはこちら
—–
#include <stdio.h>
int main() {
int a = 5;
int b = 7;
int c = a + b;
printf(“Result: %d\n", c);
return 0;
}
—–
1.コンパイルします。(-g必須)
gcc -g gdb01.c -o gdb01
2.起動してmainで停止します。
gdb ./gdb01
break main
run
3.いまの場所(コード)を確認します。
list
4.現在のレジスタの内容を確認します。
info registers
5.今回は、3つのレジスターを確認します。
・RIPは、CPUの「次の一手」の住所。(現在地)
・RSPは、スタックの「一番上」。(現場の先頭)
・RBPは、スタックフレームの「基準点」。(目印)
※今回は、数値は「なんとなく」見てもらえればOKです。
但し、「RIP=現在地」とだけ覚えてくださいね。
Kaliで手を動かす②:RSPの先(スタック)を覗く
RSPが指す先を「見る」ことで、「メモリは番号付きノート」という感覚が手に入ります。
1.スタック先頭から20個、16進で見る。
x/20x $rsp
xコマンドの説明です。
x … メモリを調べる(examine)
/20 … 20個ぶん
x … 16進表示
$rsp … スタック先頭から
となります。
2.1行進めて変化を見る。(ここが大事!!)
next
x/20x $rsp
変更のあった箇所がわかりましたか。
「変わった/変わらない」が認識できればOKです。
GDBは「正解探し」より、変化を観測するツールですから。
3.終了します。
continue
quit
GDBは何を見ているのかのまとめ
GDBが見ているのは、プログラムの入力と出力ではなく、実行中の「内部状態」です。
内部状態の中心はCPU(レジスタ)とメモリで、初心者が最初に押さえるべきレジスタはRIP/RSP/RBPの3つです。RIPは「次に実行する命令の住所=現在地」、RSPは「スタックの先頭=作業机の一番上」、RBPは「関数の基準点=目印」を示します。
さらにRSPの先をxコマンドで覗くと、スタックが実際の数値として見え、メモリが「番号付きノート」だと体感できます。数値をすべて理解する必要はありません。止める→見る→少し進めて変化を見る、という観測習慣が論理的理解と再現性を生み、後のBOF解析の土台になりますよ。