【ハードウェア仮想化】カーネルの理想郷からは程遠い

【ハードウェア仮想化】カーネルの理想郷からは程遠い

導入

このストーリーでは、ハードウェア仮想化 (HVM) を使用して、独自のフック コードの一部をカーネルから遠ざけ、他のカーネル フックの影響を受けにくくし、検出を困難にする方法について説明します。この記事のアイデアは、学校の動的な Linux カーネル アップデートから生まれたもので、多くのコードは bluepill からコピーされています。

[[251619]]

第1章(アヴァロン)アヴァロンの夜明け

システムのコントロールをめぐる駆動力間の競争が激化するにつれ、カーネル内にクリーンなスペースはほとんどなくなります。インライン フック、ssdt フックなどのさまざまなフックが若いカーネルを埋め尽くします。複雑な構造を持つもの、相互接続されたもの、検出と監視機能を備えたものなどがあります。これらのコントロール ポイントの制御を取り戻したい場合は、それらのフックを研究するためにいくらかの労力を費やす必要があり、元々単純なフックがドミノ効果を引き起こすことになります。

今では、ハードウェア仮想化テクノロジーにより、考え方を変えてこれらの問題を解決できるようになりました...

1. (アバロン) アバロンの構成

(アバロン) アバロン本体は以下の部分で構成されています。

1. Avlboot.sys (初期化されたばかりでフックによって汚染されていないシステム カーネルを後で使用するために保存するために使用されます)

2. Avalon.sys (擬似カーネル情報の読み取り、ハードウェア仮想化の有効化、擬似カーネルのロードに使用)

3. XXX.sys (ユーザーが Avlboot.sys で提供される情報を使用して特定のフック操作を実行するプログラム)

2. (アバロン) アバロンの真実

この記事で紹介するAvalon(アバロン)は、仮想化をベースにしたカーネルローディングフレームワークです。ハードウェア仮想化 (HVM) とフックによって汚染されないカーネル メモリを使用して、PC 内で 2 つのカーネルを同時に実行できるようにします。そして、Avalon は、sysenter_eip と idt 内の疑似カーネルを指す対応するアドレスを制御することによって制御を獲得します。

つまり、(Avalon) Avalon はハードウェア仮想化 (HVM) を使用して独自のカーネルをロードし、元のカーネルを上書きすることで、検出されない環境でカーネルを制御できるようになります。

実装原理を下図に示します。


擬似カーネルのベース アドレスを取得したら、独自のフック プログラムで hookport を介して ssdt と shadow ssdt を処理できます (strongod はフックした ssdt をバックアップする必要があるため、少し面倒です。AGP はアドレスをオフセットするだけで使用できます)。

3. アバロンの応用

実際、Avalon は sysenter フック + idt フックを偽装したものと見なすことができます。

(Avalon) Avalon はハードウェア仮想化 (HVM) に基づいているため、カーネル全体をオーバーライドし、実行時にカーネルをリアルタイムで置き換え可能にすることができます。

擬似カーネルが配置されているメモリ範囲はメモリ監視の対象ではなく、他のプログラムが直接アクセスできないため、擬似カーネルは他の干渉問題を心配することなく自由にフックできる安全なユートピアになります。

このタイプのフックには、従来のフックに比べて次のような利点があります。

1. 従来のメモリ監視の範囲外であり、検出が困難です。

2. システム内のオリジナルフックコードに干渉せず、高い互換性を備えています。

しかし、いくつかの欠点もあります。

1. オブジェクトフック、irpフック、およびカーネルメモリに依存しないその他のフックコードに直接干渉できない

2. システム全体はハードウェア仮想化 (HVM) に依存しており、ハードウェア デバイスに対して特定の要件があります。

第2章: ビジョンは現実になる

1. 純粋な初期化

まず、Avalonの初期化を実装しましょう。初期化は、カーネル情報の取得、疑似カーネルの構築、IDT 情報の保存、元の SYSENTER_EIP の取得という 4 つの部分で構成されます。

