web-dev-qa-db-ja.com

古いOSのメモリ空間保護-それは本当にそれほど悪かったのですか?

Andersonは、彼の著書 『Security Engineering』で、90年代から2000年代初頭にかけて、プログラムが自分のものではないメモリにアクセスする方法に焦点を当てており、プログラマーがプログラムを管理者権限で実行することを想定してプログラムを作成しました。

最新のMicrosoftシステムであるVistaは、すべてのコードを管理者特権で実行することから離れようとしています。これら3つの最新の手法は、それぞれ独立して同じことを達成しようとしています。すべてのアプリケーションがあった場合の状態に戻るためです。管理者としてではなく、ユーザー権限で実行します。それは多かれ少なかれ、1970年代にコンピューティングが行われていた頃であり、人々は時分割のミニコンピュータやメインフレーム上で特権を持たないプロセスとしてコードを実行していました。秩序と支配の失われたエデンを奪還できるかどうか、そして今日の厄介な現実から脱出できるかどうかは、時間だけが知ることになるでしょう...しかし、その試みは確かに行う価値があります。

特にこの引用

PCには、DOSやWin95/98などの古いシングルユーザーオペレーティングシステムでプロセスがデータを変更できるという不幸な遺産があります。その結果、多くのアプリケーションは、管理者権限で実行され、マシン全体へのアクセス権が付与されない限り、実行されません

これは これらのような考え を意味しますが、ポインタに任意のアドレスを割り当て、メモリにアクセスできる場合、Windows 95/98で機能しますか?他のプログラムのメモリを読み取る(またはメモリに書き込む!)メリットがあるのに、なぜこのように設計するのでしょうか。

int * firefoxmemory = (char*) 0x11111111 //this is just an example of address.
*firefoxmemory = 200;//screw firefox
52
Celeritas

メモリの分離

この例はWindows 95では機能しませんが、DOSおよびWindows 3.11(Windows NTではない)までは機能しました。

Intel 8086プロセッサ とオペレーティングシステム( [〜#〜] dos [〜#〜] )で設計されたPCアーキテクチャとMicrosoftシリーズのオペレーティングシステム一度に1つのプログラムを実行します。あなたはプログラムを実行し、それを使い終わったらそれを終了するので、別のプロセスのデータの上書きは実際には問題になりませんでした。 ( 終了後にメモリに残ったプログラム を使用できます。これらは基本的にオペレーティングシステムの一部でした。)

Intel 80386プロセッサ は、その系統の最初の メモリ管理ユニット(MMU) を持つことで契約を変更しました。 MMUは、仮想アドレス(プログラム内のポインター)を物理アドレス(RAM内の実際の場所)に変換することによって 仮想メモリ を提供するハードウェアコンポーネントです。Windows95がその系統を最初に利用して、各Windows 95アプリケーションは独自のMMU構成で実行されたため、*firefoxmemoryは、プログラム自体のアドレス空間を指すか(この場合、プログラムに影響を与える可能性のある悪いことは何でも)、まったくどこも指しません(この場合、システム全体ではなくプログラムがクラッシュします)。

Windows 3.0–3.11は386の新奇性のいくつかを利用しましたが、すべてのアプリケーションを同じアドレス空間で実行しました。これはいくつかの要因によるものでした:

  • 古いWindows 1.x/2.xアプリケーションを実行し続けるための要件(これらは単一のアドレス空間ハードウェアで実行するように設計されており、多くの人がそれを利用してOSの内部を調べ、文書化では不可能だったことを実現しました。インターフェース);
  • 完全に異なるアーキテクチャに基づいてオペレーティングシステム全体を再設計するための開発時間の不足。
  • rAMが少ないコンピューターで実行するための要件:アプリケーションを分離しておくと、2 MBまたは4 MBのスケールではより多くのメモリが必要になります(プログラム間でデータをコピーする必要があるため、オペレーティングシステムはすべてのプログラムの対話を追跡する必要があるため)アプリケーションが通信できるようにし、通信を規制するため)。

オペレーティングシステムがプログラムが互いのメモリにアクセスできるように明示的に設計されたほどではありませんが、それを防ぐ方法はありませんでした。それを防止する方法が手頃な価格になったとき、それを利用するにはいくつかのOSバージョンが必要でした。

たとえば、プログラム間のコピーと貼り付け(クリップボード)などの機能を考えてみましょう。メモリの分離がない場合は、ソースプログラムが独自のメモリにデータのコピーを保持することでこれを実装できます。データが別のプログラムに貼り付けられると、その別のプログラムはソースプログラムから直接データをコピーします。オペレーティングシステムが追跡する必要があるのは、現在誰がクリップボードを所有しているかだけです。アプリケーションのメモリが分離されている場合、オペレーティングシステムはデータのコピーを準備し、場合によってはソースアプリケーションとは独立してデータのコピーを保存する必要があります。これには、このコードを作成するためのより多くの開発作業と、このコードをメモリに格納して実行するためのより多くのリソースが必要です。

ここでいくつかのことを簡略化しました。オペレーティングシステムがMMUを使用してアプリケーションを分離する方法)の詳細については、 カーネルが悪意のあるプログラムの動作を防止する方法は?方法2つの同一の仮想アドレスが異なる物理アドレスを指すことができますか?仮想メモリをサポートせずに複数のプロセスをサポートすることは可能ですか? (それらはUnix指向ですが、原則はWindowsまたはPCで遭遇する可能性が高いOS)。

