BendyBear: サイバースパイグループBlackTechとリンクされた新しい中国のシェルコード

By

Category: Malware, Unit 42

Tags: , , , , ,

BendyBear, conceptually illustrated here, is novel Chinese shellcode linked with cyber espionage group BlackTech.

This post is also available in: English (英語)

概要

非常に順応性が高く、高度に洗練された、10,000バイトを超えるマシンコード。それがパロアルトネットワークス脅威インテリジェンスリサーチチーム Unit 42のリサーチャーがこのファイルの「熊(Bear)」のコード分析中に遭遇したものです。そのコードの動作と機能は、早ければ2009年にはアクティブだったWaterBearマルウェアファミリのそれと強く相関しています。Trend MicroTeamT5による分析で、WaterBearは多面的なステージ2インプラントであり、ファイル転送、シェルアクセス、画面キャプチャそのほか多様な機能があることが明らかになりました。本マルウェアはサイバースパイグループBlackTechと関連付けられています。BlackTechは脅威リサーチコミュニティの多くが中国政府と関係していると評価しているグループで、最近行われた複数の対東アジア政府攻撃に責任があると考えられています。このWaterBearとの類似性やコードのポリモーフィック性能から、Unit 42 ではこの新しい中国のシェルコードを「BendyBear」と呼んでいます。BendyBearは、2020年に高度で持続的な脅威攻撃者(APT)が採用したシェルコードサンプルのなかでも、最も洗練され、設計が巧みで、検出困難、という点で際立った存在といえます。

BendyBearは、ステージ0インプラントのためのx64シェルコードで、その唯一の機能はコマンド&コントロール(C2)サーバーからより堅牢なインプラントをダウンロードすることであることが特定されています。なお「シェルコード」は、その名に「シェル」こそつきますが、実際にコマンド シェルを生成するかどうかに関係なく、エクスプロイト直後に標的にロードされる小さなコードのかたまりを説明するさいに使われます。10,000バイト以上もあるBendyBearは、通常のものより著しく大きく、このサイズを活かし、変更されたRC4暗号や署名ブロック検証、ポリモーフィックコードなど、高度な機能と分析防止技術を実装しています。

本稿で分析したサンプルは、2020年8月に台湾法務部調査局が公開した、悪意のあるC2ドメインとのつながりにより識別されました。なおこのサンプルは、エクスプロイト ベクトルや潜在的被害者、使用目的に関しての追加的情報のない状態で見つかったものです。

パロアルトネットワークス製品をご利用のお客様は本稿で概説されている攻撃からNGFWDNSセキュリティURL フィルタリングWildFireのセキュリティサブスクリプション、Cortex XDRにより保護されています。

ほかに類を見ないシェルコード

マクロなレベルでこのサンプルは次の点がユニークであることがわかりました。

  • 変更されたRC4暗号によるチャンクをペイロードとして送信します。これにより単一のRC4キーでペイロード全体を復号されることがなくなりネットワーク通信の暗号強度が増します。
  • 自身がデバッグにおかれている兆候がないかどうか環境を明示的にチェックしてサイバーセキュリティ分析から逃れようとします。
  • Windows 10上でデフォルトで有効の既存Windowsレジストリ キーを利用して設定データを保存します。
  • C2サーバーへの接続を試みるたびにホストのDNSキャッシュをクリアするので、ホストは毎回、悪意のあるC2ドメインの現在のIPアドレスを解決する必要があります。
  • C2サーバーへの接続ごとに一意なセッション キーを生成します。
  • よく利用されるポート番号 (443) 経由でC2サーバーに接続することで、接続プロトコルを隠し、通常のネットワーク トラフィック内に紛れ込もうとします。
  • ポリモーフィック コードを採用してコード実行中にランタイム フットプリントを変更することで、メモリ分析を阻止し、シグネチャ判定を回避します。
  • 検出回避のため、必要に応じてランタイム中にファンクション ブロック(コード ブロック)を暗号化または復号します。
  • 位置独立コード(PIC)を使用して静的分析ツールを回避します。

