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

GDBでスタックを見る「戻る場所」が積まれる現場をGDBで観測(第5回/全8回)

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

BOF(バッファオーバーフロー)を理解するうえで、最重要の土台は「スタック」です。
スタックが分かると、次が“論理”で説明できるようになります。
※スタックとは、プログラムの実行中に関数の呼び出し情報(引数、戻り先、ローカル変数など)を一時的に保存するメモリ領域のことです。
 
・関数呼び出しで、何が積まれるのか。
・どこに戻り先(return address)があるのか。
・なぜ破壊が起きると実行の流れが変わるのか。
 
今回のゴールは、GDBで「関数の呼び出し履歴」+「スタックの中身」を実際に見て、イメージと現物を一致させることになります。
※イメージです。

スタックは「積み重ね構造」=関数の作業セット

 
スタックは一言でいえば、「上に積んで上から使う箱(LIFO)」です。
関数が呼ばれるたびに、スタックに「その関数の作業セット」が積まれます。
 
関数呼び出しとスタックを超ざっくり説明すると
 main()
  └─ add() を呼ぶと
 
スタック(上が最新)
+---------------------+  ← RSP(先頭)
| add() の作業セット  |
|  - ローカル変数     |
|  - 戻り先情報       |  ← 重要
+---------------------+
| main() の作業セット |
+---------------------+
ポイントはこれだけです。
 
「戻り先情報(戻る場所)」もスタックに置かれます。
だからスタックは、BOFを理解する入り口になります。
 
 

スタックフレームと「戻り先アドレス」

 
関数の作業セットを「スタックフレーム」と呼びます。
 
スタックフレーム(概念)
 
(上)  ローカル変数など
        ------------
        保存されたRBP(目印)
        ------------
(下)  戻り先アドレス(return address) ← 超重要
 
・RSP:スタックの先頭(現場の起点)
・RBP:その関数フレームの基準点(目印)
 
今回は、「どの関数にいるか」と、「スタックに何が積まれているか」をGDBで観測します。
 
 

Kaliで手を動かす①:呼び出し履歴を読む(backtrace)

 
第3回の "gdb03.c"(add関数あり)を使います。
※詳しくは、こちらをご覧ください。
 1.DGBで、gdb03を起動します。して add() の中で止める
gdb ./gdb03
 
2.add()で止めます。
break add
run
 
3.いまどの関数にいるかlistで確認します。
list
 
4.呼び出し履歴を見る。(ここが核心です!!)
backtrace
 
【解説】処理の履歴が見られます。
#0: 現在実行中の(一番新しい)関数です。
add (x=5, y=7): add関数が呼ばれ、引数 xに5、yに7を受け取って実行されています。
at gdb01-03.c:4: ソースファイル gdb01-03.c の 4行目 で停止していることを示します。
 
#1: #0を呼び出した元の関数です。
main (): main関数から呼び出されました。
at gdb01-03.c:11: main関数の 11行目 で add関数を呼び出したことを示します。
要するに、「main関数の11行目から呼ばれたadd関数の4行目で止まっている」という状態を指しています。
 
※「backtrace」は、関数の履歴(どこから来たか)を見せてくれます。
これが「スタック=履歴」という感覚につながります。
 
 

Kaliで手を動かす②:スタックフレームと現場を覗く(info frame / x)

 
1.フレーム情報を見る(戻り先のヒントが出る)
info frame
 
ここで表示される「saved rip」や「return address」等の表現は、環境で多少違います。
大事なのは、
・「戻り先」関する情報が出てくるという事実です。
 
2.レジスタで現場の起点(RSP/RBP)を見る
info registers rsp rbp rip
 
3.スタックの中身を覗く(RSPから)
x/24gx $rsp
 
※ x/24gx $rsp の意味
x     … メモリを調べる
/24   … 24個ぶん
g     … 8バイト単位(64bitの塊)
x     … 16進表示
$rsp  … スタック先頭から
 
とりあえず「読める」必要は今はありませんが、スタックが数値として見えていることが大切です。
 
4.1行進めて、もう一度覗く(変化を見る)
next
x/24gx $rsp
 
※変化の有無でOKです。
GDBは変化を観測する道具であることを確認してください。
 
5.終了
continue
quit
 
 

GDBでスタックを見る「戻る場所」が積まれる現場をGDBで観測のまとめ

 
スタックは、関数呼び出しのたびに「作業セット(スタックフレーム)」が積み重なる領域で、プログラムの“履歴”そのものです。
重要なのは、ローカル変数だけでなく「戻り先アドレス(return address)」の情報もスタックに保存される点で、ここがBOF理解の土台になります。
GDBでは `backtrace` により、どの関数がどこから呼ばれたかを履歴として確認でき、スタックが呼び出しの連鎖を保持していることを体感できます。さらに `info frame` と `info registers rsp rbp rip` でフレームの基準点と現場(RSP)を押さえ、`x/24gx $rsp` でスタックの中身を実際に覗くと、抽象概念が“現物”になります。今は読めなくても構いません。止める→見る→少し進めて変化を見る習慣が、論理的な解析力を育てることになります。