特権の分離

この一節では、アンダーソンは実際にはメモリの分離について議論しているのではなく、実行中のプログラムがシステムの特定の部分に影響を与えないようにする特権の分離について説明しています。メモリの分離は必要ですが、十分ではありません。オペレーティングシステムは、プロセスの相互作用方法、プロセスが開くファイルの制御方法なども制御する必要があります。各アプリケーションが独自のメモリ空間で実行されている場合でも、アプリケーションは相互作用できます。メモリ分離は、アプリケーションにオペレーティングシステムサービスの使用を強制するだけです( システムコール から カーネル を介してすべてのメモリにアクセスできます)。

Windows 1.x/3.x/9x/MEシリーズのオペレーティングシステムは、シングルユーザーオペレーティングシステムとして設計されており、アプリケーションを分離しませんでした。メモリ分離はWindows 95で追加されましたが、安定性を向上させるためだけであり、セキュリティ制限を実装するためではありません。これらのオペレーティングシステムにはセキュリティ上の制限はありません。マシン上でプログラムを実行すると、すべての操作が許可されます。 (これはもちろんウイルス作成者に役立ちます。)メモリ空間は分離されますが、ファイル空間は分離されません。

Windows NT/2000/XP /…Unixファミリのオペレーティングシステムのような一連のオペレーティングシステムは、基本的なセキュリティ目標を導入するマルチユーザーオペレーティングシステムとして設計されました。ユーザーが他のユーザーに悪影響を与えてはならないことできる。したがって、オペレーティングシステムは、たとえば、Aliceが実行するプログラムがBobが実行するプログラムと対話したり、Bobのファイルを変更したりできないことを強制する必要があります。オペレーティングシステムの一部であるプログラムとデータはすべてのユーザーに関係するため、保護する必要があります。すべてのユーザー。 (もちろん、一部の対話は明示的な許可によって許可されます。たとえば、ネットワークサーバーはネットワークから受信した要求を処理します。ボブはファイルの許可を他のユーザーが書き込み可能なように変更できます。一部のユーザーには管理者特権が付与されているため、操作を変更できます。システム等)

非常に多くのアプリケーションがWindows 9xを対象として作成されており、セキュリティ上の制限はありませんでした。そのため、彼らはオペレーティングシステムディレクトリへの書き込みなどの自由を取りました(Windows 95では、ファイルをWindowsディレクトリにコピーすることが共有ライブラリをインストールする通常の方法でした)。これらのアプリケーションが行うことの多くは、当時の標準でさえ多少厄介であると考えられていましたが、人々がそうするように機能しました。 NTシリーズのWindowsのバージョン(XP以降のすべてのバージョンを含む)は、これらのアプリケーションのいくつかを必ず壊しましたが、Microsoftはいくつかの回避策を追加しました(共有ディレクトリへのファイルの書き込みは成功したが、実際にはユーザー固有のディレクトリ)。

Windows XPユーザー分離を強制しましたが、ほとんどのインストールではそれを利用していません:多くのインストールではユーザーが管理者であったため、実行したすべてのプログラムにはほとんど何でもする特権がありました。その主な理由は2つありました。

  • 動作不良のレガシーアプリケーションを実行できます。このようなアプリケーションのほとんどは、ごく一部のユーザーしか使用していませんが、多くのユーザーがそのようなアプリケーションを実行しており、それらすべてを更新するには長い時間と多大な労力が必要です。
  • 特権を導入すると、特権がないために何かができないとユーザーに通知されることがあります。 Vistaについての不満を目撃してください。Vistaは特権昇格のプロンプトを表示し続けるということです。

アプリケーションの分離

ポータブルデバイスを介してコンピューターを発見できるほど若い場合、ユーザーではなく、アプリケーションを中心とした分離のモデルに慣れているかもしれません。 UnixおよびWindowsモデルでは、アリスのデータはボブから保護されています。アプリケーションは、セキュリティモデルでは中立です。ログインしたユーザーのIDで実行されます。これは、アプリケーションコードが誤動作しないように信頼する必要があることを意味します。

Windowsは伝統的に アンチウイルスソフトウェア を介してそれらを検出して封じ込めようとすることにより、不正なアプリケーションに対処してきました。それはあまりうまくいきません。 Unixシステム、特にLinuxは、マルウェアが排除される追跡可能なチャネルを通じてより多くのソフトウェアを配布することで対処する傾向があります。