次のセクションではこれら各機能の詳細な技術的詳細を示します。

技術的詳細

シェルコードの実行

このシェルコード(SHA256値: 64CC899EC85F612270FCFB120A4C80D52D78E68B05CAF1014D2FE06522F1E2D0)は、C2サーバーからインプラントをダウンロードする機能を持つステージャないしダウンローダと見なされています。実行中、同コードはバイト ランダム化を使用してその動作がわかりにくいようにします。そのために、ホストの現在の時刻を疑似乱数ジェネレータの初期化シードとして出力結果に追加の演算を行い、得られた値でそれまでに実行されたコード ブロックを上書きします。このバイト操作が同コードで観測された最初の分析防止技法です。というのもメモリ セグメントをダンプしようとすれば、演算結果が不正ないし不正確になるからです。図1は、ランタイムの実行前と実行中のシェルコードのメイン エントリ ポイントのサンプルを示しています。

このスクリーンショットでは、左側に元のエントリポイント(ランタイム実行前)、右側に変更されたエントリポイント(ランタイム実行中)を示すことで、バイト操作の効果を示しています。
図1 変更されたシェルコード ランタイムのサンプル

シェルコードそれ自体には実行機能がないので、実行にはメモリ内に実行環境を割り当ててくれるWindowsローダが必要です。分析時点ではシェルコード用のローダが特定されていませんでしたので、ランタイム実行中にコードを調査するためのカスタム ローダを作成したのですが、その後、同サンプルから特定されたアトリビュートによりWaterBearのシェルコードが埋め込まれた古いインストーラがいくつか見つかりました。これらのローダの詳細は、本稿巻末「付録」セクションの「x86 WaterBearローダ」に記載しておきますのでそちらを参照してください。

さて、このシェルコードは、標的のProcess Environment Block(PEB)を見つけるところから始まり、それがいまデバッグ環境下にあるかどうかを確認します。ただしこのコードはPEBから「BeingDebugged」と「BitField」の両方の値を取得するように記述されているため、結果的にデバッガのチェックが機能しないコード ロジックになってしまっています。このため、たとえデバッガが接続されていても、このシェルコードでは常にデバッグ環境の認識に失敗します。このルーチンは、whileループ内で52回実行されます。

次に、シェルコードはPEBのローダ モジュール リストをイテレートし、Kernel32.dllのベース アドレスを探します。これはシェルコードにはよくある動作です。シェルコードの実行に必要となる依存関係ファイルを解決するには、Kernel32.dllのベース アドレスが必要だからです。このベース アドレスを使用してシェルコードは依存モジュールをロードし、標準的なシェルコードのAPI名ハッシュ化を使用して、必要なWindowsアプリケーション プログラミング インタフェース(Windows API)呼び出しを解決します。次のモジュールがロードされます。

  • Advapi32.dll
  • Kernel32.dll
  • Msvcrt.dll
  • User32.dll
  • Ws2_32.dll

初期化処理を終了すると、シェルコードは自身のmain関数に移ります。これは以下のキーで標的のレジストリにクエリを発行することから始まります。

  • HKEY_CURRENT_USER\Console\QuickEdit

Windows コマンド プロンプトは、このレジストリキーでクイック編集モードを有効にしています。クイック編集モードを使うことで、コマンド プロンプトからクリップボードにコピー&ペーストをすることができます。デフォルトでは、このキーにはREG_DWORDが1つ含まれていて、有効の場合は1、無効の場合は0の32ビット数値が設定されています。BendyBearはこの値を読み取って、値に1000を掛け、得られた結果に対して次の計算を実行します。

「結果が1,000未満か3,300,000を超える場合、シェルコードの設定(QuickEdit)を4,000(0xFA0)とし、それ以外の場合は計算結果どおりの値とする」

図2のシェルコード配置構造で水色で強調表示した値を参照してください。

このチェックはシェルコード実行のたびに実行されます。このキーを利用する意図ですが、シェルコードローダにより(0または1以外の)値を書き込んで、シェルコードがそれを設定取得に利用しているものとして説明できます。