実装コードは次のとおりです。

  1. NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject、 IN PUNICODE_STRING RegistryPath)
  2. {
  3.  
  4. ...
  5.  
  6. KrnlCopy();
  7. IDTコピー();
  8. ReadMsrSysenter();
  9.  
  10. ...
  11.  
  12. }
  13.  
  14. /*
  15.  
  16. カーネルコピー
  17.  
  18. */
  19.  
  20. VOID KrnlCopy()
  21. {
  22. PVOID バッファ;
  23. ULONGサイズ;
  24. ULONG RetSize;
  25. PSYSTEM_MODULE_INFORMATION インフォバッファ;
  26. NTSTATUS ステータス;
  27. PVOID モジュールベース;
  28. ULONG モジュールサイズ;
  29.  
  30. サイズ= 0x1000;
  31.  
  32.  
  33. する {
  34. バッファ=ExAllocatePool(NonPagedPool,サイズ);
  35. ステータス=ZwQuerySystemInformation(SystemModuleInformation、バッファ、サイズ、&RetSize);
  36. (ステータス == STATUS_INFO_LENGTH_MISMATCH)の場合
  37. {
  38. ExFreePool(バッファ);
  39. サイズ= RetSize;
  40. }
  41. }while(ステータス == STATUS_INFO_LENGTH_MISMATCH);
  42.  
  43. InfoBuffer = (PSYSTEM_MODULE_INFORMATION) バッファ;
  44.  
  45.  
  46. ModuleBase=(PVOID)(InfoBuffer->ModuleInfo[0].Base);
  47. Orig_krnl=(ULONG)ModuleBase;
  48.  
  49. DbgPrint( "AvlBoot:Orig_krnl Base=%x\n" ,ModuleBase);
  50. ModuleSize=InfoBuffer->ModuleInfo[0] .Size ;
  51. makeKernelCopy((ULONG)ModuleBase,ModuleSize);
  52. DbgPrint( "AvlBoot:Avl_krnl Base=%x\n" ,Avl_krnl);
  53. ExFreePool(バッファ);
  54. }

初期化後、他のコンポーネントは Avlboot.sys にアクセスして疑似カーネル情報とカーネルのオリジナル情報を取得できます。

2. コピーされた仮想化

ここでは、Intel VT ハードウェア仮想化の手順を簡単に紹介します。

1. vt環境を確認する

2. vt機能を有効にする

3. 仮想マシンのステータスを保存するためにvtを入力します。

4. 傍受する必要がある項目を設定する

5. 仮想マシンを終了するときの戻りアドレスを設定する

6. 仮想マシンを起動し、傍受プロジェクトがトリガーされるのを待ちます。

7. 傍受プロジェクトが起動され、関連プロジェクトの処理ルーチンに入る

8. 仮想マシンを復元して実行を継続する

