
Récemment, Group-IB une activité du cheval de Troie Android Gustuff. Il opÚre exclusivement sur les marchés internationaux, ciblant les clients des 100 plus grandes banques étrangÚres, les utilisateurs de 32 portefeuilles de cryptomonnaies, ainsi que de grandes plateformes e-commerce. Quant au développeur de Gustuff, il s'agit d'un cybercriminel russophone surnommé Bestoffer. Il y a peu, il faisait l'éloge de son cheval de Troie comme d'un « produit sérieux pour les personnes ayant des connaissances et de l'expérience ».
L'analyste de malwares chez Group-IB Ivan Pisariev explique en détail dans son étude comment fonctionne Gustuff et quels sont ses dangers.
Qui Gustuff cible
Gustuff appartient à une nouvelle génération de logiciels malveillants dotés de fonctions entiÚrement automatisées. Selon le développeur, le cheval de Troie est une version améliorée du logiciel malveillant AndyBot, qui attaque les téléphones sous Android depuis novembre 2017 et vole de l'argent via des formulaires Web de phishing, se déguisant en applications mobiles des banques internationales et des systÚmes de paiement connus. Bestoffer a indiqué que le prix de location du « Gustuff Bot » était de 800 $ par mois.
L'analyse de l'échantillon de Gustuff a montré que le cheval de Troie cible potentiellement les clients utilisant des applications bancaires des plus grandes banques, telles que Bank of America, Bank of Scotland, J.P. Morgan, Wells Fargo, Capital One, TD Bank, PNC Bank, ainsi que des portefeuilles de cryptomonnaies comme Bitcoin Wallet, BitPay, Cryptopay, Coinbase, etc.
Initialement conçu comme un cheval de Troie bancaire classique, la version actuelle de Gustuff a considérablement élargi la liste des cibles potentielles. En plus des applications bancaires Android, des entreprises fintech et des services de cryptomonnaies, Gustuff s'attaque aux utilisateurs d'applications de marketplaces, de boutiques en ligne, de systÚmes de paiement et de messageries. En particulier, PayPal, Western Union, eBay, Walmart, Skype, WhatsApp, Gett Taxi, Revolut et d'autres.
Point d'entrée : ciblage d'une infection massive
Gustuff se caractĂ©rise par un vecteur d'infection « classique » pour les smartphones Android via des SMS contenant des liens vers des APK. Lorsqu'un appareil Android est infectĂ© par un cheval de Troie, Gustuff peut se propager davantage dans le carnet de contacts du tĂ©lĂ©phone infectĂ© ou dans la base de donnĂ©es du serveur sous les ordres du serveur. Les fonctionnalitĂ©s de Gustuff sont conçues pour une infection massive et une maximisation des profits de ses opĂ©rateurs â il y a une fonction unique « d'auto-injection » dans des applications bancaires mobiles lĂ©gitimes et des portefeuilles de cryptomonnaies, ce qui permet d'accĂ©lĂ©rer et d'Ă©largir le vol d'argent.
L'Ă©tude du cheval de Troie a montrĂ© que la fonction d'auto-injection est mise en Ćuvre grĂące au Service d'accessibilitĂ© â un service pour les personnes handicapĂ©es. Gustuff n'est pas le premier cheval de Troie Ă contourner avec succĂšs la protection contre l'interaction avec les Ă©lĂ©ments des fenĂȘtres d'autres applications Ă l'aide de ce service Android. Cependant, l'utilisation du Service d'accessibilitĂ© en combinaison avec l'auto-injection reste encore un phĂ©nomĂšne relativement rare.
AprĂšs son tĂ©lĂ©chargement sur le tĂ©lĂ©phone de la victime, Gustuff, en utilisant le Service d'accessibilitĂ©, obtient la possibilitĂ© d'interagir avec les Ă©lĂ©ments des fenĂȘtres d'autres applications (bancaires, de cryptomonnaies, ainsi que des applications de commerce en ligne, de messagerie, etc.), exĂ©cutant les actions nĂ©cessaires pour les malfaiteurs. Par exemple, sous les ordres du serveur, le cheval de Troie peut cliquer sur des boutons et modifier les valeurs des champs de texte dans les applications bancaires. L'utilisation du mĂ©canisme du Service d'accessibilitĂ© permet au cheval de Troie de contourner les mĂ©canismes de protection utilisĂ©s par les banques contre les chevaux de Troie mobiles de gĂ©nĂ©ration prĂ©cĂ©dente, ainsi que les modifications des politiques de sĂ©curitĂ© mises en place par Google dans les nouvelles versions du systĂšme d'exploitation Android. Ainsi, Gustuff « sait » dĂ©sactiver la protection Google Protect : selon l'auteur, cette fonction s'active dans 70 % des cas.