この後、内部の配置構造(1,152バイト)が復号されます。図2にそのサンプルを示します。

ここで例示するようにBendyBearは内部の配置構造(1,152バイト)を復号します。さまざまな色のハイライトは、配置構造の分解に役立ちます。蛍光グリーンはシェルコード全体の値のXORに使用されるキー、水色はホストのクイック編集レジストリキーから計算されたバイト、オレンジはシェルコードバージョンを表す4バイト、ピンクはC2ドメインを表す17バイト、マゼンタは標的となるC2ポートを表す2バイト、明るい黄色はシェルコードで使用される解決済みの関数ポインタ、濃いシアンは関数ポインタサイズを表す112バイトでこれをファンクションブロックの暗号化または復号に使用します。濃い赤は、シェルコードで使用される解決済みのWindows API関数を表す289バイトです。
図2 シェルコードの配置構造

図2に示した配置構造の内訳は、上から下の順に以下の内容となっています。

  • 蛍光グリーンで表示したのがシェルコード全体で値のXORに使用される2つの16バイトのキーです。
    7D 38 BA FD E1 C8 D2 DF B6 EE 33 F9 14 BF 52 96
    71 17 DF E4 AE 3B A9 F2 D5 3D 75 CC D3 0D 57 72
  • 水色で表示したのがホストのクイック編集レジストリキーから計算された2バイトです。
    E8 03
  • オレンジ色で表示したのがシェルコードのバージョンを表す4バイトです。
    30 2E 32 34 (0.24)
  • ピンクで表示したのがC2ドメインを表す17バイトです。NULLを含む値のデコードのためビット単位NOT(符号なしバイト)を実行します。
    88 98 CE D1 96 91 94 9A 8C 93 96 89 9A D1 9C 90 92
  • 濃い緑色で表示したのがパターン除去に使用される103バイトです。0xFFとのXORを行ってNULL値にします。
    FF FF FF FF FF FF FF FF FF FF FF…
  • マゼンタで表示したのが標的となるC2ポートを表す2バイトです。
    BB 01
  • 明るい黄色で表示したのがシェルコードで使用される解決された関数ポインタです。
    92 13 73 33 37 02
  • 濃いシアンは関数ポインタサイズを表す112バイトで、これがファンクションブロックの暗号化または復号に使用されます。
    EE 01
  • 濃い赤で表示したのがシェルコードで使用される解決されたWindows API関数を表す289バイトです。
    A0 2E 52 CC FC 7F 00 00…

ネットワーク通信

ステージャの通信フロー: ステージャがリクエスト パケットを生成し、C2サーバーがプレセッション キーとチャレンジ レスポンスを計算し、C2サーバーが暗号化されたチャンク ペイロードを返し、ステージャはチャレンジ レスポンスを検証してペイロードを復号し、メモリ内で実行する
図3 ステージャの通信フロー

C2サーバーとの通信前にシェルコードは次のステップを実行してホストのDNSキャッシュをフラッシュします。

  1. モジュールdnsapi.dllをロードする
  2. DnsFlushResolverCache APIを呼び出す

このAPIが呼び出されると、対象C2サーバーだけでなく解決されたすべてのドメインがホストのDNSキャッシュからクリアされます。これにより、ホストがC2ドメインに関連付けられた現在のIPを解決し、ネットワーク インフラストラクチャが危殆化したり使用できなくなったりしても通信を維持できるようにしています。これはまた開発者が当該ドメインを所有しておりIPを更新できるということも意味しています。

ステージャは、C2サーバーに送信する10バイトのデータを計算することから始めます。これらの10バイトがチャレンジ リクエスト パケットとなります。ステージャはチャレンジ リクエストをC2に送信しチャレンジ レスポンスを待ちます。チャレンジ レスポンス受信後、これを適切に復号し、ステージャは特定オフセットにあるマジック バイト(シグネチャ バイト)をチェックします。このチェックに失敗するとネットワーク接続は中止されます。このチェックにより目的のC2サーバーとの通信の信頼性を確認してからペイロードのダウンロードを開始します。