モバイルデバイス、特にiOSおよびAndroid用に設計されたオペレーティングシステムは、アプリケーション開発者を信頼しないため、アプリケーションは分離されています。たとえば、各アプリケーションには独自のファイルスペースがあります。これにはセキュリティ上の利点がありますが、アプリケーションが実行できることを減らすという大きなコストも伴います。アプリケーションには、オペレーティングシステムの動作を変更するための特権が必要です(たとえば、ショートカットを作成し、より一般的には自動化するため)。異なるアプリケーションで同じファイルを簡単に操作したり、複数のアプリケーションが同時に情報を表示することを簡単に許可したりすることはできません。または、より劇的な例を挙げれば、特権を制限してデバッガーを作成することはできません。デバッガーの目的は、デバッグ中のアプリケーションの実行をスヌーピングして実行を混乱させることです。このコストが、モバイルアプリケーション分離モデルをPC環境に移植することができない理由です。

Windowsの数年前に戻ると、マイクロコンピュータで実行されているプログラムがコンピュータを「所有」することはほぼ予想されていました。特定のサービスを引き続き使用できるようにしたい場合は、システムの特定の部分をそのままにする必要がありますが、それ以外の場合は、何かを「保護」する必要はまったくありませんでした。メインフレームコンピュータは、1人のユーザーがマシンを独占できるほど十分に大きく高価であり、複数の人が同時にマシンを使用している場合、お互いの操作を妨げない複数の独立したコンピュータのように動作できる必要がありました。しかし、問題ではなかったマイクロコンピュータ上で。すべてがハードドライブまたは不揮発性ストレージを備えている今日のコンピューターとは異なり、初期のマイクロコンピューターにはどちらもありませんでした。マシンの電源を切ってからバックアップすると、そのメモリ状態は事実上工場出荷時のデフォルトにリセットされます。 Altair 680の電源を入れると、シリアルポートからSレコード形式でプログラムを受信するのを待ちます。このようなプログラムをフィードし(おそらく紙テープリーダーを使用)、それを実行します。何か問題が発生した場合は、マシンの電源を切り、紙テープから再ロードしてください。

コンピュータがフロッピードライブを追加したとき、同じ原則が引き続き適用されました。セキュリティの問題が関係するようになったのは、パーソナルコンピュータがハードドライブを取得した後だけでしたが、フロッピーで理にかなっているプログラミング手法の多くは、機能するために引き続き使用されました。

12
supercat

簡単な例:DOSのスクリーンライティング機能には、多くの要望が残りました。ビデオメモリを直接書き込むのは日常的でした。画面を何度も更新するような場合に適切なパフォーマンスを得るには、これを行う必要があり、ビデオ画面の右下のセルに書き込む場合は絶対に不可欠でした。たとえば、表示しているものの周囲に境界線を描くことです。

以前のバージョンでは、大量のファイル(16個以上??)を開く場合は、プログラムの直前にある制御ブロックのメモリに書き込む必要がありました。同じことを達成するためにOS呼び出しを追加したバージョンを忘れています。

5
Loren Pechtel

MMU=回答を拡大すると、80年代初頭の「パーソナルコンピュータ」チップセットはすべて、その機能なしで始まりました。チップ領域のコストはゼロではなく、メモリへの遅延、当時は3 µmのチッププロセスではるかに高かったのですが、当時は約20,000のトランジスタを1つのスペースに収めることができます。

8086および68000(MacおよびAmigaで使用されている)にはMMUがありませんでした。また、最大1メガバイトのメモリしかなく、通常はフロッピーディスクドライブしかありませんでした(ディスクベースの仮想メモリもありません)。ネットワークがなく、ユーザーが1人だけの場合、メモリ保護のポイントは何でしょうか。ユーザーを自分自身から保護し、潜在的に有用なアプリ間データ共有を防ぐだけです。一般的な使用方法は、プログラムをディスクからロードし、マシン全体をそのプログラムに引き渡すことでした。 DOSにはマルチタスク機能さえありませんでした。 「終了して常駐する」モードがあり、プログラムはコードを残してキープレスまたはタイマーで実行できました。

MMUはほとんどのマイクロコントローラーにはまだ存在せず、ARMのオプション機能です。

ビデオメモリは直接アクセスの一般的なターゲットでした。ゲームを書きたい場合、それは許容できるパフォーマンスを達成する唯一の方法と考えられていました。ドライバーがないため、サウンドハードウェア(存在する場合)に直接書き込む必要もありました。

WindowsがDirectXサブシステムを取得する前に、「DOS/4GW」の奇妙な中間時代もありました。 16ビットプログラムに課せられる1Mbのメモリのハードウェア制限を克服するために、独自の小さな32ビットオペレーティングシステムでゲームを出荷できます。これには、Windows 3.0を終了する必要がありました。

この時代の16ビットゲームコードがまだ残っています。 githubに投稿するつもりです。

4
pjc50