Gustuff peut Ă©galement afficher de fausses notifications PUSH avec des icĂŽnes d'applications mobiles lĂ©gitimes. L'utilisateur clique sur la notification PUSH et voit une fenĂȘtre de phishing chargĂ©e depuis le serveur, oĂč il entre lui-mĂȘme les informations demandĂ©es de sa carte bancaire ou de son portefeuille cryptographique. Dans un autre scĂ©nario d'utilisation de Gustuff, l'application, au nom de laquelle la notification PUSH a Ă©tĂ© affichĂ©e, s'ouvre. Dans ce cas, le malware peut remplir les champs du formulaire bancaire pour une transaction frauduleuse Ă la demande du serveur via le service d'accessibilitĂ©.
Les fonctionnalitĂ©s de Gustuff incluent Ă©galement l'envoi d'informations sur l'appareil infectĂ© au serveur, la possibilitĂ© de lire/envoi de SMS, l'envoi de requĂȘtes USSD, le lancement d'un proxy SOCKS5, le suivi de liens, l'envoi de fichiers (y compris des scans de documents, des captures d'Ă©cran, des photos) au serveur, et la rĂ©initialisation de l'appareil aux paramĂštres d'usine.
Analyse du malware
Avant l'installation de l'application malveillante, le systĂšme Android affiche une fenĂȘtre contenant la liste des autorisations demandĂ©es par Gustuff :

L'installation de l'application ne se fera qu'aprĂšs l'accord de l'utilisateur. AprĂšs le lancement de l'application, le cheval de Troie affichera une fenĂȘtre Ă l'utilisateur :

AprĂšs quoi il supprimera son icĂŽne.
Gustuff est empaqueté, selon l'auteur, avec un empaqueteur de FTT. AprÚs son lancement, l'application communique périodiquement avec le serveur CnC pour recevoir des commandes. Dans plusieurs fichiers que nous avons examinés, une adresse IP a été utilisée comme serveur de contrÎle. 88.99.171[.]105 (nous l'appellerons ensuite <%CnC%>).
AprĂšs le lancement, le programme commence Ă envoyer des messages au serveur http:///api/v1/get.php.
En réponse, on s'attend à un JSON au format suivant :
{
"results" : "OK",
"command":{
"id": "",
"command":"",
"timestamp":"",
"params":{
},
},
}à chaque demande, l'application envoie des informations sur l'appareil infecté. Le format du message est présenté ci-dessous. Il convient de noter que les champs full, extra, apps et permission sont optionnels et ne seront envoyés que si une commande de demande provient du CnC.
{
"info":
{
"info":
{
"cell":,
"country":,
"imei":,
"number":,
"line1Number":,
"advertisementId":
},
"state":
{
"admin":,
"source":,
"needPermissions":,
"accesByName":,
"accesByService":,
"safetyNet":,
"defaultSmsApp":,
"isDefaultSmsApp":,
"dateTime":,
"batteryLevel":
},
"socks":
{
"id":,
"enabled":,
"active":
},
"version":
{
"versionName":,
"versionCode":,
"lastUpdateTime":,
"tag":,
"targetSdkVersion":,
"buildConfigTimestamp":1541309066721
},
},
"full":
{
"model":,
"localeCountry":,
"localeLang":,
"accounts":,
"lockType":
},
"extra":
{
"serial":,
"board":,
"brand":,
"user":,
"device":,
"display":,
"id":,
"manufacturer":,
"model":,
"product":,
"tags":,
"type":,
"imei":,
"imsi":,
"line1number":,
"iccid":,
"mcc":,
"mnc":,
"cellid":,
"lac":,
"androidid":,
"ssid":
},
"apps":{},
"permission":
} Stockage des données de configuration
Gustuff stocke des informations essentielles au fonctionnement dans un fichier de prĂ©fĂ©rences. Le nom du fichier, tout comme les noms des paramĂštres qu'il contient, est le rĂ©sultat du calcul d'une somme de contrĂŽle MD5 d'une chaĂźne. 15413090667214.6.1, oĂč <%name%> â nom-valeur d'origine. InterprĂ©tation Python de la fonction de gĂ©nĂ©ration de nom :
nameGenerator(input):
output = md5("15413090667214.6.1" + input) Nous désignerons plus tard comme nameGenerator(input).
Ainsi, le nom du premier fichier : nameGenerator("API_SERVER_LIST"), il contient des valeurs avec les noms suivants :
| Nom de la variable | Valeur |
|---|---|
| nameGenerator("API_SERVER_LIST") | Contient une liste d'adresses CnC sous forme de tableau. |
| nameGenerator("API_SERVER_URL") | Contient une adresse CnC. |
| nameGenerator("SMS_UPLOAD") | Le drapeau par défaut est activé. Si le drapeau est activé, il envoie des SMS au CnC. |
| nameGenerator(«SMS_ROOT_NUMBER») | Le numéro de téléphone vers lequel les messages SMS des dispositifs infectés seront envoyés. Par défaut, nul. |
| nameGenerator(«SMS_ROOT_NUMBER_RESEND») | Le drapeau par défaut est désactivé. S'il est activé, les SMS reçus par le dispositif infecté seront envoyés au numéro racine. |
| nameGenerator(«DEFAULT_APP_SMS») | Le drapeau par défaut est désactivé. Si ce drapeau est activé, l'application traitera les messages SMS entrants. |
| nameGenerator(«DEFAULT_ADMIN») | Le drapeau par défaut est désactivé. Si le drapeau est activé, l'application a des droits d'administrateur. |
| nameGenerator(«DEFAULT_ACCESSIBILITY») | Le drapeau par défaut est désactivé. Si le drapeau est activé, le service utilisant le Service d'accessibilité est lancé. |
| nameGenerator(«APPS_CONFIG») | Objet JSON contenant la liste des actions à effectuer lors d'un événement d'accessibilité associé à une application spécifique. |
| nameGenerator(«APPS_INSTALLED») | Contient la liste des applications installées sur le dispositif. |
| nameGenerator(«IS_FIST_RUN») | Le drapeau est réinitialisé lors du premier lancement. |
| nameGenerator(«UNIQUE_ID») | Contient l'identifiant unique. Il est généré lors du premier lancement du bot. |
Module de traitement des commandes du serveur.
L'application stocke les adresses des serveurs CnC sous forme de tableau de chaĂźnes codĂ©es en Base85 Les adresses CnC â serveurs peuvent ĂȘtre modifiĂ©es lors de la rĂ©ception de la commande appropriĂ©e, dans ce cas, les adresses seront stockĂ©es dans le fichier de prĂ©fĂ©rences.
En réponse à la demande, le serveur envoie à l'application une commande. Il convient de noter que les commandes et les paramÚtres sont présentés au format JSON. L'application peut traiter les commandes suivantes :
| Commande | Description |
|---|---|
| forwardStart | Commencer l'envoi des SMS reçus par le dispositif infecté au serveur CnC. |
| forwardStop | ArrĂȘter l'envoi des SMS reçus par le dispositif infectĂ© au serveur CnC. |
| ussdRun | ExĂ©cuter une requĂȘte USSD. Le numĂ©ro sur lequel la requĂȘte USSD doit ĂȘtre effectuĂ©e se trouve dans le champ JSON «number». |
| sendSms | Envoyer un message SMS (si nĂ©cessaire, le message est «fragmenté» en morceaux). En tant que paramĂštre, la commande prend un objet JSON contenant les champs «to» â numĂ©ro de destination et «body» â corps du message. |
| sendSmsAb | Envoyer des SMS (si nécessaire le message est 'fractionné' en parties) à tous les contacts de l'appareil infecté. L'intervalle entre l'envoi des messages est de 10 secondes. Le corps du message se trouve dans le champ JSON « body » |
| sendSmsMass | Envoyer des SMS (si nĂ©cessaire le message est 'fractionnĂ©' en parties) aux contacts spĂ©cifiĂ©s dans les paramĂštres de la commande. L'intervalle entre l'envoi des messages est de 10 secondes. Comme paramĂštre, la commande prend un tableau JSON (champ « sms »), dont les Ă©lĂ©ments contiennent les champs « to » â numĂ©ro de destination et « body » â corps du message. |
| changeServer | Cette commande peut accepter comme paramĂštre une valeur avec la clĂ© « url » â alors le bot changera la valeur de nameGenerator(âSERVER_URLâ), ou « array » â alors le bot enregistrera un tableau dans nameGenerator (âAPI_SERVER_LISTâ). Ainsi, l'application change l'adresse des serveurs CnC. |
| adminNumber | La commande est destinĂ©e Ă travailler avec le numĂ©ro root. La commande accepte un objet JSON avec les paramĂštres suivants : « number » â modifier nameGenerator(âROOT_NUMBERâ) avec la valeur reçue, « resend » â modifier nameGenerator(âSMS_ROOT_NUMBER_RESENDâ), « sendId » â envoyer Ă nameGenerator(âROOT_NUMBERâ) uniqueID. |
| updateInfo | Envoyer au serveur des informations sur l'appareil infecté. |
| wipeData | La commande est destinée à supprimer les données utilisateur. En fonction de quel nom l'application a été lancée, il se produit soit une suppression complÚte des données avec redémarrage de l'appareil (utilisateur principal), soit la suppression uniquement des données utilisateur (utilisateur secondaire). |
| socksStart | Lancer le module Proxy. Le fonctionnement du module est décrit dans une section distincte. |
| socksStop | ArrĂȘter le fonctionnement du module Proxy. |
| openLink | Accéder au lien. Le lien se trouve dans le paramÚtre JSON sous la clé « url ». Pour ouvrir le lien, on utilise « android.intent.action.VIEW ». |
| uploadAllSms | Envoyer au serveur tous les SMS reçus par l'appareil. |
| uploadAllPhotos | Envoyer à l'URL des images de l'appareil infecté. L'URL est reçue comme paramÚtre. |
| uploadFile | Envoyer à l'URL un fichier de l'appareil infecté. L'URL est reçue comme paramÚtre. |
| uploadPhoneNumbers | Envoyer au serveur les numéros de téléphone de la liste des contacts. Si un objet JSON est passé en tant que paramÚtre avec la clé « ab », l'application obtient la liste des contacts depuis le carnet d'adresses. Si un objet JSON est passé en tant que paramÚtre avec la clé « sms », l'application lit la liste des contacts des expéditeurs de SMS. |
| changeArchive | L'application télécharge un fichier depuis l'URL fournie comme paramÚtre sous la clé «url». Le fichier téléchargé est enregistré sous le nom «archive.zip». Ensuite, l'application décompresse le fichier, en utilisant éventuellement le mot de passe d'archive «b5jXh37gxgHBrZhQ4j3D». Les fichiers décompressés sont enregistrés dans le répertoire [external storage]/hgps. Dans ce répertoire, l'application stocke les web-fakes (décrits ci-dessous). |
| actions | La commande est destinée à travailler avec le Service Action, qui est décrit dans une section séparée. |
| test | Ne fait rien. |
| download | La commande est destinée à télécharger un fichier depuis un serveur distant et à le sauvegarder dans le répertoire «Downloads». L'URL et le nom du fichier sont fournis comme paramÚtres, les champs dans l'objet JSON étant respectivement : «url» et «fileName». |
| remove | Supprime un fichier du répertoire «Downloads». Le nom du fichier est fourni dans le paramÚtre JSON avec la clé «fileName». Le nom de fichier par défaut est «tmp.apk». |
| notification | Afficher une notification avec des textes de description et de titre, définis par le serveur de gestion. |
Format de la commande notification:
{
"results" : "OK",
"command":{
"id": ,
"command":"notification",
"timestamp":,
"params":{
"openApp":,
"array":[
{"title":,
"desc":,
"app":}
]
},
},
}La notification créée par le fichier examinĂ© ressemble identiquement aux notifications créées par l'application indiquĂ©e dans le champ app. Si la valeur du champ openApp â True, lorsque la notification est ouverte, l'application spĂ©cifiĂ©e dans le champ sera lancĂ©e, app. Si la valeur du champ openApp â False, alors :
- une fenĂȘtre d'hameçonnage s'ouvre, dont le contenu est tĂ©lĂ©chargĂ© depuis le rĂ©pertoire /hgps/
- une fenĂȘtre d'hameçonnage s'ouvre, dont le contenu est tĂ©lĂ©chargĂ© depuis le serveur ?id=&app=
- une fenĂȘtre d'hameçonnage s'ouvre, dĂ©guisĂ©e en Google Play Card, permettant de saisir les donnĂ©es de la carte.
Le résultat de l'exécution de toute commande est envoyé par l'application à set_state.php sous la forme d'un objet JSON du format suivant :
{
"command":
{
"command":,
"id":,
"state":
}
"id":
} ActionsService
La liste des commandes que l'application traite comprend action. Lorsque la commande est reçue, le module de traitement des commandes se connecte à ce service pour exécuter la commande étendue. Le service prend un objet JSON comme paramÚtre. Le service peut exécuter les commandes suivantes :
1. PARAMS_ACTION â lorsque cette commande est reçue, le service obtient d'abord la valeur par clĂ© Type Ă partir du paramĂštre JSON, qui peut ĂȘtre le suivant :
- serviceInfo â la sous-commande obtient la valeur par clĂ© Ă partir du paramĂštre JSON includeNotImportant. Si le flag est Ă©gal Ă True, l'application dĂ©finit le flag FLAG_ISOLATED_PROCESS sur le service utilisant Accessibility Service. Ainsi, le service sera exĂ©cutĂ© dans un processus distinct.
- root â obtenir et envoyer au serveur des informations sur la fenĂȘtre qui est actuellement au premier plan. L'application obtient les informations Ă l'aide de la classe AccessibilityNodeInfo.
- admin â demander des droits administratifs.
- delay â suspendre le fonctionnement d'ActionsService pendant le nombre de millisecondes spĂ©cifiĂ© dans le paramĂštre clĂ© «data».
- windows â envoyer la liste des fenĂȘtres visibles Ă l'utilisateur.
- install â installer l'application sur l'appareil infectĂ©. Le nom du paquet â l'archive se trouve dans la clĂ© «fileName». L'archive elle-mĂȘme se trouve dans le rĂ©pertoire Downloads.
- global â la sous-commande est destinĂ©e Ă effectuer une transition depuis la fenĂȘtre actuelle :
- vers le menu Quick Settings
- retour
- accueil
- vers les notifications
- vers la fenĂȘtre des applications rĂ©cemment ouvertes
- launch â lancer l'application. Le nom de l'application est transmis comme paramĂštre dans la clĂ© data.
- sounds â changer le mode audio en silence.
- unlock â active la luminositĂ© maximale de l'Ă©cran et du clavier. L'application effectue cette action Ă l'aide de WakeLock, en spĂ©cifiant la chaĂźne [Application lable]:INFO comme tag.
- permissionOverlay â fonction non implĂ©mentĂ©e (rĂ©ponse Ă l'exĂ©cution de la commande â {«message»:«Not support»} ou {«message»:«low sdk»})
- gesture â fonction non implĂ©mentĂ©e (rĂ©ponse Ă l'exĂ©cution de la commande â {«message»:«Not support»} ou {«message»:«Low API»})
- permissions â cette commande est nĂ©cessaire pour demander des permissions pour l'application. Cependant, la fonction de demande n'est pas implĂ©mentĂ©e, donc la commande n'a pas de sens. La liste des permissions demandĂ©es arrive sous forme de tableau JSON avec la clĂ© «permissions». Liste standard :
- android.permission.READ_PHONE_STATE
- android.permission.READ_CONTACTS
- android.permission.CALL_PHONE
- android.permission.RECEIVE_SMS
- android.permission.SEND_SMS
- android.permission.READ_SMS
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
- open â afficher une fenĂȘtre de phishing. Selon les paramĂštres reçus du serveur, l'application peut prĂ©senter les fenĂȘtres de phishing suivantes :
- Afficher la fenĂȘtre de phishing, dont le contenu est dĂ©fini dans le fichier dans le rĂ©pertoire /hgps/. Le rĂ©sultat de l'interaction de l'utilisateur avec la fenĂȘtre sera envoyĂ© Ă l'adresse /records.php
- Afficher la fenĂȘtre de phishing, dont le contenu est prĂ©alablement chargĂ© depuis l'adresse ?id=&app=. Le rĂ©sultat de l'interaction de l'utilisateur avec la fenĂȘtre sera envoyĂ© Ă l'adresse /records.php
- Afficher la fenĂȘtre de phishing dĂ©guisĂ©e en carte Google Play.
- interactive â la commande est destinĂ©e Ă interagir avec les Ă©lĂ©ments des fenĂȘtres d'autres applications via AcessibilityService. Un service spĂ©cial a Ă©tĂ© mis en place pour l'interaction dans le programme. L'application explorĂ©e peut interagir avec les fenĂȘtres :
- Actives au moment présent. Dans ce cas, le paramÚtre contient l'id ou le texte (le nom) de l'objet avec lequel il faut interagir.
- Visibles Ă l'utilisateur au moment de l'exĂ©cution de la commande. L'application sĂ©lectionne les fenĂȘtres par id.
AprĂšs avoir obtenu les objets AccessibilityNodeInfo pour les Ă©lĂ©ments d'intĂ©rĂȘt de la fenĂȘtre, l'application peut effectuer des actions en fonction des paramĂštres :
- focus â mettre le focus sur l'objet.
- click â cliquer sur l'objet.
- actionId â exĂ©cuter l'action par ID.
- setText â modifier le texte de l'objet. La modification du texte peut ĂȘtre effectuĂ©e de deux maniĂšres : en exĂ©cutant l'action ACTION_SET_TEXT si la version d'Android de l'appareil infectĂ© est infĂ©rieure ou Ă©gale Ă LOLLIPOP), ou en plaçant la chaĂźne dans le presse-papiers et en la collant dans l'objet (pour les versions plus rĂ©centes). Cette commande peut ĂȘtre utilisĂ©e pour modifier des donnĂ©es dans une application bancaire.
2. PARAMS_ACTIONS â c'est la mĂȘme chose que PARAMS_ACTION, sauf que cela arrive sous la forme d'un tableau JSON de commandes.
Il semble que beaucoup d'entre vous soient curieux de savoir Ă quoi ressemble la fonction d'interaction avec les Ă©lĂ©ments d'une fenĂȘtre d'autre application. C'est ainsi que cette fonctionnalitĂ© a Ă©tĂ© mise en Ćuvre dans Gustuff :
boolean interactiveAction(List aiList, JSONObject action, JsonObject res) {
int count = action.optInt("repeat", 1);
Iterator aiListIterator = ((Iterable)aiList).iterator();
int count = 0;
while(aiListIterator.hasNext()) {
Object ani = aiListIterator.next();
if(1 <= count) {
int index;
for(index = 1; true; ++index) {
if(action.has("focus")) {
if(((AccessibilityNodeInfo)ani).performAction(1)) {
++count;
}
}
else if(action.has("click")) {
if(((AccessibilityNodeInfo)ani).performAction(16)) {
++count;
}
}
else if(action.has("actionId")) {
if(((AccessibilityNodeInfo)ani).performAction(action.optInt("actionId"))) {
++count;
}
}
else if(action.has("setText")) {
customHeader ch = CustomAccessibilityService.a;
Context context = this.getApplicationContext();
String text = action.optString("setText");
if(performSetTextAction(ch, context, ((AccessibilityNodeInfo)ani), text)) {
++count;
}
}
if(index == count) {
break;
}
}
}
((AccessibilityNodeInfo)ani).recycle();
}
res.addPropertyNumber("res", Integer.valueOf(count));
}Fonction de remplacement de texte :
boolean performSetTextAction(Context context, AccessibilityNodeInfo ani, String text) {
boolean result;
if(Build$VERSION.SDK_INT >= 21) {
Bundle b = new Bundle();
b.putCharSequence("ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE", ((CharSequence)text));
result = ani.performAction(0x200000, b); // ACTION_SET_TEXT
}
else {
Object clipboard = context.getSystemService("clipboard");
if(clipboard != null) {
((ClipboardManager)clipboard).setPrimaryClip(ClipData.newPlainText("autofill_pm", ((CharSequence)text)));
result = ani.performAction(0x8000); // ACTION_PASTE
}
else {
result = false;
}
}
return result;
}Ainsi, avec la configuration correcte du serveur de contrĂŽle, Gustuff peut remplir les champs de texte dans une application bancaire et appuyer sur les boutons nĂ©cessaires pour effectuer des transactions. Le cheval de Troie n'a mĂȘme pas besoin de passer par la procĂ©dure d'authentification dans l'application â il suffit d'envoyer un ordre pour afficher une notification PUSH, suivie de l'ouverture de l'application bancaire installĂ©e prĂ©cĂ©demment. L'utilisateur s'authentifiera lui-mĂȘme, aprĂšs quoi Gustuff pourra procĂ©der Ă un remplissage automatique.
Module de traitement des messages SMS
L'application installe un gestionnaire d'événements pour la réception de messages SMS sur l'appareil infecté. L'application étudiée peut recevoir des commandes de l'opérateur qui arrivent dans le corps des messages SMS. Les commandes arrivent au format :
7!5=
L'application recherche dans tous les messages SMS entrants la chaĂźne 7!5=, lors de la dĂ©tection de la chaĂźne â dĂ©code la chaĂźne en Base64 avec un dĂ©calage de 4 et exĂ©cute la commande. Les commandes sont similaires aux commandes avec CnC. Le rĂ©sultat de l'exĂ©cution est envoyĂ© au mĂȘme numĂ©ro d'oĂč la commande a Ă©tĂ© reçue. Format de la rĂ©ponse :
7*5=
Optionnellement, l'application peut envoyer tous les messages reçus au numĂ©ro Root. Pour cela, le numĂ©ro Root doit ĂȘtre spĂ©cifiĂ© dans le fichier de prĂ©fĂ©rences et le drapeau de redirection des messages doit ĂȘtre activĂ©. Le SMS est envoyĂ© au numĂ©ro de l'attaquant au format :
â
L'application peut également optionnellement envoyer des messages au CnC. Le SMS est envoyé au serveur au format JSON :
{
"id":,
"sms":
{
"text":,
"number":,
"date":
}
}Si le drapeau est activĂ© nameGenerator(«DEFAULT_APP_SMS») â l'application arrĂȘte le traitement du SMS et vide la liste des messages entrants.
Module Proxy
L'application examinée comporte un module Backconnect Proxy (ci-aprÚs dénommé module Proxy), qui a une classe distincte contenant des champs statiques avec la configuration. Les données de configuration sont stockées en clair dans l'échantillon :

Toutes les actions effectuĂ©es par le module Proxy sont journalisĂ©es dans des fichiers. Pour cela, l'application crĂ©e un rĂ©pertoire nommĂ© «logs» dans le stockage externe (champ ProxyConfigClass.logsDir dans la classe de configuration), oĂč sont stockĂ©s les fichiers de log. La journalisation se fait dans des fichiers nommĂ©s :
- main.txt â ce fichier enregistre le fonctionnement de la classe nommĂ©e CommandServer. Plus tard, la journalisation de la chaĂźne str dans ce fichier sera dĂ©signĂ©e comme mainLog(str).
- session-.txt â ce fichier enregistre les donnĂ©es de log liĂ©es Ă une session de proxy spĂ©cifique. Plus tard, la journalisation de la chaĂźne str dans ce fichier sera dĂ©signĂ©e comme sessionLog(str).
- server.txt â ce fichier enregistre toutes les donnĂ©es Ă©crites dans les fichiers dĂ©crits ci-dessus.
Format des données de log :
[Thread[], id[]]: log-string
Les exceptions survenant lors du fonctionnement du module Proxy sont également journalisées dans un fichier. Pour cela, l'application forme un objet JSON au format :
{
"uncaughtException":
"thread":
"message":
"trace": //Stack trace info
[
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
},
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
}
]
}Ensuite, il le convertit en une représentation sous forme de chaßne et le consigne.
Le module Proxy est lancĂ© aprĂšs rĂ©ception de la commande appropriĂ©e. Lors de la rĂ©ception de la commande de dĂ©marrage du module Proxy, l'application dĂ©marre le service appelĂ© MainService, qui est responsable de la gestion des opĂ©rations du module Proxy - son dĂ©marrage et son arrĂȘt.
Ătapes de dĂ©marrage du service :
1. Démarre un minuteur qui se déclenche toutes les minutes et vérifie l'activité du module Proxy. Si le module n'est pas actif, il le lance.
Ăgalement, lors de l'activation de l'Ă©vĂ©nement android.net.conn.CONNECTIVITY_CHANGE , le module Proxy est lancĂ©.
2. L'application crĂ©e un wake-lock avec le paramĂštre PARTIAL_WAKE_LOCK et l'attrape. Ainsi, cela empĂȘche le CPU de l'appareil de passer en mode veille.
3. Lance la classe de traitement des commandes du module Proxy, aprÚs avoir préalablement consigné la chaßne mainLog(«start server») et
Server::start() host[], commandPort[], proxyPort[]
oĂč proxy_cnc, command_port et proxy_port sont des paramĂštres obtenus Ă partir de la configuration du serveur Proxy.
La classe de traitement des commandes s'appelle CommandConnection. DÚs son lancement, elle exécute les actions suivantes :
4. Se connecte à ProxyConfigClass.host: ProxyConfigClass.commandPort et envoie les données de l'appareil infecté au format JSON :
{
"id":,
"imei":,
"imsi":,
"model":,
"manufacturer":,
"androidVersion":,
"country":,
"partnerId":,
"packageName":,
"networkType":,
"hasGsmSupport":,
"simReady":,
"simCountry":,
"networkOperator":,
"simOperator":,
"version":
}OĂč :
- id â identifiant, essaie de rĂ©cupĂ©rer la valeur du champ «id» du fichier Shared Preference nommĂ© «x». Si cette valeur ne peut pas ĂȘtre obtenue, en gĂ©nĂšre une nouvelle. Ainsi, le module Proxy a son propre identifiant, gĂ©nĂ©rĂ© de la mĂȘme maniĂšre que le Bot ID.
- imei â IMEI de l'appareil. Si une erreur se produit lors de la rĂ©cupĂ©ration de la valeur, un message d'erreur sera inscrit Ă la place de ce champ.
- imsi â IdentitĂ© d'abonnĂ© mobile internationale de l'appareil. En cas d'erreur lors de l'obtention de la valeur, un message d'erreur sera enregistrĂ© Ă la place de ce champ.
- model â Le nom visible de l'utilisateur final pour le produit final.
- manufacturer â Le fabricant du produit/matĂ©riel (Build.MANUFACTURER).
- androidVersion â une chaĂźne au format « (), »
- country â la localisation actuelle de l'appareil.
- partnerId â une chaĂźne vide.
- packageName â nom du package.
- networkType â le type de connexion rĂ©seau actuelle (exemple : «WIFI», «MOBILE»). En cas d'erreur, renvoie null.
- hasGsmSupport â true â si le tĂ©lĂ©phone prend en charge le GSM, sinon false.
- simReady â Ă©tat de la carte SIM.
- simCountry â code ISO du pays (basĂ© sur le fournisseur de carte SIM).
- networkOperator â nom de l'opĂ©rateur. En cas d'erreur lors de l'obtention de la valeur, un message d'erreur sera enregistrĂ© Ă la place de ce champ.
- simOperator â Le nom du fournisseur de services (SPN). En cas d'erreur lors de l'obtention de la valeur, un message d'erreur sera enregistrĂ© Ă la place de ce champ.
- version â ce champ est stockĂ© dans la classe de configuration, pour les versions Ă©tudiĂ©es du bot, il Ă©tait Ă©gal à «1.6».
5. Passe en mode d'attente des commandes du serveur. Les commandes du serveur arrivent au format :
- 0 offset â commande
- 1 offset â sessionId
- 2 offset â longueur
- 4 offset â donnĂ©es
Lors de la réception de la commande, l'application journalise :
mainLog("Header { sessionId], type[], length[] }")
Les commandes suivantes peuvent provenir du serveur :
| Nom | Commande | Données | Description |
|---|---|---|---|
| connectionId | 0 | ID de connexion | Créer une nouvelle connexion |
| SLEEP | 3 | Temps | Suspendre le module Proxy |
| PING_PONG | 4 | â | Envoyer un message PONG |
Le message PONG est constitué de 4 octets et se présente comme suit : 0x04000000.
Lors de la réception de la commande connectionId (pour la création d'une nouvelle connexion) CommandConnection crée une instance de la classe ProxyConnection.
- Deux classes participent au proxy : ProxyConnection et end. Lors de la création de la classe ProxyConnection une connexion est établie à l'adresse ProxyConfigClass.host: ProxyConfigClass.proxyPort et un objet JSON est transmis :
{
"id":
}En rĂ©ponse, le serveur envoie un message SOCKS5, qui contient l'adresse du serveur distant avec lequel il faut Ă©tablir une connexion. L'interaction avec ce serveur se fait via la classe end. De maniĂšre schĂ©matique, l'Ă©tablissement de la connexion peut ĂȘtre reprĂ©sentĂ© comme suit :

Interactions réseau
Pour prĂ©venir l'analyse du trafic par des sniffers rĂ©seau, l'interaction entre le serveur CnC et l'application peut ĂȘtre protĂ©gĂ©e par le protocole SSL. Toutes les donnĂ©es transmises, tant du serveur que vers le serveur, sont prĂ©sentĂ©es au format JSON. Pendant son fonctionnement, l'application effectue les requĂȘtes suivantes :
- http:///api/v1/set_state.php â rĂ©sultat de l'exĂ©cution de la commande.
- http:///api/v1/get.php â rĂ©ception de la commande.
- http:///api/v1/load_sms.php â extraction des SMS du dispositif infectĂ©.
- http:///api/v1/load_ab.php â extraction de la liste de contacts du dispositif infectĂ©.
- http:///api/v1/aevents.php â la requĂȘte est effectuĂ©e lors de la mise Ă jour des paramĂštres dans le fichier de prĂ©fĂ©rences.
- http:///api/v1/set_card.php â extraction des donnĂ©es obtenues via la fenĂȘtre de phishing se faisant passer pour Google Play Market.
- http:///api/v1/logs.php â extraction des journaux de donnĂ©es.
- http:///api/v1/records.php â extraction des donnĂ©es obtenues via des fenĂȘtres de phishing.
- http:///api/v1/set_error.php â notification d'une erreur survenue.
Recommandations
Pour protéger leurs clients contre la menace des chevaux de Troie mobiles, les entreprises doivent utiliser des solutions globales qui permettent de surveiller et de prévenir les activités malveillantes sans installer de logiciel supplémentaire sur les appareils des utilisateurs.
Pour cela, les mĂ©thodes de dĂ©tection basĂ©es sur des signatures des chevaux de Troie mobiles doivent ĂȘtre renforcĂ©es par des technologies d'analyse comportementale tant du client que de l'application elle-mĂȘme. La protection doit Ă©galement inclure une fonction d'identification des appareils utilisant la technologie d'empreinte digitale, ce qui permettra de comprendre quand un compte est utilisĂ© sur un dispositif atypique et est dĂ©jĂ tombĂ© entre les mains d'un fraudeur.
Un point crucial est la disponibilitĂ© d'une analyse cross-canal, permettant aux entreprises de contrĂŽler les risques apparaissant non seulement du cĂŽtĂ© d'Internet, mais aussi du canal mobile, par exemple, dans les applications de banque mobile, pour les transactions en cryptomonnaie, et dans d'autres domaines oĂč des transactions financiĂšres peuvent avoir lieu.
RÚgles de sécurité pour les utilisateurs :
- ne pas installer d'applications pour dispositifs Android à partir de sources autres que Google Play, et faire particuliÚrement attention aux permissions demandées par l'application ;
- installer réguliÚrement les mises à jour du systÚme Android.
- faire attention aux extensions des fichiers téléchargés;
- ne pas visiter des ressources suspectes;
- ne pas cliquer sur les liens reçus par SMS.
En participant Semena Rogatchev, spécialiste junior en recherche de logiciels malveillants au Laboratoire de criminalistique informatique de Group-IB.
Source : habr.com