I. ステージャがチャレンジ リクエスト パケットを生成

ステージャは、C2への情報を含む10バイトのチャレンジ リクエストを計算し、次に受信すべきデータ(セッション キー)のサイズを含めます。チャレンジ リクエストとセッション キーは同時にC2に送信されます。リクエストはたとえば次のようになります:

26BCFCCE738A211F3763

II. C2サーバーがチャレンジ リクエスト パケットを復号

C2は、次のステップでチャレンジ リクエスト パケットを復号します。

1. 最初のバイトを2番目のバイトとXOR、2番目のバイトを3番目のバイトとXOR…というぐあいでこれをバイト10まで続けます。その後、以下を行います:

A. バイト7を (バイト7とバイト3のXOR) の結果から更新
B. バイト2を (バイト2とバイト0のXOR) の結果から更新
C. バイト8を (バイト8とバイト0のXOR) の結果から更新
D. バイト9を (バイト9とバイト5のXOR) の結果から更新

2. 最終的な値がキー0x3FDA5F9AD85D50C77E6AとXORされます。

チャレンジ リクエストは次のようにして復号されます (16進バイト表記)。

C2はチャレンジリクエストパケットを復号し、次のコンポーネントを生成する: GetTickCount、Fixed Signature、GetTickCount、Fixed Value、GetTickCount、Data Size littleEndian。
図4 復号されたリクエスト チャレンジ

復号されたリクエスト パケットの最後の4バイトは、C2サーバーに対し、この後に期待しているネットワーク トラフィックのサイズを通知します。上に示したように、この値は0x20、つまり32バイトです。この32バイトはC2サーバーの使うセッションキーを表し、これがC2サーバーのチャレンジ レスポンスとペイロードを暗号化します。

C2サーバーが受信したセッションキーの例:

セッション キー 1–> 8C931D4F764B0661C26D77239EB454CA

セッション キー 2–> 7A4DD0AA6C3F37CDBDAFA4CBD6B27697

リクエスト パケットとセッション キーは、それぞれのビーコンごとに計算されるので常に一意になります。

III. C2がステージャを認証

C2は、セッションキーを使用してRC4のステートボックス(sbox、Sボックス)を作り、このセッションキーを暗号化と復号のXORキーとしても使用します。

*注: セッションキー2の用途はまだよくわかっていません。ステージャとの通信に使用されているようには見えません。

1. プレセッション キーは、セッション キー1 (最初の16バイト) を使用して次のように計算されます。

プレセッション キー = セッション キー 1 XOR 0X6162636465666768696A6B6C6D6E6F00

2. ステップ1で計算したプレセッション キーを使って、C2サーバーがRC4の鍵スケジューリング アルゴリズム(KSA)を構成します。この計算は次のように行われます。

a. 以下に示す関数に、以下の入力を与えてRC4のKSAを構成します。

data = 16バイトのキー 0x0C2F65194FF37B2D63D34635C7B205E4
key = ステップ1で計算した16バイトのプレセッション キー

   RC4(変更済み)KSAルーチンの例:

* KSAルーチンの入力パラメータ「data」は、蛍光グリーンで示した2つの16バイトキー(※)のXOR結果であることに注意。※ 図2のシェルコード配置構造参照。

3. 図5に示す16進値を使用し、10バイトのサーバー チャレンジ レスポンス ヘッダを作成します。

サーバー コマンド チャレンジ ヘッダは、ランダム値(赤で表示)、固定の署名(緑)、ランダム値(水色)、コマンド(青)、ランダム値(灰色)、およびヘッダ サイズのリトル エンディアン(オレンジ)で構成されます。
図5 サーバー コマンド チャレンジ ヘッダ

4. ステップ3のサーバー チャレンジ レスポンス ヘッダを暗号化します。

a. 10バイトのサーバー チャレンジをキー0x33836E6B3FAA6AC464DAとXORして以下を実行します:

i. バイト7を (バイト7とバイト3のXOR) の結果から更新
ii. バイト2を (バイト2とバイト0のXOR) の結果から更新
iii. バイト8を (バイト8とバイト0のXOR) の結果から更新
iv. バイト9を (バイト9とバイト5のXOR) の結果から更新

b. 暗号化されたサーバー チャレンジ レスポンス ヘッダ = ステップ 4(a) の結果

5. 最終的な認証キーを計算します。

a. 以下の値をXOR:

i. 0x0C2F65194FF37B2D63D34635C7B205E4
ii. ステップ1、つまりプレセッション キーから計算された値

*注: ステップ 5(a)(i)の16バイト値は、ステップ2のKSAアルゴリズムで使用されたものと同じ入力パラメータです。ステージャはC2からこのキーを期待しており、それが得られなければセッションを中止します。

ステップ4と5で生成された値でサーバー チャレンジ レスポンスは完結します。この時点で、C2はサーバー チャレンジ レスポンスをステージャに送り、認証プロセスを完了します。

IV. C2がペイロードを暗号化して送信

次にC2はステージャにコマンドを送信する準備をします。BendyBearは、ペイロードのダウンロードという1種類のコマンドのみをサポートしています。

1. 図6に示した16進値を使い、10バイトのコマンドヘッダを作成します。

更新されたサーバー コマンド チャレンジ ヘッダは、ランダム値(赤で表示)、固定署名(黄と緑)、ランダム値(水色)、コマンド(青)、ランダム値(灰色)、ヘッダ サイズのリトル エンディアン(オレンジ)で構成されます。
図6 更新されたサーバー コマンド チャレンジ ヘッダ

ヘッダへの唯一の変更は、固定のシグネチャ値が0x40から0x43になったことです。

2. ステップ1のコマンド ヘッダを暗号化します。

以下は、使用できる変更されたRC4ルーチンの例です。1つ目の引数boxはステップIII(2)で計算したSボックス、2つ目の引数dataはステップ1で得たコマンド ヘッダです。

3. ペイロード サイズを取得し、ステップ2と同じRC4アルゴリズムでその値を暗号化します。ペイロード サイズは復号したペイロード サイズの合計である必要があります。

4. ペイロードを暗号化しチャンクでステージャに送信します。

a. ペイロードから4,086バイト分読み取ります。これがステージャの受け入れる最大チャンク サイズです。

b. コマンド ヘッダを作成し (上記ステップ1)、以下のフィールドを更新します:

i. ヘッダ サイズ = ペイロード チャンク サイズ

ii. コマンド = 1

c. 更新した10バイトのコマンド ヘッダをステージャに送信します。

d. 暗号化されたペイロード チャンクを送信します。

e. ペイロードが送信され終わるまで手順aからdを繰り返します。

図7は、ステージャに送信されるペイロード チャンクの例を1つ示したものです。

BendyBearの調査から得られた暗号化されたペイロード ヘッダとデータ。カラーコード: レスポンス ヘッダ 10バイト(紫)。復号化されたペイロードサイズ(薄緑)。暗号化されたペイロードチャンク(灰色)。コマンド ヘッダ(水色)。
図7 暗号化されたペイロード ヘッダとデータ

各チャンクを受信すると、ステージャはコマンド ヘッダを取り除いてメモリ内のペイロード チャンクを復号します。

ペイロード のインメモリ ローディング

ペイロードがすべて復号されると、ステージャはいくつか基本的なチェックを実行し、ペイロードがWindows実行可能ファイルに準拠していることを確認します。ステージャはDOSとPEヘッダを検証し、ペイロードがDLLであることを検証します。次にダイレクトメモリがペイロードをロードし、そのエントリポイント (AddressOfEntryPoint) を呼び出します。ペイロードのダイレクト メモリ ロードは、Windows PE ローダであるLoadLibraryをエミュレートします。その結果、PEBのLDR_DATA_TABLE_ENTRYメタデータ構造体は作成されず、シェルコードを実行しているプロセスのPEBには、ホスト上で実行されている不正モジュールの検出に使われるDLLのロード記録が残りません。これはシェルコードをロードしたプロセス内でWinDbgの!addressコマンドを実行することで確認できます。図8にサンプルを示します。