ここに少しトリッキーなコードがあります:

  1. /*
  2. Vmx 初期化
  3. */
  4. NTSTATUS NTAPI VmxInitialize (
  5. PCPU CPU、
  6. PVOIDゲストEip、
  7. PVOIDゲストEsp
  8. {
  9. PHYSICAL_ADDRESS が調整された VmcsPA;
  10. ULONG VaDelta;
  11. NTSTATUS ステータス;
  12.  
  13.  
  14. // VMXON領域にメモリスペースを割り当てる
  15. Cpu->Vmx.OriginaVmxonR = MmAllocateContiguousPages(
  16. VMX_VMXONR_SIZE_IN_PAGES、
  17. &Cpu->Vmx.OriginalVmxonRPA);
  18. (!Cpu->Vmx.OriginaVmxonR) の場合
  19. {
  20. DbgPrint( "VmxInitialize(): 元の VMCS にメモリを割り当てることができませんでした\n" );
  21. STATUS_INSUFFICIENT_RESOURCES を返します
  22. }
  23.  
  24. DbgPrint( "VmxInitialize(): OriginaVmxonR VA: 0x%x\n" 、 Cpu->Vmx.OriginaVmxonR);
  25. DbgPrint( "VmxInitialize(): OriginaVmxonR PA: 0x%llx\n" 、 Cpu->Vmx.OriginalVmxonRPA.QuadPart);
  26.  
  27. // VMCS のメモリ空間を申請する
  28. Cpu->Vmx.OriginalVmcs = MmAllocateContiguousPages(
  29. VMX_VMCS_SIZE_IN_PAGES、
  30. &Cpu->Vmx.OriginalVmcsPA);
  31. (!Cpu->Vmx.OriginalVmcs) の場合
  32. {
  33. DbgPrint( "VmxInitialize(): 元の VMCS にメモリを割り当てることができませんでした\n" );
  34. STATUS_INSUFFICIENT_RESOURCES を返します
  35. }
  36.  
  37. DbgPrint( "VmxInitialize(): Vmcs VA: 0x%x\n" 、 Cpu->Vmx.OriginalVmcs);
  38. DbgPrint( "VmxInitialize(): Vmcs PA: 0x%llx\n" 、 Cpu->Vmx.OriginalVmcsPA.QuadPart);
  39.  
  40. // vmx を有効にする
  41. if (!NT_SUCCESS (VmxEnable (Cpu->Vmx.OriginaVmxonR)))
  42. {
  43. DbgPrint( "VmxInitialize(): Vmx の有効化に失敗しました\n" );
  44. STATUS_UNSUCCESSFULを返します
  45. }
  46.  
  47. *((ULONG64 *)(Cpu->Vmx.OriginalVmcs)) =
  48. (MsrRead (MSR_IA32_VMX_BASIC) & 0xffffffff); // vmcs_revision_id を設定する
  49.  
  50. // VMCS構造体に記入する
  51. ステータス = VmxSetupVMCS (Cpu、GuestEip、GuestEsp);
  52. if (!NT_SUCCESS (ステータス))
  53. {
  54. DbgPrint( "VmxSetupVMCS() がステータス 0x%08hX\n で失敗しました" , Status);
  55. VmxDisable();
  56. ステータスを返します
  57. }
  58.  
  59. DbgPrint( "VmxInitialize(): Vmxが有効\n" );
  60.  
  61. // EFER を保存
  62. Cpu->Vmx.GuestEFER = MsrRead (MSR_EFER);
  63. DbgPrint( "ゲスト MSR_EFER 読み取り 0x%llx \n" 、 Cpu->Vmx.GuestEFER);
  64.  
  65. // 制御レジスタを保存する
  66. Cpu->Vmx.GuestCR0 = RegGetCr0();
  67. Cpu->Vmx.GuestCR3 = RegGetCr3();
  68. Cpu->Vmx.GuestCR4 = RegGetCr4();
  69.  
  70. CmCli();
  71. STATUS_SUCCESS を返します
  72. }
  73.  
  74.  
  75.  
  76. /*
  77. vmxを有効にする
  78. */
  79. NTSTATUS NTAPI VmxEnable (
  80. PVOID VmxonVA
  81. {
  82. ウロンcr4;
  83. ULONG64 vmxmsr;
  84. ULONG フラグ;
  85. 物理アドレス VmxonPA;
  86.  
  87. // VM モードを有効にするために cr4 ビットを設定します
  88. set_in_cr4 (X86_CR4_VMXE);
  89. cr4 = get_cr4();
  90. DbgPrint( "VmxEnable(): VmxEnable の後の CR4: 0x%llx\n" , cr4);
  91. もし (!(cr4 & X86_CR4_VMXE))
  92. STATUS_NOT_SUPPORTED を返します
  93.  
  94. // vmx がサポートされているかどうかを確認します
  95. vmxmsr = MsrRead (MSR_IA32_FEATURE_CONTROL);
  96. (!(vmxmsr & 4) の場合)
  97. {
  98. DbgPrint( "VmxEnable(): VMX はサポートされていません: IA32_FEATURE_CONTROL は 0x%llx\n です" , vmxmsr);
  99. STATUS_NOT_SUPPORTED を返します
  100. }
  101.  
  102. //bochs のバグ、IA32_FEATURE_CONTROL のロックを 1 に変更
  103. #if ボックデバッグ
  104. MSR_IA32_FEATURE_CONTROL 関数をオーバーライドします。
  105. #終了
  106.  
  107. MSR_IA32_VMX_BASIC の呼び出し。
  108. *((ULONG64 *) VmxonVA) = (vmxmsr & 0xffffffff); // vmcs_revision_id を設定する
  109. VmxonPA = MmGetPhysicalAddress (VmxonVA);
  110.  
  111. DbgPrint( "VmxEnable(): VmxonPA: 0x%llx\n" , VmxonPA.QuadPart);
  112.  
  113. // VMXを有効にする
  114. VmxTurnOn(VmxonPA);
  115. フラグ = RegGetEflags();
  116. DbgPrint( "VmxEnable(): vmcs_revision_id: 0x%x Eflags: 0x%x \n" , vmxmsr, flags);
  117.  
  118. STATUS_SUCCESS を返します
  119. }
  120.  
  121.  
  122.  
  123. /*
  124. 仮想マシンに入る
  125. */
  126. NTSTATUS NTAPI VmxVirtualize (
  127. PCPU CPU
  128. {
  129.  
  130. ULONG、特に;
  131. (!CPU)の場合
  132. STATUS_INVALID_PARAMETER を返します
  133.  
  134. *((PULONG) (g_HostStackBaseAddress + 0x0C00)) = (ULONG) CPU;
  135.            
  136. VmxLaunch();
  137.  
  138. // 決して返らない 
  139.  
  140. STATUS_UNSUCCESSFULを返します
  141. }

3. 面倒な傍受処理

sysenterの扱い方:

ハードウェア仮想化 (HVM) は sysenter 命令を直接インターセプトできないため、制御を取得するには他の方法しか使用できません。

これを行うには、次の 3 つの方法があります。

1. 割り込みまたは特権命令を使用して VM に入るには、kifastcallentery のヘッダーに cpuid、int3 などを書き込みます。

2. デバッグレジスタを使用してkifastcallenteryでハードウェア割り込みを実行し、その割り込みを使用してVMに入ります。

3. VMM に入った後、ゲストの sysenter_eip アドレスを直接変更し、msr の読み取りと書き込みを制御することで、msr にアクセスする他のプログラムを欺きます。

メモリ検出を回避し、デバッグ レジスタを最大限に活用するために、sysenter を実行した後、プロセスの実行方向を制御するために Avalon のソリューション 3 を選択しました。

コードの一部:

  1. 静的ブール型 NTAPI VmxDispatchMsrRead (
  2. PCPU CPU、
  3. PGUEST_REGS ゲスト登録、
  4. PNBP_TRAP トラップ、
  5. ブール型 WillBeAlsoHandledByGuestHv
  6. {
  7.  
  8. ...
  9.  
  10. スイッチ (ecx) {
  11. MSR_IA32_SYSENTER_CSの場合:
  12. MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_CS);
  13. 壊す;
  14.  
  15. MSR_IA32_SYSENTER_ESPの場合:
  16. MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_ESP);
  17. 壊す;
  18. MSR_IA32_SYSENTER_EIPの場合:
  19. MsrValue.QuadPart = Avlkrnlinfo->SysenterAddr;
  20.  
  21. ...
  22.  
  23. }

IDTリダイレクト処理方法:

1. IDTアドレスのなりすまし

2. IDTシミュレーション配信

最初のものは、sidt を傍受するスキームを指し、lidt 命令は偽造された idt アドレスを入力して訪問者を誤解させます (システムによる配信は比較的安定しています)。

2 番目の方法は、IDT の処理を​​シミュレートし、IDT を配信する独自​​のプログラムを作成することです。

最初のソリューションでは、特定のストレージ アドレスを分析するために逆アセンブリ エンジンを使用する必要があり、これが大きすぎるため、このバージョンの Avalon では 2 番目のソリューション、つまり idt シミュレーション配信を使用します。

コードの一部:

  1. 静的ブール型 NTAPI VmxDispatchException (
  2. PCPU CPU、
  3. PGUEST_REGS ゲスト登録、
  4. PNBP_TRAP トラップ、
  5. ブール型 WillBeAlsoHandledByGuestHv
  6.  
  7. {
  8.  
  9. ...
  10.  
  11. //SETP 7. EIPを設定する
  12.  
  13. if((uIntrInfo & 0xff) == 1){
  14. ComPrint( "VmxDispatchException():#BD ヒット /n" );
  15. VmxWrite(GUEST_RIP、Avlkrnlinfo->Fake_IDTMap[0]);
  16. }
  17. そうでない場合 ((uIntrInfo & 0xff) == 3){
  18. ComPrint( "VmxDispatchException():#BP ヒット /n" );
  19. VmxWrite(GUEST_RIP、Avlkrnlinfo->Fake_IDTMap[1]);}
  20.  
  21. ...
  22.  
  23. }

第3章 ユートピアの黄昏

1. (アバロン) アバロン検出

ハードウェア仮想化 (HVM) に基づくプログラムの場合、最初に思い浮かぶ方法は、ハードウェア仮想化を直接検出して対抗することです。

ハードウェア仮想化の主な検出は、efer 検出と vme 検出です。

割り込みを処理する vmm の場合は、割り込みの前後の時間差を計算することで仮想マシン内かどうかを判断することもできます。

もちろん、Avalonには他の検出方法もあります(xx文字は省略)

2. 今後のアップデート

Avalon はまだ始まったばかりで、その機能はまだ完成していません。追加したい機能がまだたくさんあります:

1. カーネルをEPT(NPT)に移動して、まったく見えないようにします。

2. ring3 プログラムとの対話...

3. その他の隠れた機能

要約する

Avalon は、ハードウェア仮想化アプリケーションの氷山の一角にすぎません。私たちが探索するのを待っているアプリケーションは他にもたくさんあります。私のレベルには限界があるので、今後も専門家のアドバイスを聞きながら頑張って勉強していきたいと思います。

ビンテスト環境は次のとおりです。

ボクサー2.4.5

ウィンドウズXP SP3

注: このビンは単なる単純なサンプルです。実機で実行する場合は青色で、ring0 の割り込みのみを対象とします。 ring3 には修正されていないバグが 3 つあります。

<<:  AWS がプライベートクラウドの空に残っていた最後の暗雲を吹き飛ばす

>>:  IT の進化を考察し、業界のデジタル変革を分析する | ITE 2018のハイライト

推薦する

ブロックチェーンと分散型台帳の違い

暗号通貨とブロックチェーンの分野では、業界関係者の間でよく話題になる新しい用語があります。それは、分...

処方薬のオンライン購入禁止の撤廃案は、医薬品小売業の再編を加速させるだろう。

処方薬のオンライン販売に関するタブーは、間もなく解除される見込みだ。 5月28日、国家食品医薬品監督...

変化を繰り返す国美は、まだ電子商取引に挑戦する勇気を持っているのだろうか?

今日の中国の電子商取引は、多くのプレーヤーによる戦いであると言えます。JD.comやTaobaoなど...

マルチクラウドかシングルクラウドか?国防総省はエンタープライズクラウドの将来を定義するために100億ドルを費やす予定

[[259132]] 2019 年第 1 四半期には、世界のクラウド業界で将来を決定づける大きな出来...

A5 最適化チーム: SEO に関する FAQ (パート 3)

ウェブマスターがウェブサイトを最適化する際に、さまざまな問題に遭遇し、どこから始めればよいのかわから...

ファーウェイのクラウドネイティブ分散データベースと高性能データベース技術の公開

クラウド時代の発展とともに、データベースの物語は続きます。 Oracle の商用バージョンであれ、M...

Weiboマーケティングの優位性の分析:コミュニケーション方法の変化

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス2011 年のトップ 1...

360は他社への攻撃的な姿勢を失い、3つの変化を遂げた。

[360 に関する最近のニュースは、他のインターネット企業に対する攻撃が減り、自社の開発に対する反省...

恵州SEOブログKステーションの謎? WordPress の欠陥?

みなさんこんにちは。私は恵州 SEO の Ye Jianhui です。恵州 SEO ブログのブロガー...

#ハロウィン# hostodo ロサンゼルス 4Gメモリ VPS 年払い 21ドル/Alipay

hostodo.com は、ハロウィーン プロモーション (hostodo 割引コードを探す必要はあ...

ヒット曲「江南スタイル」に隠されたウェブサイト運営のノウハウ

「オパ カンナムスタイル」 このリズムを聞くと、つい一緒に踊りたくなる。 そう、これが神曲「カンナム...

説明:バンワゴン公式サイト、バンワゴン公式サイト、偽のウェブサイトを排除

BandwagonHost VPS は非常に人気があるため、偽のウェブサイトがたくさんあります。騙さ...

テンセントクラウドのQiu Yuepeng氏:今後のクラウドコンピューティングには3つの大きなトレンドがある

11月6日、テンセント副社長兼テンセントクラウド社長の邱月鵬氏が「テンセントテクノデベロッパー」カン...

モバイルインターネットの時代に、Taobao の顧客はどうやって収益を得るのでしょうか?

2012年、Taobao AllianceプラットフォームがウェブマスターとTaobao顧客にもたら...

ニューラインが新たなブランド戦略と新製品シリーズを発表

Hony Technology傘下の商業ブランドNewlineは本日、「Enjoy the Futu...