This post is also available in: English (英語)
次の記事: 「PyXie Lite」
以前のバージョンのPyXieについては、2019年12月にBlackBerry Cylanceが詳しく説明していました。ここでは主に、更新された亜種について、そして弊社が確認した重要な変更点をいくつかご紹介します。
変更点には次のようなものがあります。
- 強固になったインタープリタ
- 新たにマッピングし直されたオペコードテーブル
- データ窃盗および偵察ツールとしての再利用
- 内部サーバーによるデータの漏出
コードベースが大幅に小さくなったため、弊社ではこの亜種をPyXie Liteと呼んでいますが、名前に惑わされないでください。かなりの威力です。
ローダー
以前のバージョンのPyXieをロードするには、Goopdate.dllおよびLMIGuardianDll.dllのサイドロードアプリケーションがよく使用されていましたが、弊社が分析した最近の亜種では、Vatetが使用されています。
復号されたVatetペイロードには、シェルコードローダーによって追加されるPyXieの第1段階が含まれています。シェルコードローダーは、PyXieの第1段階をメモリにマッピングして実行します。
このシェルコードローダーは、MurmurHash3ハッシュを利用して、プロセス実行時に必要なAPIを特定します。
dll | 関数 | APIハッシュ |
Kernel32.dll | GetProcAddress | 0x261C88ED |
Kernel32.dll | VirtualAlloc | 0xC17E7EB2 |
Kernel32.dll | LoadLibraryExA | 0x4B9B30B9 |
表2: MurmurHash3 APIハッシュ
第1段階
第1段階の目的は、第2段階のペイロードを復号してメモリ内で実行することです。
ミューテックス
ミューテックスは、複数のインスタンスの同時実行を防ぐために作成されます。次のロジックが使用されます。
- GetComputerNameAを呼び出してコンピュータ名を取得する。失敗した場合、DEFAULTCOMPNAMEにフォールバックする。
- コンピュータ名のMD5ハッシュを計算する。
- 計算されたハッシュと0x2とのXOR演算を実行する。
- StringFromGUID2で演算結果を文字列に変換する。
- CreateMutexWを呼び出し、変換された文字列を使ってミューテックスを作成する。
文字列の暗号化
重要な意味を持つ文字列は暗号化されており、暗号化にはあるルーチンが使用されています。そのルーチンは、暗号化テキストの各バイト値にインデックス値を加算し、その結果を0x7F(ASCII文字セットの最大値)でマスクし、さらに長さの等しいキーとのXOR演算を実行します。
表3: 文字列の復号例
復号された文字列
uiAccess=true” -q -s {%S} -p %u werfault.exe vsjitdebugger.exe dvdplay.exe onedrivesetup.exe openwith.exe %windir%\syswow64\ %windir%\system32\ kernel32.dll KiUserExceptionDispatcher RtlCreateUser IsWow64Process \StringFileInfo\%04x%04x\ProductName |
表4: 復号された第1段階の文字列
ペイロードの復号化
次の段階のペイロードは、バイナリの.gfidsセクションにある暗号化された7zアーカイブに保存されています。このペイロードは、以前BlackBerry Cylanceの記事で取り上げられた、変更されたRC4アルゴリズムで復号されます。復号には、次のハードコードされたキーを使用します: 2C01443389BDFC7330A3386981C43E154AE8B60EC6646D916F93D18137A53544
ペイロードの実行
OpenProcessTokenおよびGetTokenInformationが呼び出され、LocalSystemアカウントでプロセスが実行されているかどうかを確認します。この確認は、次の段階のペイロードの実行方法を判断するために使用されます。
LocalSystemで実行されていると判断した場合、ペイロードは、Windowsディレクトリから選択された、新たに作成されたプロセスに挿入されます。このプロセスのコマンドラインは次のフォーマットにしたがっており、侵害指標に使えます。
1 |
-q -s {{GUID}} -p NUMBER |
LocalSystemとして実行されていることが確認できない場合は、現在のプロセスのメモリ領域内でペイロードが実行されます。
第2段階
第2段階のペイロードは、カスタムコンパイルされたPythonインタープリタです。PyXieの以前の亜種で使用されていたものとよく似ています。
設定
設定は、zlib圧縮されたjson Blobに保存されており、インタープリタの.gfidsセクションにあります。以前のバージョンのPyXieとは異なり、今回は暗号化されていません。変数sys.builtin_json_cfgは、PySys_SetObjectを呼び出して作成されます。圧縮されている設定Blobは、この変数に保存され、その後最終段階のPythonコンポーネントで使用されます。
復号された文字列
第2段階では、第1段階で述べたものと同じ文字列暗号化を使用します。
kernel32.dll openwith.exe onedrivesetup.exe dvdplay.exe vsjitdebugger.exe werfault.exe -q -s {%S} -p %u oleout32.dll VariantClear Mozilla\Firefox Mozilla\Firefox\profiles.ini SOFTWARE\Clients\StartMenuInternet\firefox.exe\shell\open\command I_CryptUIProtect cryptui.dll RtlCreateUserThread import core.modules.winapi_stubs as winapi_stubs import core.zip_logs as zip_logs import os zip_logs.send_zip_log(winapi_stubs.get_self_executable_path(), os.getpid(), ‘CERTS’, r’%s’) KiUserExceptionDispatcher uiAccess=”true” \StringFileInfo\%04x%04x\ProductName \VarFileInfo\Translation \\?\globalroot\systemroot\system32\drivers\null.sys SystemDrive IsWow64Process core.entry_point zipimporter memzipimport libs_zip_ctx start_bind_port |
表5: 復号された第2段階の文字列
最終段階: Libs.zip
最終段階のPyXieバイトコードは、インタープリタのバイナリ内に組み込まれた、暗号化されたZIPファイルに含まれています。以前のバージョンのPyXieでは、メモリからバイトコードをインポートするためにmemzipimportライブラリが使用されていました。
PyXie Lite
この亜種内の「コア」モジュールが41個のファイルで構成されているのに対し、以前のバージョンのPyXieでは、BlackBerry Cylanceの分析によると79個のファイルが確認されています。この相違は、次のセクションで取り上げる機能の変化によるものです。
インタープリタの強化
バイトコードを簡単に分析したところ、以前のバージョンのPyXieと同様にヘッダが取り除かれていることがわかりました。また、オペコードテーブルが再度変更されており、以前のバージョンのPyXieから復元されたオペコードは、このバイトコードの逆コンパイルには使用できなくなっていました。
この状況は理解しつつも、オペコードの復元に使用できるバイトコードを生成できるのではないかという望みにかけてインタープリタにDeDropのall.pyを強制的にインポートしてみたのですが、残念ながらスクリプトをインポートするだけでは、インタープリタにバイトコードを出力させることはできませんでした。
インタープリタをよく調べてみると、sys.dont_write_bytecode変数がtrueに設定されていました。この設定は、モジュールがインポートされたときにバイトコードがディスクに書き出されるのを防止する効果があります。分析作業を妨げるために、開発者が意図的にこのような操作をしたように見えます。
検索順序の脆弱性を利用してインタープリタをハイジャック
インタープリタを分析している間に、インタープリタが現在の作業ディレクトリから多数のモジュールをロードしようと試みており、検索順序のハイジャックに対して脆弱であることがわかりました。
弊社では、PyXieがインポートを試みたモジュールの1つに簡単なPythonシェルをドロップして、この脆弱性を有利に利用することができました。これにより、インタープリタに自由にアクセスできるようになったので、sys.dont_write_bytecode変数を上書きしたり、必要に応じてモジュールのオペコードを生成したり、PyXieの設定のダンプまで取得できるようになりました。
私たちが選択したモジュールのバイトコードさえ出力できれば、マッピングし直されたオペコードの復元とPyXieの逆コンパイルはごく簡単です。この亜種のオペコードのコピーは、付録に記載されています。
機能
これまでに述べたように、PyXie Liteは、データの収集と漏出の自動化に焦点を当てて再利用されたものです。
実行を開始すると、tempfile.NamedTemporaryFile()コマンドの出力に基づいた名前を持つステージングディレクトリを作成します。
%temp%\tmp1rjvhglo |
表6: ステージングディレクトリの名前の例
次に、PyXie実行時のユーザーアカウントによって決定されるルーチンの組み合わせを実行して、システムからデータを収集します。表7は、これらの各ルーチンと、どのアカウントタイプの場合にどのルーチンを実行するかを詳細に示したものです。
ルーチン | ユーザータイプ | 説明 |
_mimi_redirector | すべて | メモリ内でMimikatzを実行する。次のリスト内の新たに作成されたプロセスに挿入する: write.exe、notepad.exe、explorer.exe |
_main_routine | すべて |
|
_save_sysinfo | すべて | レジストリからアンインストールリストを収集 |
_get_passwords | すべて | Lazagneを使用してパスワードを収集 |
_find_files | システム | 設定で指定されているキーワード、ディレクトリ、拡張子に基づいてファイルおよびディレクトリを検索し、収集する |
_scan_network | システム | ネットワークスキャンを実行する |
_run_shell_cmds | システム | システムの詳細情報を収集するための一連のコマンドを実行する |
_get_desktop_files | ユーザー | find_filesに似ているが、現在のユーザーのデスクトップを検索するのみ |
_take_screenshot | ユーザー | スクリーンショットを取得する |
_get_ps_history | ユーザー | Powershellの履歴を収集する |
表7: PyXieのルーチン
設定で指定されている、以下のキーワードとディレクトリのリストから、攻撃者が関心を持っているデータのタイプについていくつかのヒントが得られます。
passw | logins | wallet | private |
confidential | username | wire | access |
treason | vault | operation | bribery |
contraband | censored | instruction | credent |
cardholder | secret | explosive | suspect |
personal | cyber | restricted | balance |
passport | victim | submarine | checking |
saving | routing | esxi | vsphere |
spy | admin | newswire | bitcoin |
ethereum | n-csr | 10-sb | 10-q |
convict | tactical | engeneering | military |
disclosure | attack | infrastruct | marketwired |
agreement | illegal | nda | hidden |
privacy | fraud | statement | finance |
marketwired | clandestine | compromate | concealed |
investigation | security |
表8: PyXie Liteの設定に指定されたキーワード(スペルの間違いはそのまま記載)
データ収集ルーチンの一部として、システムの詳細情報を収集するために多数のコマンドが実行されます。
netstat -an net user net use net view /all net view /all /domain net share net config workstation net group “Domain Admins” net group “Enterprise Admins” route print net localgroup ipconfig /all tasklist /V wmic process arp -a gpresult /z cmdkey /list net config workstation nslookup -type=any %userdnsdomain% vssadmin List Shadows wmic qfe list klist manage-bde -status nltest /domain_trusts nltest /domain_trusts /all_trusts qwinsta ipconfig /displaydns systeminfo dclist net group “domain admins” /domain net localgroup “administrators” wmic path win32_VideoController get name wmic cpu get name reg.exe save hklm\security %LOCALAPPDATA%\temp\[RANDOM] reg.exe save hklm\system %LOCALAPPDATA%\temp\[RANDOM] reg.exe save hklm\sam %LOCALAPPDATA%\temp\[RANDOM] |
表9: 実行されたコマンド
データの漏出
収集されたデータが含まれるステージングディレクトリは、圧縮されたZIPアーカイブに追加され、暗号化された後に設定のgatesセクションで指定されたサーバーに送信されます。このアーカイブの暗号化にはAES方式をCBCモードで使用し、キーとしてTHIS_KEY_IS_FOR_INTERNAL_USE_ONLYを使用します。16バイトのランダムな初期化ベクトル(IV)を使用して暗号化されたアーカイブに追加します。これまでサンプルを確認してきた中で、データの漏出に利用されたサーバーは、通常、被害を受けたネットワーク上にある、内部の侵害されたサーバーでした。このようなネットワークでは、ポート31337/tcp、900/tcp、8443/tcpでリスニングしています。今回被害を受けたネットワークから、攻撃者がどのようにデータを漏出させたのかは確認できなかったのですが、少なくとも1つのインシデントでは、データ漏出に利用されたサーバーでCobalt Strikeが実行されていました。
続きを読む: 最後の重要な記事: Defray777