BendyBearのシェルコードを実行しているプロセスのPEBには、ホスト上で実行されている不正モジュールの検出に使えるDLLのロード記録が残りません。ここで図示したように、これはシェルコードをロードしたプロセス内でWinDbgの!addressコマンドを実行することで確認できます。
図8 ダイレクト インメモリ ローディングが行われたDLLのアーティファクト

インメモリのアーティファクト:

  • TypeはMEM_PRIVATEになっていますが、これはロードしたプロセスに対してプライベートなメモリページであることを意味しています。Windowsプラットフォームの場合、通常はDLLがMEM_IMAGEとしてロードされます。これにより異なるプロセスとの間でDLLを共有し、メモリ スペースを節約できるようにしています。
  • ProtectionはPAGE_EXECUTE_READWRITE(RWX)になっていますが、これはその領域がMZヘッダを含むメモリ領域で書き込み可能・実行可能であることを意味しています。このMZヘッダがインメモリ ローディングしたDLLです。

図8に示すように、WinDbgの!address コマンドの出力で異常のあるエントリが見つかります。モジュールの0x7ff4c2450000 のメモリアドレスは、プライベートのメモリ割り当てと、ProtectionがRWXに設定されていることと、UsageにMZヘッダを含むことによる結果です。

x64 シェルコードの振る舞い

次の表に、BendyBearの主な動作を示します。

行動アーティファクト ATT&CK ID
レジストリのクエリ

HKEY_CURRENT_USER\Console\QuickEdit

T1012: Query Registry (レジストリのクエリ)
コマンド&コントロール T1573.002: Encrypted Channel: Asymmetric Cryptography(暗号化されたチャネル: 非対称暗号)
リモートホストからのペイロード転送 T1105: Ingress Tool Transfer(内部へのツール転送)
変更されたRC4暗号チャンク内のペイロード T1027.002: Obfuscated Files or Information: Software Packing(難読化されたファイルまたは情報: ソフトウェアのパック)
シェルコードがC2サーバー接続前にWindows APIのkernel32!GetTickCountKernel32を最大65回呼び出す。ファンクション ブロックを暗号化ないし復号するために使用される。 T1497.003: Time Based Evasion(時間ベースの回避)
ダイナミックDLLのインポートとAPIルックアップ T1106 Native API(ネイティブAPI)
Process Environment Block (PEB) を取得し、IsDebuggerフラグをチェックするシェルコードを52回イテレートする T1082: System Information Discovery(システム情報の探索)
C2サーバー接続前のmsvcrt!timeを8回呼び出す
API DNSAPI!DnsFlushResolverCache経由でホストのDNSキャッシュをクリアする
PEBの_LDR_DATA_TABLE_ENTRYメタデータ構造体は作成されず、シェルコードを実行しているプロセスのPEBには、ホスト上で実行されている不正モジュールの検出に使われるDLLのロード記録が残らない
ロードされたペイロード モジュール (DLL) のタイプがMEM_PRIVATE

表1 実行されるx64シェルコードコマンド

BendyBearとWaterBearの比較

アトリビュート WaterBear BendyBear
ファイルタイプ EXE/DLL シェルコード
インプラントの種類 ステージ2 ステージ0
RC4の変更
追加の暗号化 不明 追加でXORを計算
16バイトのXORキー
C2通信における認証
シグネチャ検証マジック バイト 1F 40

1F 43

1F 40

1F 43

ペイロードのチャンク化
ポリモーフィックコード
インメモリ ローディング
PEB デバッガ チェック
パターン除去
関数ルーチンの暗号化/復号
APIフック
プロセスの隠蔽
ネットワーク トラフィック フィルタリング

表2 BendyBearとWaterBearの比較

