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

GDB入門 スタックを実際に見てみよう(episode-05)

黒ネコと学ぶ・論理的エクスプロイト開発への道

エクスプロイト開発を学ぶうえで、必ず登場する言葉があります。それが「スタック(stack)」です。スタックは、プログラムが動くときに使われる重要なメモリ領域で、関数の呼び出しや戻り先、ローカル変数などが一時的に置かれます。
 
しかし初心者の方にとって、「スタック」と聞くと、難しそう、見えない、よく分からないと感じてしまうことが多いでしょう。
 
そこで今回は、GDB(GNU Debugger)を使って、実際にスタックを「目で見て確認する」ことを目標にします。
くろちゃんと白猫先生と一緒に、「スタックって何が入ってるの?」「GDBでどうやって見るの?」を、ひとつずつ丁寧に理解していきましょう。
 

くろちゃん

白猫先生……。プロセスとかメモリは少し分かってきたけど、スタックって急に難しく感じるよ……


白猫先生

大丈夫よ、くろちゃん。

スタックは“考え方”が分かれば、とても素直な仕組みなの

 
※イメージです。

スタックって何をしている場所?


白猫先生

まず大事なのは、スタックは関数のための作業台だということよ

 プログラムは、次のように動いています。
・main関数が呼ばれる
・別の関数を呼ぶ
・処理が終わったら元の場所に戻る
 
このとき、
・どこから呼ばれたか
・戻るべき場所
・関数内の変数
これらを一時的に置いておく場所が スタック です。

くろちゃん

じゃあ、スタックがないと「戻り道」が分からなくなるんだね!


白猫先生

その通り。だからエクスプロイトでは、スタックの中身を操作できるかどうかが、とても重要になるの

それでは、Kali Linuxを利用してGDBの確認をしていきましょう。
 
 

Kali Linux には GDB が最初から入っています

Kali Linux では、通常 GDB は標準インストール済みです。
確認方法
gdb --version
以下のように表示されれば インストール済みです。

GDBで「スタック」をとりあえず触って見てみよう

ここからは実際に、Kali LinuxにインストールされているGDB を使います。
難しい操作はしません。「見る」ことだけに集中します。
 
1.サンプルプログラムを用意する
まずは、シンプルなCプログラムを用意します。
a.ファイル名:gdb-sample.c で、nanoエディターを立ち上げます。
nano gdb-sample.c
 
 
b.以下のプログラムを入力します。
 #include <stdio.h>
 void hello() {
    int x = 10;
    printf("Hello\n");
}
 int main() {
    hello();
    return 0;
}
 
c.入力完了後
「Ctrl」+ o で、プログラムの書き込み
「Ctrl」+ x で、nanoエディター終了です。
 
d.ポイント
・"hello()"の中にローカル変数 "x"
・関数呼び出しが1回ある
これだけで、スタックは動いています。
  
2.デバッグ情報付きでコンパイル
gcc -g gdb-sample.txt -o gdb-sample
※"-g"は GDBで中身を見るためのおまじない です。
実行ファイルが作成されました。
 

くろちゃん

えっ、これだけでいいの? 何か壊しそうでドキドキする……


白猫先生

今日は「観察」だけ。壊すのは、もっと先のお楽しみよ。

  
3.GDBを起動する
gdb ./gdb-sample
そして実行します。
【gdbの画面】
run
 
4.ブレークポイントを置く
"hello()"の中で止めてみましょう。
break hello
run
※プログラムが hello関数の入口で停止します。
  
5.スタックを表示してみる
・コールスタック(プログラム実行中に関数が呼び出された履歴(呼び出し階層)を追跡・表示する機能)を見る
backtrace
すると、こんな表示が出ます。
#0 hello () at gdb-sample.c:4
#1 0x0000555555555168 in main () at gdb-sample.c:9
 

くろちゃん

おおっ!"main → hello"って、呼ばれた順番が見えてる!


白猫先生

それが コールスタック。今どの関数の中にいるかが分かるの

 
6.スタックフレームを切り替える
frame 0
→ "hello()"の中
 
frame 1
→ "main()"の中
 

くろちゃん

関数ごとに「場所」が分かれてる感じがするね。


白猫先生

その“場所”が、スタックフレームよ。エクスプロイトでは、この構造を崩すことで制御を奪うの。

  
7.ローカル変数を確認する
next
info locals
 x = 10

くろちゃん

うわ、本当に中身が見える……!


白猫先生

これが「見えるようになる」という第一歩。スタックは、もう怖くないでしょう?

   
8.なぜエクスプロイトでスタックが重要なのか
・リターンアドレスが置かれている。
・バッファオーバーフローの標的になる。
・ROPや制御奪取の出発点になる。
つまり、
スタックを理解する=エクスプロイトの基礎体力になのです。
 
 

GDB入門 スタックを実際に見てみようのまとめ

今回は、GDBを使ってスタックを実際に観察することを目標にしました。
スタックは、関数呼び出しを支える重要なメモリ領域であり、
「どこから来て、どこへ戻るのか」
「どんな変数を使っているのか」
といった情報が詰まっています。
 
GDBの"break"、"backtrace"、"frame"、"info locals"を使うことで、
目に見えないはずのスタック構造が、はっきりと確認できる
ことを体験できたはずです。
 
エクスプロイト開発は、いきなり攻撃する学習ではありません。
まずは、
観察 → 理解 → 操作
という順番を守ることが、最短ルートです。
 
上記より、「見て分かる」、「触って納得する」を積み重ねていけば、スタックは確実に味方になります。