アーカイブ

第1章 2. バッファオーバーフローを理解するための基礎知識:メモリ空間

公開日:2007年9月26日

独立行政法人情報処理推進機構
セキュリティセンター

本ページの情報は2007年9月時点のものです。
記載の資料は資料公開当時のもので、現在は公開されていないものも含みます。

メモリ空間

コンパイルされた機械語プログラムは、ひと続きのメモリ空間において実行される。メモリの中は、バイトあるいはワードの単位ごとにアドレスが付けられており、プログラムはそれらのアドレスに自由にアクセスできる。

多くのオペレーティングシステムは「仮想メモリ」の仕組みを採用している。この場合プログラムの実行単位である「プロセス」ごとに異なるメモリ空間が用意される。他のプロセスとの間でメモリ空間を共有しない。ひとつのメモリ空間は、例えば次のような用途の領域に分けて使用される。

  • 命令コードが置かれる領域
  • 静的データのための領域
  • スタック
  • ヒープ 等

領域は分かれているが、ひと続きの空間であるため、これらは相互に干渉する可能性がある。プログラムが命令コード領域の一部をデータとして読み出したり、ヒープの一部を命令として実行することが(後者はプロセッサやオペレーティングシステムのデータ実行防止機能がはたらいていない限りにおいて)可能である。

  • 図1-2:プロセスごとにメモリ空間が用意されている

命令カウンタ

機械語プログラムの実行は、メモリの命令コード領域から次々と命令が読み出され動作が実施されることによって進行する。 命令の実行の流れは、通常は並べられた順序どおりに進行するが、条件分岐や関数呼び出しのように、連続しない遠くのアドレスに置かれた命令へ「ジャンプ」することもある。

命令の実行順序を左右するのが「命令カウンタ」と呼ばれるレジスタである。 命令カウンタは、「次に実行すべき命令のアドレス」を保持している。プロセッサがメモリから命令を読み出すと、命令カウンタには「次の命令」のアドレスが自動で入れられる。メモリに並べられた命令が順に処理されてゆくのは、この仕組みによる。

演算命令と命令カウンタ

演算命令が実行される過程で命令カウンタが更新されてゆく様子を一連の図に示す。

(1) ひとつ前の命令の実行直後

  • 図1-3:命令カウンタはすでにADD命令のアドレスを指している

(2) ADD命令の取り出し

  • 図1-4:命令カウンタが次の命令のアドレスを指すようになる

(3) ADD命令の実行

  • 図1-5:レジスタ間で加算演算が行われる

(4) 次の命令の取り出し

  • 図1-6:既に命令カウンタが指していたところから命令が取り出される

ジャンプ命令と命令カウンタ

プログラムが「分岐」や「関数呼び出し」のジャンプを行えるのは、「分岐命令」や「関数呼び出し命令」が、命令カウンタを別の値に書き換えるはたらきをするからである。命令カウンタの値が書き換えられると、後続の命令は書き換えられたそのアドレスから読み出されるようになり、命令実行の流れが変化する。

命令カウンタを書き換えることによってジャンプ命令が効果を表す様子を一連の図に示す。

(1) ひとつ前の命令の実行直後

  • 図1-7:命令カウンタはJMP命令のアドレスを指している

(2) JMP命令の取り出し

  • 図1-8:命令カウンタはいったん次の命令のアドレスを指すようになる

(3) JMP命令の実行

  • 図1-9:命令カウンタが書き換えられる

(4) 次の命令の取り出し

  • 図1-10:ジャンプ先のアドレスから命令が取り出される