ファイルの種類: WaterBearはスタンドアロンPE/EXE。BendyBearはローダまたはコード インジェクションを必要とするx64シェルコード。

インプラントタイプ: WaterBearは多くの機能を備えたステージ2インプラントで、BendyBearはステージ0のダウンローダ。

変更されたRC4暗号: WaterBearもBendyBearも変更されたRC4を使用するが、実装は多少異なる。WaterBearは、鍵スケジューリング アルゴリズム部でサイズ256のRC4 Sボックスを使ってバイトシフトと加算を行う。BendyBearは鍵スケジューリング アルゴリズム部でサイズ258のRC4 Sボックスを使用してXORを実行する。

追加の暗号化: どちらも暗号化によりアーティファクトを隠蔽するが、BendyBearの方には追加のXOR暗号化ステップが含まれている。

16バイトのXORキー: どちらも同じ16バイトのXORキー0x6162636465666768696A6B6C6D6E6f00でプレセッション キーを生成する。

C2通信における認証 : WaterBearもBendyBearも10バイトの初期チャレンジ リクエストを送信し、その後で32バイトのセッション キーを送信する。

シグネチャ検証マジックバイト: WaterBearもBendyBearも同一の合致するマジックバイト検証値を使う。

ペイロードのチャンク化: WaterBearもBendyBearもペイロードが暗号化されたチャンクで送信されることを想定している。

ポリモーフィックコード: WaterBearもBendyBearもランダムバイトによるランタイム実行中のコード操作を採用している。

インメモリ ローディング: WaterBearもBendyBearもペイロードのインメモリ ローディングをサポートしている。

PEB デバッガチェック : WaterBearもBendyBearもコードがデバッグ環境下におかれているかどうかを確認する。

パターン除去: WaterBearもBendyBearも使用時に復号した文字列を再暗号化する。

関数ルーチンの暗号化/復号: WaterBearもBendyBearもランタイム関数のアドレスを難読化する。

APIフック: WaterBearの亜種はAPIフックを実装しているがBendyBearでは実装していない。

プロセス隠蔽: WaterBearの亜種は、APIフック経由でプロセスを隠蔽可能だがBendyBearはこの機能をサポートしていない。

ネットワーク トラフィック フィルタリング: WaterBearの亜種はAPIフック経由でネットワーク トラフィックをフィルタリングまたは隠蔽できるがBendyBearはこの機能をサポートしていない。

結論

BendyBearのシェルコードには、シェルコードではあまり見かけない高度な機能が含まれています。分析防止技術やシグネチャ防止検証の使用は、開発者がステルス化や検出の回避に関心があることを示しています。さらに、カスタム暗号化ルーチンやバイト操作を利用していることからは、高度な技術力がうかがわれます。

パロアルトネットワークスのお客様は、次の方法で本稿で概説した攻撃から保護されています。

  • このシェルコードで使用されているC2ドメインは、DNSセキュリティURLフィルタリングNFGWWildFireセキュリティ サブスクリプションによりマルウェアと分類されます。
  • Cortex XDRはシェルコードを実行中に識別してブロックします。
  • App-ID(NGFWのトラフィック分類システム) は、どのようなポート番号、プロトコル、暗号化 (SSH/SSL)、その他回避戦術が使われていても当該アプリケーションを識別します。このシェルコードは443/tcp経由で、正規のSSLその他の既知アプリケーションに準拠していないトラフィックで通信しようとします。ベストプラクティスとしてセキュリティ ポリシーで不明なアウトバウンドTCPトラフィックをブロックすることをお勧めします。

IoC

シェルコードのサンプル

x64 –(バージョン0.24)
64CC899EC85F612270FCFB120A4C80D52D78E68B05CAF1014D2FE06522F1E2D0 wg1.inkeslive[.]com

x86 –(バージョン0.1)
49901034216a16cfd05c613f438eccee4a7bf6079a7988b3e7094d9498379558 web2008.rutentw[.]com

x86 WaterBearローダ

