web-dev-qa-db-ja.com

Windows PEファイルとマルウェア

結局のところ、Windows Portable Executable形式でウイルス、マルウェア、ワーム、コードインジェクションがどのようにそしてなぜ成功するかを理解しようとしています。 PE構造のドキュメント Part 1 および Part 2 を調べていました。

それはPE実行可能ファイルで何ですか、ヘッダー、コードインジェクションを発生させるセクションですか?なぜそれらは実行可能なコードの変更と注入に対して脆弱なのですか?言い換えれば、ウイルスやマルウェアはどのようにしてそれ自体または他の悪意のあるコードをPEファイルまたはメモリプロセスに挿入するのでしょうか。

3
Kapish M

ポータブル実行可能(PE)ファイルは、EXEファイル、DLL、スクリーンセーバー、ドライバーなど、さまざまな種類のオブジェクトを記述できます。すべてのPEファイルには一連のヘッダーがあり、その後に一連のセクションがあります。

ヘッダーとテーブルは、実行可能ファイルのタイプ、それがサポートする機能、それが呼び出すAPIなどを記述します。これらのセクションは、PEローダーにファイルデータをメモリにマップする方法を伝えます。

3つのメインヘッダーと2つのメインテーブルがあります。

  • DOSヘッダー-マジックナンバー(MZ)、DOSスタブ、および実行可能ファイルに関する非常に低レベルの情報が含まれます。これは主にレガシーであり、歴史的な目的でのみ含まれています。
  • 共通オブジェクトファイル形式(COFF)ヘッダー-マシンタイプ(i386やIntel64など)と、このファイルの実行可能ファイルのタイプに関するいくつかの基本的なフラグが含まれています。
  • Portable Executable(PE)Header-プロセスのランタイムに関する情報が含まれています。エントリポイントアドレス、コードとデータサイズ、ベースアドレス、実行するWindowsサブシステム(例:GUI、コンソール、ドライバー、EFIなど)、モジュールの特性(例:NX/ASLR互換ですか?)、初期スタックとヒープのサイズなど.
  • データディレクトリテーブル-ファイルデータの16の「特別な」セグメントのポインタ(RVA)とサイズのセット。インポート/エクスポートディレクトリ、デバッグディレクトリ、.NETメタデータ、セキュリティディレクトリ、再配置テーブル、TLSディレクトリなど
  • セクションテーブル-実行可能ファイル内のさまざまなセクションを表すテーブル。セクションには、実際のプログラムを構成するデータが含まれています。説明書。

OSがPEファイルをロードすると、セクションテーブルで指定されたアドレス、サイズ、およびフラグを使用して、セクションごとに仮想メモリのブロックを作成し、ファイルからこれらのメモリセクションにデータをコピーします。コードとデータの2つの特別なセクションがあります。コードおよびデータセクションは、PEヘッダーのBaseOfCodeおよびBaseOfDataフィールドで識別され、それぞれCSおよびDSセグメントレジスタに割り当てられます。次に、eipレジスター(または64ビットではrip)が、PEヘッダーのAddressOfEntryPointフィールドで指定された値に設定され、プログラムが開始します。

PE形式は、変更に対して耐性があるように設計されていません。ファイルレベルでコードインジェクションを行うベクトルは多数あります。

  • 新しいセクションをセクションテーブルに追加し、コードとしてマークしてから、AddressOfEntryPointを変更して新しいセクションを指すようにします。これでコードを実行して、元のエントリポイント(OEP)に戻ることができます。 EPはコードセクションの外側を指しているため、AVがこれを検出するのは簡単です。
  • 元のコードセクションの最後の「スラック」スペースにコードを挿入し、エントリポイントを変更して、挿入されたコードの最後でOEPに戻ります。このスラックスペースのサイズは通常制限されているため、必ずしもこのように単純であるとは限りません。デッドコードをスラックスペースとして使用することもできます。
  • 元のコードセクションを展開し、データを下にシフトし、OEPにコードを挿入し、セクションテーブル全体を再マップし、修正を再マップして、インポートおよびエクスポートディレクトリを再構築します。これは困難であり、本質的にファイル全体の再構築を伴いますが、AVが検出することは困難です。
  • 命令(しばしば暗号化されている)を含む新しいデータディレクトリを追加し、新しい実行可能メモリブロックを割り当ててデータをそこにコピーする小さなスタブを(上記の方法のいずれかを介して)プログラムに挿入します。暗号化が使用されている場合、スタブは命令を復号化します。この新しいコードブロックは、直接ジャンプできます。
  • ファイルに挿入したコードに、初期化コールバックを含むTLSコールバックエントリを追加します(たとえば、新しいセクションを介して)。
  • 既知の関数を変更して、まったく異なることを行います。
  • 代替(パッチされた)コードを指すように呼び出しテーブルを変更します。
  • もっともっと...

ご覧のように、攻撃者がPEファイルへの書き込みアクセス権を持っている場合、攻撃者はコードを簡単に挿入できます。これに対する最良の保護は、デジタル署名であり、PEファイルのセキュリティディレクトリ内で管理されます。デジタル署名は基本的に、信頼できるプロバイダー、または信頼できる認証局のプロバイダーによって署名された証明書です。この証明書はPEファイルに埋め込まれ、データと正確に一致します。 PEファイルを変更するか、署名を変更すると、PEローダーはファイルを拒否します。もちろん、ファイルから署名を取り除くだけで、証明書なしで実行することもできます。これは、すべての実行可能ファイルに署名することを要求するフラグを設定できるローカルポリシーによって防止できます。

残念ながら、これがコードを注入する唯一の方法ではありません。別の方法は、実行時にメモリをプロセスに注入し、そのプロセス内でリモートスレッドを開始することです。これはWindowsでは比較的簡単です。

  1. PROCESS_VM_WRITEPROCESS_VM_OPERATION、およびPROCESS_CREATE_THREAD特権を使用して、ターゲットプロセスでOpenProcessを呼び出します。
  2. VirtualAllocExを呼び出して、リモートプロセスに実行可能メモリのブロックを割り当てます。
  3. WriteProcessMemoryを使用して、そのメモリにコードを書き込みます。
  4. CreateRemoteThreadを呼び出して、割り当てられたメモリのベースをスレッドエントリポイントとして使用し、プロセスで新しいスレッドを開始します。

これにより、ターゲットプロセスのコンテキストでコードが実行されます。ただし、これはステップ1が成功した場合にのみ可能であり、これは悪意のあるプロセスが他のプロセスにアクセスできることに依存しています。特権の低いユーザーは、特権の高い(管理者など)ユーザーのプロセスに対してこのようなハンドルを開くことはできません。ただし、悪意のあるプロセスが高い特権で実行されている場合、すべての賭けは無効になります。

悪意のあるアプリケーションがプロセスと実行可能ファイルへの書き込みアクセスで実行されると、これらの攻撃からユーザーを保護するためにできることはほとんどありません。

9
Polynomial