ペネトレーションテスト&バグバウンティ
パソコンやスマホの中で動いているプログラム。その中で「メモリ」はとても大事な役割をしています。そこで、ハッカーやプログラマーがよく見る「メモリの地図(メモリマップ)」について説明します 。

※イメージです。
なぜメモリマップが重要なのか
Linuxのプログラムを解析したり、CTFで脅威の極端をついたり、ゼロデイエクスプロイトを開発するために、メモリマップの理解は必須です。
これは「プログラムがどのようにメモリを使っているか」を解明する所で、脅威の発生ポイントや、防御技術の配置を理解するカギでもあります。
メモリマップとは
プログラムが実行されると、Linuxのメモリ上に次のような領域が割り当てられます。
メモリマップ全体像(簡易図解)
各メモリ領域の役割と特徴
textセクション
ここには、「実行されるプログラムの中身(プログラムの命令にあたる機械言語 )」が入っています。たとえば、「Aを計算してBを出す」などの手順がここに書かれていて、パソコンはこの命令を読んで実行しています。
これは読み取り専用(read only)です。NXビットにより、データ領域に不正なコードが書き込まれて実行されるのを防ぎます。 (勝手に書きかえることはできません。 )
dataセクション
プログラムを動かすとき、最初から値が決まっている変数(たとえば int x = 5;)など初期化されたグローバル変数 は、このエリアに入ります。実行中に書き換えることもできます。
bssセクション
int y; のように、最初に値がない未初期化のグローバル変数 はこのエリアに置かれます。プログラムが始まると、自動的に「0」に初期化されます。
ヒープ (heap)
malloc() や new を使って、必要なときにメモリを借りる動的メモリを確保する場所です。メモリを多く使うゲームやアプリでよく使われます。
ただし、使ったらちゃんと free() や delete で返さないと、メモリがムダに残ってしまい「メモリリーク」という問題になります。
スタック (stack)
スタックは、「一時的なデータ」をしまう場所です。関数の引数やローカル変数、戻り先のアドレスなどが入ります。
お弁当箱を積み重ねるように「後から入れたものを先に取り出す(LIFO)」のルールで動いています。入れすぎると「スタックオーバーフロー」になり、プログラムが壊れることもあります。
メモリマップとエクスプロイトの関係
メモリマップを知らないと、攻撃されるポイントが分からないからです。
具体的な例として
① スタックオーバーフロー攻撃
バグでスタックに入りきらないデータを入れると、隣のデータ(リターンアドレス)を上書きできます。
それを悪用すると、好きな命令を実行させることができる!
② ヒープオーバーフロー
malloc などで確保したヒープに、大きすぎるデータを入れると、他のヒープ領域を壊せます。
これを使って、重要な構造体を書き換える → 任意の関数を実行する。
③ .text領域の実行制限(NXビット)
スタックやヒープに悪いコードを入れても、実行ができないようにブロックされます。
しかし、攻撃者は「Return-Oriented Programming(ROP)」のような回避手段を使い、.text にある既存の命令を「部品」としてつなげて、意図した動作をさせる可能性があります。、
どう守るのか
OSやコンパイラは、スタックカナリやNXビット、ASLRなどの技術でこのメモリマップを守っています。
ハッカーが見るメモリの世界:スタック・ヒープ・text・data・bssを解説のまとめ
ハッカーがメモリを操る理由は、このメモリマップをよく見て、どこに問題があるかを調べます。
たとえば、ヒープやスタックの使い方にミスがあると、そこからプログラムを乗っ取られることもあります。
この「メモリの世界」を理解することが、安全なプログラムを作る第一歩となります。