
この質問をここに置くべきか、ここに置くべきかわかりません。reverseengineering.stackexchange.com
から引用ウィキペディア:
8086プロセッサでは、割り込みテーブルをInterrupt Vector Table(IVT)と呼びます。 IVTは常に0x0000から0x03ffの範囲のメモリ内の同じ場所にあり、256個の4バイトの物理モード遠距離ポインタ(256×4 = 1024バイトのメモリ)で構成されています。
qemuモニターで見つけたものは次のとおりです。
(qemu) xp/128xw 0
0000000000000000: 0xf000ff53 0xf000ff53 0xf000e2c3 0xf000ff53
0000000000000010: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000020: 0xf000fea5 0xf000e987 0xf000d62c 0xf000d62c
0000000000000030: 0xf000d62c 0xf000d62c 0xf000ef57 0xf000d62c
0000000000000040: 0xc0005526 0xf000f84d 0xf000f841 0xf000e3fe
0000000000000050: 0xf000e739 0xf000f859 0xf000e82e 0xf000efd2
0000000000000060: 0xf000d648 0xf000e6f2 0xf000fe6e 0xf000ff53
0000000000000070: 0xf000ff53 0xf000ff53 0xf0006aa4 0xc0008930
0000000000000080: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000090: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000c0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000d0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000e0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000100: 0xf000ec59 0xf000ff53 0xf000ff53 0xc0006730
0000000000000110: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000120: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000130: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000140: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000150: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000160: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000170: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000180: 0x00000000 0x00000000 0x00000000 0x00000000
0000000000000190: 0x00000000 0x00000000 0x00000000 0xf000ff53
00000000000001a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001c0: 0xf000d611 0xf000ec4e 0xf000ec4e 0xf000ec4e
00000000000001d0: 0xf000d61a 0xf000d623 0xf000d608 0xf000ec4e
00000000000001e0: 0xf000ff53 0x00000000 0xf000ff53 0xf000ff53
00000000000001f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
これらの価値をどのように理解するのか分かりません。割り込み記述子テーブルのようには見えません(値を逆参照すると、すべてのNULL値が提供されます)。それでは、私は正確に何を見ていますか?
答え1
ファームウェアは何でも残してください。
SU Q&Aで説明したように、理想的な最新システムでは、プロセッサはリアルモードにはまったく入りません。最新の64ビットIntelチップPCはどのモードでブートセクタを実行しますか?、Johan Myréenが他の答えで指摘したように、物理メモリの最初のKiBは重要ではありません。しかし、多くの最新のファームウェアでは(まだ)互換性のサポート、意味は
- 彼らは退くことができます(例えば、後ろに、MBR、VBRのレガシーPC / ATブートローダなど、リアルモード用に作成されたシステムソフトウェアを実行するために仮想モードから保護モードに直接移動することを検討してください。
- これらは以前のリアルモードファームウェアAPIを提供し、これらのAPIに上記のシステムソフトウェアが依存するすべてのデータ構造を確立します。
これらのデータ構造の1つはリアルモードIVTです。以前のリアルモードファームウェアAPIはint
命令に基づいており、リアルモードIVTは初期化の一環として、その命令へのさまざまなファームウェア処理ルーチンへのポインタでファームウェアで埋められました。
保護モードシステムソフトウェアは古いリアルモードファームウェアAPIを必要とせず、リアルモードでプロセッサを実行しないため、物理メモリの最初の1KiBのリアルモードIVTは使用されません。 (v8086 保護モードはアドレスを指定しません。物理住所は00000000以上なので、ぜひ覚えてください。解決しました論理的00000000以上のアドレスはページテーブルによって変換されます。 )最新のEFIシステムでは、ファームウェアは物理メモリのメモリマップをオペレーティングシステムのブートローダに渡し、ファームウェアが自己保護モードAPI目的で使用するために予約されている部分を通知し、オペレーティングシステムは引き続き自由に使用できます。物理メモリプールのどの部分ですか?理論的には、物理メモリの最初のページは後者のカテゴリに属することができます。
実際、ファームウェアは通常、物理メモリの最初のページを「ブートサービスコード」と表示します。これはオペレーティングシステムですできるこれを宣言し、引き続き物理メモリプールの一部として使用します。しかしその後EFIファームウェアの起動時間サービスはオペレーティングシステムによってオフになり、ファームウェアはランタイムサービスのみを提供するように縮小されます。add_efi_memmap
これの例は、Finnbarr P. Murphyによって示されたLinuxカーネルログ(オプションを含む)にあります。
[0.000000] efi: mem00: タイプ=3, attr=0xf, 範囲=[0x0000000000000000-0x0000000000001000) (0MB)xeは他のプログラムを使用してより理解しやすい形式でデコードされ、次のことを行います。
[#00] タイプ: EfiBootServicesCode プロパティ: 0xF 物理学: 00000000000000000-0000000000001000 仮想: 00000000000000000-0000000000001000
第二に、実際には、Linuxはこれらの物理メモリ範囲を明示的に無視します。〜でもファームウェアには引き続き使用できると記載されています。 EFIファームウェアと非EFIファームウェアの両方で、Linuxは物理メモリマップがある場合はそれをパッチします(という関数ではtrim_bios_range
)、次のカーネルログメッセージを生成します。
[0.000000] e820:アップデート[mem 0x00000000-0x00000fff]有効==>予約済み
これは、リアルモードIVTがファームウェアAPIの一部ではなく最新のEFIファームウェアを処理するのではなく、ファームウェアAPIの一部ですが、ファームウェアがそれを報告する以前のPC98ファームウェアを処理するためのものです(次の同じAPIを介して)。物理メモリ)オペレーティングシステムで簡単に上書きできます。
したがって、物理メモリの理論的範囲はできるカーネルメモリアロケータと要求ページング仮想メモリの一時的な要求に応じて、任意のコードまたはデータが含まれています。実際、Linuxはファームウェアが最初に設定されているため、これを変更しません。
システムのファームウェアは、システムをリアルモードのIVTエントリで満たしました。もちろん、リアルモードIVTエントリは16:16の遠距離ポインタです。 2バイトの16進ダンプを使用してメモリーを表示すると、実際にこれを非常に明確に表示できます。いくつかの例:
- ほとんどのIVTエントリは、リアルモードファームウェアROM領域のアドレスF000:FF53を指します。実行のみの仮想ルーチンにすることもできます
iret
。 - IVTはじめに1E同じROM領域にあるテーブルF000:6AA4を指します。
- IVT入口1階リアルモードビデオROMファームウェア領域のテーブルであるC000:8930を指します。
- IVT項目43リアルモードビデオROMファームウェア領域の別のテーブルであるC000:6730を指します。
追加読書
- フィンバーマーフィー(2012-08-18)。UEFIメモリV E820メモリ。 fpmurphy.com.
- 最新の64ビットIntelチップPCはどのモードでブートセクタを実行しますか?
答え2
元の8086プロセッサアーキテクチャ(80286+プロセッサでリアルモードで実装されています)は、保護モードで実行されているLinuxとは関係ありません。物理アドレス 0 には割り込みベクタテーブルはなく、代わりに割り込みディスクリプタを含む割り込みディスクリプタテーブルが使用されます。 IDTはメモリ内の任意の場所に配置できます。
Linuxカーネルは、ファームウェア(BIOSまたはEFI)から物理メモリマップをインポートします。これにより、使用可能な物理メモリページフレームと予約済みまたはなしのフレームがわかります。利用可能なページフレームの範囲は連続的ではないが、しばしば大きな穴がある。従来、x86 Linux カーネルは、物理メモリが使用可能とマークされていてもブートをスキップします。したがって、Linuxカーネルは物理アドレス0を使用しません。
答え3
ダンプメモリ
以下は、外部で実行せずにシステム内部にメモリ内容をダンプする別の方法です。
$ head /dev/mem | hexdump -C
00000000 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 |S...S...S...S...|
00000010 53 ff 00 f0 53 ff 00 f0 cc e9 00 f0 53 ff 00 f0 |S...S.......S...|
00000020 a5 fe 00 f0 87 e9 00 f0 53 ff 00 f0 46 e7 00 f0 |........S...F...|
00000030 46 e7 00 f0 46 e7 00 f0 57 ef 00 f0 53 ff 00 f0 |F...F...W...S...|
00000040 22 00 00 c0 4d f8 00 f0 41 f8 00 f0 fe e3 00 f0 |"...M...A.......|
00000050 39 e7 00 f0 59 f8 00 f0 2e e8 00 f0 d4 ef 00 f0 |9...Y...........|
00000060 a4 f0 00 f0 f2 e6 00 f0 6e fe 00 f0 53 ff 00 f0 |........n...S...|
00000070 ed ef 00 f0 53 ff 00 f0 c7 ef 00 f0 ed 57 00 c0 |....S........W..|
00000080 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 53 ff 00 f0 |S...S...S...S...|
...
...
000afea0 00 00 00 00 00 00 00 00 aa aa aa 00 aa aa aa 00 |................|
000afeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000b0000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
000c0000 55 aa 40 e9 62 0a 00 00 00 00 00 00 00 00 00 00 |[email protected]...........|
000c0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 42 |..............IB|
分析する
000c0000上記の上部はブートローダに関連している可能性があります。私はなぜこれを疑うのですか? 55aah位置のコードは、000c0000
通常、セカンダリブートローダを実行するためにBIOSをトリガするなどの操作に使用されるメモリの表示であり得る。
ただし、この55aahがc0000h-effffhの範囲に表示されることを考慮すると、この部分はPNP拡張ヘッダーである可能性が高くなります。
引用:BIOS起動仕様3.3 PnP拡張コネクタ付きデバイス
オプションROMを持つすべてのIPLデバイスには、システムメモリアドレスC0000hとEFFFFhの間(55AAhから始まる)の2k境界にある有効なオプションROMヘッダーを含める必要があります。 PnP拡張ヘッダーを持つデバイスのみが起動を制御できます。拡張ヘッダーは標準オプションROMヘッダーのオフセット+ 1Ahにあり、デバイス構成に関する重要な情報が含まれています。また、BIOSがデバイスから起動するために呼び出すデバイスオプションROM(BCVまたはBEV)のコードへのポインタも含まれています。 PnP拡張ヘッダーの構造については付録Aを参照してください。 PnP拡張ヘッダを使用してIPLデバイスを起動する方法は2つあります。 BCVまたはBEVを含める必要があります。
53以来..
最初は53ffhデータについて。私はそれが何であるか正確にはわかりません。さらなる調査によると、BIOSのMBRブートローダが起動のためにLinuxカーネルに引き渡された後、Linuxカーネルに何かが記録された可能性があります。
通常、ブートローダはカーネルをメモリにロードしてからカーネルにジャンプします。これにより、カーネルはブートローダが使用しているメモリを回復できます(すでに作業を行ったためです)。ただし、ブートセクタにオペレーティングシステムコードを含め、オペレーティングシステムが起動した後もそのまま残すことは可能です。
詳しくは、次の研究論文でこの段落を見つけました。/dev/memを介してマルウェアを挿入する:
メモリデバイス1個
/ dev / memは、物理的にアドレス指定できるメモリ用のドライバインタフェースです。 memとkmemの元の目的は、カーネルのデバッグをサポートすることでした。アドレスオフセットを選択するには、lseek()を使用して通常の文字デバイスと同じようにデバイスを使用できます。 kmem デバイスは似ていますが、仮想アドレス指定コンテキストでカーネルメモリイメージを提供します。 Xorgサーバーは、memデバイスを使用してVESAビデオメモリと物理アドレス0x00000000にあるBIOS ROM割り込みベクタテーブル(IVT)にアクセスし、VM86モードでビデオモードを操作します。 DOSEMUはまた、それを使用してBIOS IVTにアクセスし、さまざまな操作(ディスクの読み取り、コンソールへの印刷など)に対してBIOS割り込みを実行できます。