GDBでメモリを読む 覗いてはいけない場所を覗く(第7回/全8回)

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

xコマンド/16進数/little endianの壁を壊す(Kali Linux)
  
レジスタ(RIP/RSP)が分かってくると、次に必ずこう思います。
RSPが指している「先」には何があるの?
 
それが「メモリ」です。
そしてここで私たち多くの初心者が挫折します。
・16進数が怖い。
・数字の意味が分からない。
・どこを見れば良いか分からない。
 
今回のゴールは3つだけです。
・メモリを「番号付きノート」として理解する。
・"x" コマンドで、スタック周辺(安全な現場)を覗けるようになる。
・little endianを逆に見えるだけとして受け入れる。
※Little Endian(リトルエンディアン)とは、複数バイトで構成される数値データをメモリに保存したり転送したりする際、「下位(小さい桁)のバイトから順番に」配置する方式のことです。
 ※イメージです。

メモリは「住所(アドレス)付きの巨大ノート」

 メモリは、1行ずつ番号(住所)が振られた巨大なノートです。
CPUは「住所」を指定して、そこから読み書きします。
 
メモリの考え方として
アドレス(住所)  →  中身(値)
0x7ffd….      →  0x0000….
0x7ffd….      →  0x41414141….
 
GDBは、このノートを「好きな場所から覗く」道具です。
ここでは、自分のプログラムのメモリだけを安全に観測します。
 
 

まず見る場所は「RSP周辺」だけでいい

 メモリは広く大きいですが、最初に見る場所は決まっています。
それは、RSP(スタック先頭)周辺なんです。
 
理由はシンプルです。
・いま実際に使われている。
・関数呼び出しやローカル変数がある。
・変化が起きる。(学びやすい)
 
 

Kaliで手を動かす①:xコマンドでスタックを覗く

 ソースは第6回の “gdb01-06″(add/printfあり)を使います。
※無ければ、こちらを御覧いただき作成してください。
 
1.コンパイルします。
gcc -g gdb01-06.c -o gdb01-06
  
2.起動します。
gdb ./gdb06
  
3.mainで止めます。
break main
run
  
4.まずレジスタで現場を確認
info registers rsp rip
  
5.② RSPの先を覗く(16進)
x/20x $rsp
 “x/20x $rsp"の意味
・x   … examine(調べる)
・/20 … 20個ぶん
・x   … 16進表示
・$rsp… スタック先頭から
  
6.8バイト単位で覗く(64bitに馴染む)
x/20gx $rsp
 ※"g"は「8バイト単位」64bit環境ではこちらが見やすいことが多いです。
 
 

Kaliで手を動かす②:表示形式を変える+little endianの直感

 1.バイト単位で見る(並びが見える)
x/32bx $rsp
 ・"b":1バイト単位
・little endian の「逆並び」を感じやすい。
 
little endian(逆に見えるだけ)
値(頭の中)は    0x41424344
でもメモリ上は    44 43 42 41
         ↑1バイトずつ並ぶと逆に見える
 
2.同じ場所を「文字」として見る。(雰囲気でOK)
x/32cb $rsp
 ・"c":文字として表示
・読めなくてもOK。「見方が変わる」体験が目的
 
3.変化を見る(1行進めて再チェック)
next
x/20gx $rsp
 ※メモリ理解は「暗号解読」ではなく、変化やパターンを観測する作業です。
 
 

GDBでメモリを読む 覗いてはいけない場所を覗くのまとめ

 
メモリは「住所(アドレス)付きの巨大ノート」で、CPUは住所を指定して読み書きします。
GDBはそのノートを覗き、実行中の内部状態を観測できる道具です。初心者が最初に見るべき場所は広いメモリ全体ではなく、いま使われている「現場」であるRSP周辺(スタック)です。
“x/20x $rsp" で16進表示、"x/20gx $rsp" で8バイト単位表示、"x/32bx $rsp" でバイト列表示など、表示形式を切り替えると同じメモリでも見え方が変わり理解が進みます。little endian は値が逆順に並んで見えるだけで、恐れる必要はありません。
数字を全部読むのではなく、止める→覗く→少し進めて再度覗く、という観測習慣が、後のBOF解析で「入力がどこまで届いたか」を論理的に追える土台になります。