A smart TV that shipped with malware: a Triada-family backdoor
An Android TV sold in Uzbekistan ships with a Triada-family backdoor in its firmware. It plants code in every app on the TV and can turn your home internet into a proxy for strangers' traffic. How it works, and how to check and protect your TV.

On this page
The full technical report will be sent to UZCERT and to the vendors. Malware samples, decrypted modules, decryption keys and values unique to one device (identifiers, network addresses) are not published here.
In short
- An Android TV sold in Uzbekistan under the Skyworth/Velar brand (CVTE MT5863 board, Zeasn launcher, Android 7.0) ships with a backdoor pre-installed in its firmware.
- Its structure, file names, configuration keys and class naming match the Triada malware family (Kaspersky 2016 and 2025, Dr.Web Android.Triada.231).
- At boot, hidden code runs while Android's zygote process (the parent of every app) preloads its classes. From then on, every app started on the TV, including Google Play Services and System UI, gets a hidden loader (
systemlibarm_10145.jar) written into its data folder and executed. - The loader receives further code from its operators (Java dex and native libraries), runs it in memory, and can run shell commands.
- We decrypted the encrypted modules stored in the Google Play Services folder. They include a module framework, a reverse proxy (
IPProxyCore) that turns the TV into an exit node for other people's traffic, and a WhatsApp account-data stealer. The stealer was not deployed on this TV. - We observed a live connection from the TV to a command-and-control (C2) server in Hong Kong (112.121.178.213:10080, Netsec Limited).
- The malicious code sits in the read-only part of the system. A factory reset does not remove it.
- The firmware is signed with the public AOSP test keys. Separately, the vendor's own service silently installs an ad-SDK app.
Affected device
| Field | Value |
|---|---|
| Brand / market | Skyworth / Velar, sold widely in Uzbekistan |
| Board / SoC | CVTE, MediaTek MT5863 (ro.board.platform=mt5863) |
| Model string | ro.product.model=SMART_TV |
| Launcher | Zeasn (Whale TV) |
| Build fingerprint | Android/cvt_mt5863_eu:7.0/NRD90M/builde09050933:userdebug/release-keys |
| Build | cvt_mt5863_eu-userdebug 7.0 NRD90M eng.builde.20190905.093305 release-keys, built 2019-09-05 |
| Build type | userdebug (ro.debuggable=1), Android 7.0 security level, no updates |
Whether other CVTE MT5863 builds (other brands, other regions) are affected is unknown. The build name cvt_mt5863_eu and the CVTE platform suggest the same firmware may be used by several brands.
How it was found
A test app on the TV could not write to the Android log: android.util.Log output was suppressed inside its process. The boot log then showed two things:
- zygote and system_server were trying to open hidden
.MLAndroidfolders. SELinux denied it, so the attempts were logged. - At every app start,
dex2oatwas compiling an unknownsystemlibarm_10145.jarinside the app's data folder.
The evidence was collected over ADB on the local network. The analysis was offline and static only: no sample was executed and nothing was uploaded. The SHA-256 hash of every collected file is recorded.
Technical analysis
Figure 1. The infection chain. The injector's first stage has not been found yet.
1. Injection into every process
- At boot, zygote (SELinux
u:r:zygote:s0) tries to open.MLAndroiddirectories under/dataand on shared storage. SELinux denies it, and the denials are logged. - This happens during zygote class preloading, about 100 ms after
libmedia_jni.soand the stagefright media framework initialise, before any app or system_server is forked. The code is therefore inherited by every process on the device. - system_server,
shared_relroand processes of platform, privileged and normal apps make the same.MLAndroidaccesses. - At each app start,
dex2oatcompiles/data/data/<package>/systemlibarm_10145.jar. This was observed forcom.android.systemui,com.google.android.gms,com.android.inputmethod.latin, CVTE and MediaTek system apps, factory apps, Google config apps and a freshly installed third-party app. com.android.systemuiandcom.google.android.gmsalso receivemms-core.jar.- Copies are deleted after loading. One remained in
com.android.externalstorageand was preserved.
2. The loader, systemlibarm_10145.jar
- Classes
com.android.core.info.config.LDMCoreandcom.android.ml.bt.dymc.*. The dex timestamp is 2018-11-14 and the log tag isEXPML. LDMCore.loadDexMem(String, String, byte[]),loadDexFinish(String, ClassLoader)andloadSoFinish(String)are native methods with no implementation in the jar. They are supplied by native code already present in the process, which is the firmware-level injector.DymcService.onCreate(int)starts a worker thread.ContexHunterobtains an AndroidContextby reflection onActivityThread/RuntimeInit, for both system_server and app processes.DymcReceiver/DymcHandlerregister broadcast actionscom.dymc.<md5(package)>.lddexand.ldso. A broadcast carries a byte buffer (buf), a class name (clazz) and a module path (jmd). The handler loads that code into the process in memory, or loads a native library, and reports back with a response broadcast. Any app can therefore be made to run operator-supplied code.makeShCmdruns commands throughshand returns their output.
3. Encrypted modules and configuration
Location: /data/data/com.google.android.gms/files/.data/ and /data/data/com.android.browser/files/.data/ (Google Play Services and the system browser).
| File | Content |
|---|---|
ylmd_1003.md (164,917 B) |
Encrypted module, decrypted |
ss_1027.md (785 B) |
Encrypted module, decrypted |
.ylc/.rtresext/.oc_1_2004_1_Y29tLmFuZHJvaWQub2FkLmlwcHJveHkuSVBQcm94eUNvcmU= (26,084 B; the file name ends in a newline) |
Encrypted reverse-proxy module, decrypted. The name decodes from Base64 to com.android.oad.ipproxy.IPProxyCore |
btdoinfo.db |
Java-serialized com.android.ml.bt.core.OPBDomainInfo = C2 domain list |
phone.db |
ophead_regtime, cd, sericode, ppglcd, interval |
.ss_log |
Heartbeat-like log lines every 30 s |
The hidden device-ID store is in /data/system/.MLAndroid/, /data/misc/.MLAndroid/ (both mode 0777) and /sdcard/.MLAndroid/: com.android.btcore.db, timeStampMask.db.
Decryption. The .md and .oc modules are XOR-encrypted ZIP archives, consistent with the "double XOR" scheme Kaspersky described for Triada. The decrypted outputs are valid ZIPs that pass their CRC-32 checks (hashes in the IOC section below). Inside the modules, every string literal is itself XOR-encrypted with an inline key. All were recovered. The keys and decryption details are not published.
4. What the decrypted modules do
ylmd_1003, the task and module framework. It runs inside Google Play Services and the system browser.
- It reads the per-device IDs (
sericode,cd) from the hidden.MLAndroid/phone.dbstores. - It polls
https://hcnk.uedfd.com/OadCtrl/ifabout once every 20 hours (the server-set heartbeat is 1,200 minutes). - It downloads further "OAD" modules that the server names, checks them against a server-supplied MD5, runs the tasks the server assigns, and reports results to
/OadCtrl/bt. - Each poll sends a device profile: advertising ID, Android ID, MAC, serial number, model, language and country.
- Every HTTPS client in these modules accepts any server certificate.
Figure 2. The IPProxyCore reverse proxy: the operator's traffic passes through the TV and appears to come from the home IP address.
IPProxyCore, the reverse proxy (OAD module 2004, delivered via the framework).
- It runs in the Google Play Services process.
- It asks a gateway at
dv1wi3buwqfbb.cloudfront.net/ProxyGateway/...for a relay address, then holds a persistent connection to that relay. - Over that connection the operator opens TCP connections and UDP exchanges to arbitrary destinations. The TV carries the traffic, and it appears to come from the owner's IP address.
- The server can also pause the module, set its reconnect interval and collect its log.
- Its log on the TV records an earlier version connected to relay
148.66.17.4:11080in November 2024. - This is the residential-proxy behaviour described for Triada (Kaspersky 2025) and BADBOX 2.0.
Embedded WhatsApp account-data stealer (com.dl.tk.TKEntry, inside ylmd_1003). It is designed to run inside WhatsApp and send WhatsApp account keys and identifiers to bk79n.uedfd.com. The framework only deploys it for other host types. On this TV it was not deployed, and WhatsApp is not installed. Its presence shows what the platform is built to do on other devices.
ss_1027 is an empty plug-in stub.
5. Comparison with Triada
- Same design as Kaspersky 2025: a reverse proxy in Google Play Services, a WhatsApp-key theft module, double-XOR encryption,
ppgl/sericode/cdnaming. - Different: the command numbering, the module hashes and all C2 infrastructure. This build's C2 infrastructure (
*.1g5k5w.com,*.o96p.com,*.aaodp.com) and several file artefacts (.MLAndroid,ylmd_1003,ss_1027,IPProxyCore) are not found in public reports. This is a related but unpublished build.
6. Where the injector is
What was ruled out in the system partition. Static, offline analysis of the system files ruled out the following as the injector:
android.util.Log.println_nativeinlibandroid_runtime.so. It is identical in logic to AOSP 7.0. This is the hook point Kaspersky reported in 2025; this build does not use it.- The framework's Java code (dex embedded in
boot-framework.oatand all other boot images, including the CVTE and MediaTek boot jars). No foreign packages, no in-memory dex loading, no hidden strings. app_process32,libnativehelper.so,liblog.soandlibandroid.so, judged by imports and the calls that matter.- The 14 MediaTek media-extractor plugins that zygote loads from
/etc/VendorExtractor.cfg, and their dependencies. They have no load-time constructors and no file, process or network imports. - Every direct
RegisterNatives/jniRegisterNativeMethodscaller among the 117 libraries mapped into zygote. All are standard AOSP registration code.
The encrypted loader and its key strings (the JNI signature of loadDexMem, dalvik/system/DexClassLoader, the LDMCore / DymcService class names, .MLAndroid, systemlibarm_) were searched for in every system file in three ways: in plaintext, under every repeating XOR or additive key up to 29 bytes, and as strings built on the stack in code. No hits. The injector therefore protects its strings with a non-trivial cipher or compression.
What was found later. A second read-only collection (with temporary adb root) found two native libraries in /data/dalvik-cache, disguised as ART boot-image files:
| File on the TV | Notes |
|---|---|
/data/dalvik-cache/arm/system@framework@boot-acco.oat |
ARM ELF32 shared object, stripped, 218,540 bytes |
/data/dalvik-cache/arm/system@framework@boot-bridacco.oat |
ARM ELF32 shared object, stripped |
- Neither file is on
BOOTCLASSPATH, and neither has a matching jar in/system/framework. They are not real OAT boot images. - Their file dates match the unit's first boot, the same date as the earliest malware files.
- Both files had the ext4 immutable + append-only attributes set. The legitimate
system@framework@boot.oatin the same directory has the same attributes and the same SELinux label (u:object_r:zygote_exec:s0) on this build. This looks like how the build labels its boot images, not something malware-specific. - Assessment: these are the injector stages that could not be found in
/system. What wrote them at first boot (stage 1) is still not located.
Quarantine and result. 9 items were moved, not deleted, into a quarantine folder: the two .oat files above, the three .MLAndroid folders (/data/system, /data/misc, /data/media/0), and files/.data and files/.rtmark of Google Play Services and of the system browser. After one reboot, checked right away and again about 3 minutes later:
- zygote's memory maps no longer contain
acco/bridacco; - no
systemlibarm*ormms-core*file appears in any app's data folder; - none of the quarantined paths was re-created;
- logcat has no hits for
systemlibarm,MLAndroid,mms-core,boot-accoorbridacco; - the memory maps of Google Play Services and System UI are clean;
- all established TCP connections go to Google or the local network.
Normal TV functions (launcher, video streaming, input/source menu) still work.
What this means. Removing the two dalvik-cache files stopped the per-app injection, at least on this boot. The first-stage code that created them may still be in the read-only system image. It could write them again after a factory reset, or under a condition that was not met on this boot. A factory reset should therefore not be treated as a fix, and it might bring the injector back. Finding stage 1 needs a comparison with a clean copy of the same build; the vendor (CVTE) will be asked for one.
7. A separate issue: test keys and the vendor ad-SDK channel
- Test keys. The firmware's platform certificate is the public AOSP test key (SHA-1
27196e386b875e76adf700e7ea84e4c6eee33dfa), although the build is taggedrelease-keys. Any party can sign apps that this TV treats as platform apps. - Silent installer.
com.zeasn.services.general(Zeasn, v2.1.13) checkshttps://saas.zeasn.tv/sp/api/device/v1/app/silentevery hour. On instruction it downloadscom.android.media.module.servicesand installs, upgrades or reinstalls it with no user prompt and no integrity check, then starts it with server-supplied rules. The consent flag is hard-coded to "true". This is a built-in vendor feature, not a modified app. - The ad APK.
com.android.media.module.services(code packagecom.ad.service, v1.1.18). It is signed by an unrelated key (CN=socket, O=China) and was packed with Qihoo 360 Jiagu 1.4.0.6 on 2026-08-25. Its code is encrypted and was not unpacked. Visible configuration: three exported third-party SDK services ("Meta", "Pluzed", "ZeroOne"); a private root CA pinned formeta365.frostbytesize.com(AWS Ireland); Firebase projectmac-ad-9f1ee; permissions for location, phone state, the full app list, all-files storage and the advertising ID. It was installed and updated without any user action. - Assessment. It is an undisclosed ad or traffic-monetisation SDK host (medium confidence). Whether it acts as a proxy or shows hidden ads is unproven. No code, key or infrastructure overlap with the Triada implant was found.
- Disabling both apps did not stop the firmware-level injection.
Why this is dangerous
- Remote code execution in every app, including Google Play Services, System UI and apps holding user accounts. The operator can push arbitrary Java or native code at any time, and run shell commands with each app's permissions. This allows theft of account tokens, ad fraud, installing apps and changing behaviour later.
- Reverse / residential proxy.
IPProxyCorerelays operator-chosen TCP and UDP traffic through the owner's internet connection. Its log shows it connected to a relay in November 2024. Fraud, scanning or other abuse routed this way appears to come from the owner's IP address. - Data collection and account theft capability. The framework reports device identifiers (advertising ID, Android ID, MAC, serial). It ships a module built to steal WhatsApp account keys (not deployed on this TV). Its TLS clients accept any certificate.
- Device tracking. A persistent device ID (
sericode/cd) is stored in hidden folders and survives app data clearing. - Weak platform trust. The firmware is signed with public AOSP test keys, and the vendor's own service installs third-party code silently.
- Persistence. The injector is active since the unit's first boot. Its first stage may sit in the read-only system partition, and a factory reset does not remove it.
- Scale. The firmware is built for a platform sold in large numbers in Uzbekistan, so many households may be affected.
How to check your TV
Enable network (ADB) debugging on the TV, connect from a computer on the same network, and run each command on its own. None of them changes the device. No root is needed.
adb connect <TV-IP>:5555
adb shell getprop ro.build.fingerprint
adb shell getprop ro.build.tags
adb shell ls -la /sdcard/.MLAndroid
adb shell cat /proc/net/tcp
adb shell cat /proc/net/tcp6
adb shell pm list packages -u
adb shell dumpsys package com.android.media.module.services
adb logcat -b all -d
adb pull /system/framework/framework-res.apk
| # | Check | Infected / affected if |
|---|---|---|
| 1 | ro.build.fingerprint |
contains cvt_mt5863_eu and 20190905 (this build; other builds may also be affected) |
| 2 | /sdcard/.MLAndroid |
the directory exists (holds com.android.btcore.db) |
| 3 | logcat right after a reboot |
avc: denied … name=".MLAndroid" from zygote or system_server, or dex2oat lines naming systemlibarm_*.jar, mms-core.jar or .rtresext/.jar_ |
| 4 | /proc/net/tcp remote addresses (little-endian hex) |
D5B27970 (112.121.178.213, ports 2760 = 10080 and 28CB = 10443) or 04114294 (148.66.17.4, port 2B48 = 11080) |
| 5 | Package list | com.android.media.module.services present; dumpsys package shows installerPackageName=com.zeasn.services.general |
| 6 | apksigner verify --print-certs framework-res.apk on the computer |
certificate SHA-1 27196e386b875e76adf700e7ea84e4c6eee33dfa (public AOSP test key) |
| 7 | Router / DNS logs | queries for 1g5k5w.com, o96p.com, aaodp.com, uedfd.com, lvditoys.com, 3ko1.com, dv1wi3buwqfbb.cloudfront.net, frostbytesize.com, or traffic to the IPs in the IOC section |
| 8 | adb shell ls -la /data/dalvik-cache/arm/ (may need root on some builds) |
files named system@framework@boot-acco.oat or system@framework@boot-bridacco.oat exist |
The per-app payload store (/data/data/<app>/files/.data/) and /data/system/.MLAndroid/ need root to list. A non-root check relies on items 1–8.
When you are done, turn ADB debugging off again.
How to protect yourself
- Disconnect the TV from the internet (Ethernet and Wi-Fi), or put it on an isolated guest network or VLAN with no access to other home devices.
- If disconnecting is not possible, block at the router or DNS the domains and IPs in the IOC section. The proxy relay address is handed out at runtime, so blocking only known IPs is incomplete.
- Block Cloudflare, CloudFront and BunnyCDN-hosted indicators by domain, not by IP: their IPs are shared with unrelated sites.
- Port filtering of TCP/UDP 10080–11080 for the TV covers the observed C2 and relay ports.
- In testing, once these indicators were blocked at the router, the live C2 connection disappeared, the C2 domains no longer resolved, and the C2 and relay IPs timed out, while normal streaming services still worked.
- Do not sign in to Google or other accounts on the TV. If accounts were used on it, sign them out from another device and change their passwords.
- A factory reset does not remove this infection. Only clean firmware from the vendor fixes it. Until then, use an external streaming device and keep the TV offline.
For the vendor (CVTE / Skyworth / Velar / Zeasn): investigate the cvt_mt5863_eu build of 2019-09-05 and its supply chain, especially native libraries loaded by zygote (media JNI stack, ART runtime); publish clean firmware and an over-the-air update; re-sign the firmware with private release keys; explain why com.zeasn.services.general silently installs a packed third-party ad-SDK app without user consent, and who configured that server rule.
For CERTs and Google: block or sinkhole the C2 infrastructure (Cloudflare, Amazon CloudFront/AWS, BunnyCDN and Netsec HK can act on abuse reports for their hosted indicators); notify affected ISPs; check this build's Play Protect certification status; coordinate with HUMAN Security (BADBOX tracking) and anti-virus vendors. The YARA rules can be shared with them.
Indicators of compromise (IOC)
All hashes are SHA-256. Samples are kept offline and shared only on request.
Files from the TV
| File | SHA-256 |
|---|---|
systemlibarm_10145.jar (loader) |
c62ed6ed18509ed02165e1a812acda2705e42bd8cf090bb18601750561217059 |
loader classes.dex |
a99c9c099ffaf1d6b0224f9482ae20e9ce083948444d29c870d5c92c0f81e4a9 |
systemlibarm_10145.dex (dex2oat output; first 6,238 bytes zeroed) |
410ef622801b8264a683f93afa8a976fdaa9da47a0b15881eee6d8066bd19ef8 |
ylmd_1003.md (encrypted) |
4866a5eb2c7155aff8164185aa62e0b53b03179a0e3d8f0a982a4a15824def4b |
ss_1027.md (encrypted) |
c1fd9eb701cdb67f783a84d1c8cccb060f379ddeff59394b325082fb25503bca |
.oc_1_2004_1_…IPProxyCore (encrypted; MD5 7fdfcb86a58d2af3572c90fc48a09a32) |
a526a5fbb1621804b351645c4975b085ed06ffce52bbf49efd4e5e6ee6d243f5 |
com.android.media.module.services APK v1.1.18 |
c97195aff98d094ba8b4ddba2c7fc8f26328312ebf5b06e1ecbaab96a90f2c0e |
com.zeasn.services.general APK v2.1.13 |
322a0fd5a601b3c7d096f31992265bf26c6cea8b737e8937b8e434b00af8e6a9 |
Firmware libandroid_runtime.so |
385f357bee0dd1326d71e24fe776d7ba4279d527bb182ef231a2005ce14896f9 |
Firmware libart.so |
15c3548b3e87a4a8435c4c78e47eedf83151365fc51029d2abd7f881ffaaa261 |
Firmware libmedia_jni.so |
55dfa57ced72b19340bc6b84a79c03ccad89dd54b9255e4849bd02f549fe7ea0 |
Firmware boot-framework.oat |
65ac4b1db475a54c8f892860946addabb541e5a891e80e0a533b85bc4ed7a85e |
Decrypted modules (derived from the files above)
| Module | Decrypted ZIP | classes.dex |
|---|---|---|
ylmd_1003 (framework) |
987955308c3c1e4ebc0c1e0261a3ff08a2d82582e2a88bde733ec8fb806c472f |
2b72aa1040ad64f881244c5438a3933c1ad718d815b8b6cbd08e264084c2ca5c |
ss_1027 (stub) |
48db499a439560ae7f3f32bd21859dc5f7ba0ca80ee64061449607a9042d7393 |
aa2cac622785ec0e71ec07bf4b361bac71cc73276564c778845985d18b809e0b |
IPProxyCore (reverse proxy) |
b2ee5685e81e3a5c148954cf7d1d10e96caea8090e62fb5644f58d919e41eab4 |
53264eca4a42f41b3931df73dffd894a7ca6de0dc2c60c56386296eed4923566 |
TKEntry (WhatsApp stealer, not deployed) |
bfbd2be05a24adb5fb2845762bd99309fc8c7b8ea5cf07822fbc8949a71b66d7 |
7302f3ac6cf4442cc44f5f19bb173df2efe8a87dc4ec70a2261e3cb83f35f32b |
Network indicators (resolved 2026-10-21; may rotate)
| Indicator | Resolved to | Role |
|---|---|---|
XA1847.1g5k5w.com, 77o6S5.1g5k5w.com, 2TX120.1g5k5w.com, 7y3luK.1g5k5w.com (:10080); sXSplO.1g5k5w.com, hrqchb.1g5k5w.com (:10443) |
112.121.178.213 (Netsec Limited HK, 112.121.160.0/19) | Domain list in btdoinfo.db. Live connection observed from the GMS uid |
i4njg2.o96p.com, qobtwp.o96p.com |
CloudFront | CDN-fronted C2 (btdoinfo.db) |
https://vdy8jd.aaodp.com:10430/PhDomainf/recdot |
216.118.232.45 | Domain-list recovery |
https://216.118.228.253:10430/PhRecoverf/recip |
— | IP recovery |
https://hcnk.uedfd.com/OadCtrl/if, /OadCtrl/bt |
188.114.96.11, 188.114.97.11 (Cloudflare) | Framework task poll and reports (used on this TV) |
https://bk79n.uedfd.com/DLLogic/if, /DLLogic/bt, /DLLogic/app/token |
Cloudflare | Task poll for other hosts; WhatsApp-data exfiltration |
https://n6x5.uedfd.com/AdLogic/if, /AdLogic/bt |
Cloudflare | OAD module base (IPProxyCore) |
https://dv1wi3buwqfbb.cloudfront.net/ProxyGateway/apply/service |
CloudFront | Proxy gateway: hands out relay host/port |
148.66.17.4:11080 |
— | Proxy relay (November 2024, .ss_log) |
http://p8ydfra.lvditoys.com/DLBehavior/bt |
CloudFront | Loader-variant reports |
https://ivwbczv.3ko1.com/zvqmks/patch |
BunnyCDN, 138.199.24.219 | Device-ID provisioning (variant) |
https://saas.zeasn.tv/sp/api/device/v1/app/silent, …/app/download, …/auth-api/api/v1/auth/deviceSign, http://saas.zeasn.tv/log/open/report |
108.128.156.113 (AWS eu-west-1) | Vendor silent-install channel |
meta365.frostbytesize.com |
52.17.197.71, 108.132.135.213 (AWS eu-west-1) | Ad-SDK control host (pinned private CA) |
Firebase project mac-ad-9f1ee (sender 565791277901) |
Ad-APK telemetry |
File paths, names and other artefacts
- Loader:
/data/data/<any package>/systemlibarm_<N>.jar/.dex(N = 10145 here);/data/data/{com.android.systemui,com.google.android.gms}/mms-core.jar. - Injector stages:
/data/dalvik-cache/arm/system@framework@boot-acco.oat,/data/dalvik-cache/arm/system@framework@boot-bridacco.oat. - Device-ID stores:
/data/system/.MLAndroid/,/data/misc/.MLAndroid/,/sdcard/.MLAndroid/holdingcom.android.btcore.dbandtimeStampMask.db;/system/etc/com.android.btcore.db(path read by the framework). - Payload store (in GMS, the browser, potentially any app):
<app>/files/.data/holdingylmd_1003.md,ss_1027.md,btdoinfo.db,phone.db,timeStampMask.db,bt_mark_recover.db,.ss_log,.tkupdata.db;.ylc/.rtresext/,.ylc/.rtmarkext/,.ylc/.rtinfosext/info.db;.oc_<status>_<id>_<status>_<Base64(class)>\n, whose name ends in a newline;- temporary
.jar_<…>files.
IPProxyCorestate:<app>/files/.rtmark/.oci/.data_<id>/holding.odi_<id>.db,.ss_log,.ss_fp,.ss_ll,.ss_id; wake-lock tagPhoneWakelockTag.- Classes:
com.android.core.info.config.LDMCore,com.android.ml.bt.dymc.*,com.android.ml.bt.core.OPBDomainInfo,com.android.xb.ylmd_1003.*,com.android.xb.ss_1027.*,com.ds.server.DSCore,com.android.oad.ipproxy.IPProxyCore,com.dl.tk.TKEntry. - Broadcast actions:
com.dymc.<md5(package)>.lddex,com.dymc.<md5(package)>.ldso,LTF3OGYILC57K903ZDR4L8TBN1IYHJV4. Log tag:EXPML. Local service: port 45884 on the device itself (variant). - Certificates: AOSP test platform key, SHA-256
c8a2e9bccf597c2fb6dc66bee293fc13f2fc47ec77bc6b2b0d52c11f51192ab8(firmware and Zeasn APK); ad-APK signerCN=socket, O=China, SHA-256b0a71babf3c7cb18ba80df3c7bffd3a5ba89da32e5d37a31c63504133fcc5c74. - Vendor channel artefacts:
/data/data/com.zeasn.services.general/shared_prefs/ad_service_sdk.xml(ad_rule_data),/data/data/com.zeasn.services.general/files/ad_service_<ver>.apk.
The YARA rules (8 for the Triada implant, 4 for the ad APK) match every local sample. They gave 0 hits on 60 clean framework dex files and on a raw scan of 533 pulled system files. They have not been tested against a broad goodware corpus. The rules will be shared with CERTs and anti-virus vendors.
Evidence
Logs, copies of the malware files, system-partition copies, decrypted payloads and analysis scripts are kept with SHA-256 hashes. Malware samples are shared only on request, with recipients chosen by the owner.
References
- Kaspersky, "Triada strikes back" (2025-04-25): https://securelist.com/triada-trojan-modules-analogy/116380/
- Kaspersky, "Attack on Zygote" (2016): https://securelist.com/attack-on-zygote-a-new-twist-in-the-evolution-of-mobile-threats/74032/
- Dr.Web, Android.Triada.231 (2017): https://news.drweb.com/show/?i=11390
- FBI PSA I-060525 on BADBOX 2.0 (2025): https://www.ic3.gov/psa/2025/psa250605