次の実行可能ファイルが、古いWaterBearのx86シェルコードを含むローダ/インジェクタとして識別されています。このシェルコードのコードは、49901034216…で始まるバージョン 0.1のx86サンプルのものと同一です。

5d1414b47d88e95ae6612d3fc211c29b35cc5db4a8a992f5e27cff5203ebf44b
9880ba4f93cade2f6bbb4cc8efdcf087e8ac51b5c209ee32ad8134eb87ef70e1
682122f34027e3f8025928d446989b02952449f5e5930c2670f8f789f41573ff
2a09ec2d6edadd06e18c841e0ed794ba3eeb21818476f75ccc0e5d40e08eac80
76ef704d21fbaaceca8a131429ccfb9f5de3d8f43a160ddd281ffeafc391eb98

追加資料

台湾英文新聞 Taiwan News: Taiwan urges blocking 11 China-linked phishing domains(台湾、中国とリンクする11のフィッシングドメインのブロックを強く推奨)
iThomeニュース: 調查局首度揭露國內政府委外廠商成資安破口的現況,近期至少10個公家單位與4家資訊服務供應商遇害(複数の台湾政府機関ハッキング事件に関連した台湾法務部調査局の最近の調査)
TeamT5: Evil Hidden in Shellcode: The Evolution of malware DbgPrint.(シェルコードに隠された悪: マルウェア DbgPrintの進化)
TrendMicro : WaterBear Returns, Uses API Hooking to Evade Security.(WaterBear再び: APIフックでセキュリティ回避)
TrendMicro : The Trail of BlackTech’s Cyber Espionage Campaigns.(BlackTechのサイバースパイキャンペーンを追う)
CryCraft Technology Corp – Taiwan Government Targeted by Multiple Cyberattacks in April 2020 Part 1: Waterbear Malware(2020年4月 台湾政府が複数のサイバー攻撃の標的に。パート1: WaterBearマルウェア)
JPCERT/CC Eyes – ELF_PLEAD – Linux Malware Used by BlackTech(BlackTechの使うLinuxマルウェアELF_PLEAD)

付録

シェルコードの概念実証 (PoC)

ステージャにリクエストを提供し、メッセージ ボックスを表示するペイロード (DLL) を送信するモック用C2サーバー:

python.exe U42ETHOS_C2.py -l 8080 -p c:\temp\DLLSample.dll

[+] Started U42ETHOS_C2.py ver 1.0.0 waiting for connection on TCP port 8080

[!] Using payload file c:\temp\DLLSample.dll

[!] Received new connection from: (‘192.168.163.138’, 49918)

[-] Received Encrypted challenge Request Packet–> 40da9a64bf3992d39db6

[-] Decrypted challenge Request packet–> 46401f8c032320000000

[+] Session key 1–> 9816f78b57fff54efb5419202d81a729

[+] Session key 2–> 6ec83a6e4d8bc4e28496cac865878574

[+] Computed PreSessionKey–> f97494ef32999226923e724c40efc829

[+] Challenge command–> a3601149a495d02598b7

[-] Challenge key is–> f55bf1f67d6ae90bf1ed3479875dcdcd

[+] Payload Size is 00920100

[!] Payload sent to stager. Check if executed

図9 Unit 42によるモック用C2サーバー

BendyBearのサンプル ステージャにテスト用DLLをインメモリローディングさせたところ
図10 ステージャのインメモリ ローディング テスト用DLLの例

図9は、ステージャと対話するために私たちが作成したPythonのモック用C2サーバーです。8080/tcpでリッスンするように構成してあり、ペイロードはテスト用DLLで、このテスト用DLLがcalc.exeを起動し、メッセージボックス (Hello, Implant) を表示します。図10は、カスタム ローダを介してインメモリでシェルコードを実行しているWindows10ホストです。シェルコードがモック用C2サーバーと通信するように構成しておきました。

上記ペイロードのネットワークトラフィック(後半省略)

図11 ネットワーク トラフィック キャプチャのサンプル
図11 ネットワーク トラフィック キャプチャのサンプル