
Proprio nei giorni scorsi, Group-IB l'attività del trojan mobile Android Gustuff. Questo malware opera esclusivamente sui mercati internazionali, prendendo di mira i clienti delle 100 maggiori banche straniere, utenti di 32 portafogli crypto, oltre a grandi risorse e-commerce. Il suo sviluppatore, Gustuff, è un criminale informatico di lingua russa sotto il nickname Bestoffer. Recentemente, ha descritto il suo trojan come un «prodotto serio per persone con conoscenze e competenze».
Uno specialista in analisi del malware di Group-IB Ivan Pisarev nel suo studio descrive in dettaglio il funzionamento di Gustuff e la sua pericolosità.
Cosa attacca Gustuff
Gustuff appartiene a una nuova generazione di malware con funzionalità completamente automatizzate. Secondo lo sviluppatore, il trojan è una nuova e migliorata versione del malware AndyBot, che da novembre 2017 attacca i telefoni con sistema operativo Android e ruba denaro tramite moduli web di phishing che si mascherano da applicazioni mobili di banche internazionali ben note e sistemi di pagamento. Bestoffer ha dichiarato che il costo di affitto del «Gustuff Bot» era di $800 al mese.
L'analisi del campione di Gustuff ha mostrato che il trojan potrebbe colpire i clienti che utilizzano le app mobili delle maggiori banche, come Bank of America, Bank of Scotland, J.P. Morgan, Wells Fargo, Capital One, TD Bank, PNC Bank, così come i portafogli crittografici Bitcoin Wallet, BitPay, Cryptopay, Coinbase e altri.
Originariamente creato come un classico trojan bancario, nella versione attuale Gustuff ha notevolmente ampliato la lista degli obiettivi potenziali. Oltre alle app Android delle banche, delle aziende fintech e dei servizi crittografici, Gustuff prende di mira gli utenti di app di marketplace, negozi online, sistemi di pagamento e messaggistica. In particolare, PayPal, Western Union, eBay, Walmart, Skype, WhatsApp, Gett Taxi, Revolut e altri.
Punto di ingresso: mirato a una diffusione di massa
Gustuff si caratterizza per un approccio "classico" di infiltrazione nei dispositivi Android tramite SMS contenenti link ad APK. Una volta che un dispositivo Android è infettato dal trojan, per comando del server, Gustuff può diffondersi ulteriormente attraverso la rubrica dei contatti del telefono infetto o attraverso il database del server. Le funzionalità di Gustuff sono progettate per un'infezione di massa e una massimizzazione del profitto per i suoi operatori: è presente una funzione unica di "auto-inserimento" in legittime applicazioni bancarie mobili e portafogli criptati, che consente di accelerare e scalare il furto di denaro.
Lo studio del trojan ha mostrato che la funzione di auto-inserimento è implementata mediante il servizio Accessibility Service, progettato per persone con disabilità. Gustuff non è il primo trojan a eludere con successo le protezioni contro l'interazione con gli elementi delle finestre di altre applicazioni grazie a questo servizio di Android. Tuttavia, l'uso dell'Accessibility Service insieme all'auto-inserimento rimane ancora un fenomeno piuttosto raro.
Dopo il caricamento sul telefono della vittima, Gustuff, usando il Servizio di Accessibilità, ottiene la possibilità di interagire con gli elementi delle finestre di altre applicazioni (bancarie, di criptovalute, così come applicazioni per shopping online, messaggistica e altro), eseguendo le azioni necessarie per i malintenzionati. Ad esempio, su comando del server, il trojan può premere pulsanti e modificare i valori nei campi di testo delle applicazioni bancarie. L'uso del meccanismo del Servizio di Accessibilità consente al trojan di bypassare i meccanismi di protezione utilizzati dalle banche per contrastare i trojan mobili di generazione precedente, così come le modifiche nella politica di sicurezza implementate da Google nelle nuove versioni del sistema operativo Android. Così, Gustuff "sa" disattivare la protezione di Google Protect: secondo le affermazioni dell'autore, questa funzione si attiva nel 70% dei casi.

Inoltre, Gustuff può mostrare notifiche PUSH false con icone di legittime app mobili. L'utente clicca sulla notifica PUSH e vede una finestra di phishing caricata dal server, dove inserisce autonomamente i dati della propria carta di credito o del portafoglio crypto richiesti. In un altro scenario d'uso di Gustuff, si apre l'applicazione da cui è stata mostrata la notifica PUSH. In questo caso, il malware, su comando del server tramite Accessibility Service, può compilare i campi del modulo dell'app bancaria per eseguire una transazione fraudolenta.
Le funzionalità di Gustuff includono anche l'invio al server di informazioni sul dispositivo infetto, la possibilità di leggere/inviare messaggi SMS, l'invio di richieste USSD, l'avvio di un proxy SOCKS5, il passaggio a un link, l'invio di file (inclusi fotocopie di documenti, screenshot, fotografie) al server e il ripristino del dispositivo alle impostazioni di fabbrica.
Analisi del malware
Prima dell'installazione dell'applicazione malevola, il sistema operativo Android mostra all'utente una finestra contenente un elenco dei permessi richiesti da Gustuff:

L'installazione dell'applicazione avverrà solo dopo aver ottenuto il consenso dell'utente. Dopo l'avvio dell'app, il trojan mostrerà all'utente una finestra:

Dopo di che, cancellerà la sua icona.
Gustuff è impacchettato, secondo l'autore, da un pacchetto FTT. Dopo l'avvio, l'applicazione si collega periodicamente al server CnC per ricevere comandi. In alcuni file che abbiamo analizzato, l'indirizzo IP utilizzato come server di controllo era 88.99.171[.]105 (da ora in poi indicato come <%CnC%>).
Dopo l'avvio, il programma inizia a inviare messaggi al server http:///api/v1/get.php.
Come risposta ci si aspetta un JSON nel seguente formato:
{
"results": "OK",
"command":{
"id": "",
"command":"",
"timestamp":"",
"params":{
},
},
}Ad ogni richiesta, l'applicazione invia informazioni sul dispositivo infetto. Il formato del messaggio è riportato di seguito. È importante notare che i campi full, extra, app e permission sono opzionali e saranno inviati solo in caso di richiesta di comando da parte del CnC.
{
"info":
{
"info":
{
"cell":<%Sim operator name%>,
"country":<%Country ISO%>,
"imei":<%IMEI%>,
"number":<%Phone number%>,
"line1Number":<%Phone number%>,
"advertisementId":<%ID%>
},
"state":
{
"admin":<%Has admin rights%>,
"source":<%String%>,
"needPermissions":<%Application needs permissions%>,
"accesByName":<%Boolean%>,
"accesByService":<%Boolean%>,
"safetyNet":<%String%>,
"defaultSmsApp":<%Default Sms Application%>,
"isDefaultSmsApp":<%Current application is Default Sms Application%>,
"dateTime":<%Current date time%>,
"batteryLevel":<%Battery level%>
},
"socks":
{
"id":<%Proxy module ID%>,
"enabled":<%Is enabled%>,
"active":<%Is active%>
},
"version":
{
"versionName":<%Package Version Name%>,
"versionCode":<%Package Version Code%>,
"lastUpdateTime":<%Package Last Update Time%>,
"tag":<%Tag, default value: "TAG"%>,
"targetSdkVersion":<%Target Sdk Version%>,
"buildConfigTimestamp":1541309066721
},
},
"full":
{
"model":<%Device Model%>,
"localeCountry":<%Country%>,
"localeLang":<%Locale language%>,
"accounts":<%JSON array, contains from "name" and "type" of accounts%>,
"lockType":<%Type of lockscreen password%>
},
"extra":
{
"serial":<%Build serial number%>,
"board":<%Build Board%>,
"brand":<%Build Brand%>,
"user":<%Build User%>,
"device":<%Build Device%>,
"display":<%Build Display%>,
"id":<%Build ID%>,
"manufacturer":<%Build manufacturer%>,
"model":<%Build model%>,
"product":<%Build product%>,
"tags":<%Build tags%>,
"type":<%Build type%>,
"imei":<%imei%>,
"imsi":<%imsi%>,
"line1number":<%phonenumber%>,
"iccid":<%Sim serial number%>,
"mcc":<%Mobile country code of operator%>,
"mnc":<%Mobile network codeof operator%>,
"cellid":<%GSM-data%>,
"lac":<%GSM-data%>,
"androidid":<%Android Id%>,
"ssid":<%Wi-Fi SSID%>
},
"apps":{<%List of installed applications%>},
"permission":<%List of granted permissions%>
} Memorizzazione delle configurazioni
Gustuff memorizza informazioni importanti per il funzionamento in un file di preferenze. Il nome del file, così come i nomi dei parametri al suo interno, è il risultato del calcolo dell'hash MD5 della stringa 15413090667214.6.1, dove <%name%> — valore di origine nome-valore. Interpretazione Python della funzione di generazione del nome:
nameGenerator(input):
output = md5("15413090667214.6.1" + input) In seguito ci riferiremo come nameGenerator(input).
Pertanto, il nome del primo file è: nameGenerator(«API_SERVER_LIST»), esso contiene valori con i seguenti nomi:
| Nome della variabile | Significato |
|---|---|
| nameGenerator(«API_SERVER_LIST») | Contiene un elenco di indirizzi CnC sotto forma di array. |
| nameGenerator(«API_SERVER_URL») | Contiene l'indirizzo CnC. |
| nameGenerator(«SMS_UPLOAD») | Il flag di default è impostato. Se il flag è attivato, invia SMS al CnC. |
| nameGenerator(«SMS_ROOT_NUMBER») | Numero di telefono al quale saranno inviati gli SMS ricevuti dall'unità infetta. Di default è null. |
| nameGenerator(«SMS_ROOT_NUMBER_RESEND») | Il flag di default è disattivato. Se abilitato, quando l'unità infetta riceve un SMS, sarà inviato al numero root. |
| nameGenerator(«DEFAULT_APP_SMS») | Il flag di default è disattivato. Se questo flag è attivato, l'applicazione elaborerà i messaggi SMS in arrivo. |
| nameGenerator(«DEFAULT_ADMIN») | Il flag predefinito è stato resettato. Se il flag è impostato, l'applicazione ha diritti di amministratore. |
| nameGenerator(«DEFAULT_ACCESSIBILITY») | Il flag predefinito è stato resettato. Se il flag è impostato, il servizio che utilizza il servizio di accessibilità è attivo. |
| nameGenerator(«APPS_CONFIG») | Oggetto JSON che contiene un elenco di azioni da eseguire al verificarsi di un evento di accessibilità legato a un'applicazione specifica. |
| nameGenerator(«APPS_INSTALLED») | Memorizza un elenco delle applicazioni installate sul dispositivo. |
| nameGenerator(«IS_FIST_RUN») | Il flag viene resettato al primo avvio. |
| nameGenerator(«UNIQUE_ID») | Contiene un identificatore unico. Viene generato al primo avvio del bot. |
Modulo di elaborazione comandi dal server
L'applicazione memorizza gli indirizzi dei server CnC come un array di stringhe codificate in Base85 L'elenco CnC può essere modificato all'arrivo di un comando adeguato, in tal caso gli indirizzi saranno memorizzati nel file di preferenze. server In risposta a una richiesta, il server invia un comando all'applicazione. Vale la pena notare che i comandi e i parametri sono presentati in formato JSON. L'applicazione può elaborare i seguenti comandi:
forwardStart
| Team | Descrizione |
|---|---|
| Iniziare l'invio degli SMS ricevuti dal dispositivo infetto al server CnC. | Iniziare l'invio degli SMS ricevuti dal dispositivo infetto al server CnC. |
| forwardStop | Interrompi l'invio dei messaggi SMS ricevuti dal dispositivo infetto al server CnC. |
| ussdRun | Esegui una richiesta USSD. Il numero al quale deve essere effettuata la richiesta USSD si trova nel campo JSON "number". |
| sendSms | Invia un SMS (il messaggio verrà suddiviso in parti se necessario). Come parametro, il comando accetta un oggetto JSON contenente i campi "to" — numero di destinazione e "body" — corpo del messaggio. |
| sendSmsAb | Invia SMS (il messaggio verrà suddiviso in parti se necessario) a tutti i contatti del dispositivo infetto. L'intervallo tra l'invio dei messaggi è di 10 secondi. Il corpo del messaggio si trova nel campo JSON "body". |
| sendSmsMass | Invia SMS (il messaggio verrà suddiviso in parti se necessario) ai contatti specificati nei parametri del comando. L'intervallo tra l'invio dei messaggi è di 10 secondi. Come parametro, il comando accetta un array JSON (campo "sms"), i cui elementi contengono i campi "to" — numero di destinazione e "body" — corpo del messaggio. |
| changeServer | Questo comando può accettare il valore con la chiave «url» come parametro, in tal caso il bot modificherà il valore di nameGenerator(“SERVER_URL”), oppure «array» — in tal caso il bot registrerà un array in nameGenerator(“API_SERVER_LIST”). In questo modo, l'applicazione modifica l'indirizzo dei server CnC. |
| adminNumber | Il comando è destinato a lavorare con il numero root. Il comando accetta un oggetto JSON con i seguenti parametri: «number» — modifica nameGenerator(“ROOT_NUMBER”) al valore ricevuto, «resend» — modifica nameGenerator(“SMS_ROOT_NUMBER_RESEND”), «sendId» — invia a nameGenerator(“ROOT_NUMBER”) uniqueID. |
| updateInfo | Invia al server informazioni sul dispositivo infetto. |
| wipeData | Il comando è destinato a eliminare i dati dell'utente. A seconda di quale nome è stato utilizzato per avviare l'applicazione, si eseguirà la cancellazione completa dei dati con il riavvio del dispositivo (primary user) oppure l'eliminazione solo dei dati dell'utente (secondary user). |
| socksStart | Avviare il modulo Proxy. Il funzionamento del modulo è descritto in una sezione separata. |
| socksStop | Interrompere il funzionamento del modulo Proxy. |
| openLink | Vai al link. Il link si trova nel parametro JSON con la chiave «url». Per aprire il link si utilizza «android.intent.action.VIEW». |
| uploadAllSms | Invia al server tutti i messaggi SMS ricevuti dal dispositivo. |
| uploadAllPhotos | Invia all'URL l'immagine del dispositivo infetto. L'URL arriva come parametro. |
| uploadFile | Invia all'URL un file dal dispositivo infetto. L'URL arriva come parametro. |
| uploadPhoneNumbers | Invia al server i numeri di telefono dall'elenco dei contatti. Se come parametro arriva un oggetto JSON con la chiave "ab", l'app riceve l'elenco dei contatti dalla rubrica del telefono. Se come parametro arriva un oggetto JSON con la chiave "sms", l'app legge l'elenco dei contatti dai mittenti dei messaggi SMS. |
| changeArchive | L'app carica un file dall'indirizzo che arriva come parametro con la chiave "url". Il file caricato viene salvato con il nome "archive.zip". Successivamente, l'app decomprime il file, utilizzando eventualmente la password per l'archivio "b5jXh37gxgHBrZhQ4j3D". I file decompressi vengono salvati nella directory [external storage]/hgps. In questa directory, l'app memorizza le web-fake (descritto di seguito). |
| azioni | Il comando è destinato a lavorare con il Action Service, descritto in una sezione separata. |
| test | Non fa nulla. |
| download | Il comando è progettato per scaricare un file da un server remoto e salvarlo nella directory «Downloads». L'URL e il nome del file vengono forniti come parametri, rispettivamente nei campi del JSON-oggetto: «url» e «fileName». |
| rimuovi | Rimuove un file dalla directory «Downloads». Il nome del file viene fornito nel parametro JSON con la chiave «fileName». Il nome standard del file è «tmp.apk». |
| notification | Mostra una notifica con testi di descrizione e titolo determinati dal server di gestione. |
Formato del comando notification:
{
"results" : "OK",
"command":{
"id": <%id%>,
"command":"notification",
"timestamp":<%Server Timestamp%>,
"params":{
"openApp":<%Open original app or not%>,
"array":[
{"title":<%Title text%>,
"desc":<%Description text%>,
"app":<%Application name%>}
]
},
},
}La notifica creata dal file esaminato appare identica alle notifiche generate dall'applicazione specificata nel campo app. Se il valore del campo openApp è True, quando viene aperta la notifica si avvia l'applicazione specificata nel campo app. Se il valore del campo openApp è False, quindi:
- si apre una finestra di phishing, il cui contenuto viene caricato dalla directory /hgps/
- si apre una finestra di phishing, il cui contenuto viene caricato dal server ?id=&app=
- si apre una finestra di phishing mascherata da Google Play Card, con la possibilità di inserire i dati della carta.
Il risultato dell'esecuzione di ogni comando viene inviato all' set_state.php in formato JSON del seguente tipo:
{
"command":
{
"command":,
"id":,
"state":
}
"id":
} ActionsService
L'elenco dei comandi che l'applicazione gestisce include action. Al ricevimento di un comando, il modulo di elaborazione dei comandi contatta questo servizio per eseguire il comando esteso. Il servizio accetta come parametro un oggetto JSON. Il servizio può eseguire i seguenti comandi:
1. PARAMS_ACTION — al ricevimento di tale comando, il servizio ottiene innanzitutto dal parametro JSON il valore della chiave Type, che può essere uno dei seguenti:
- serviceInfo – il sottocomando ottiene dal parametro JSON il valore della chiave includeNotImportant. Se il flag è impostato su True, l'applicazione imposta il flag FLAG_ISOLATED_PROCESS sul servizio che utilizza Accessibility Service. In questo modo, il servizio verrà avviato in un processo separato.
- root — ottenere e inviare al server informazioni sulla finestra attualmente in focus. L'applicazione riceve le informazioni tramite la classe AccessibilityNodeInfo.
- admin — richiedere i diritti di amministratore.
- ritardo — sospendere il funzionamento di ActionsService per il numero di millisecondi specificato nel parametro con la chiave «data».
- windows — inviare un elenco delle finestre visibili all'utente.
- install — installare l'applicazione su un dispositivo compromesso. Il nome del pacchetto si trova nella chiave «fileName». L'archivio si trova nella cartella Downloads.
- global – il comando secondario è destinato a passare dalla finestra attuale:
- al menu Impostazioni rapide
- indietro
- alla home
- alle notifiche
- alla finestra delle applicazioni recentemente aperte
- lancia — avviare l'applicazione. Il nome dell'applicazione viene fornito come parametro con la chiave data.
- suoni — cambiare la modalità del suono in silenzio.
- sblocca — accende la retroilluminazione dello schermo e della tastiera alla massima luminosità. L'applicazione esegue questa azione tramite WakeLock, indicando come tag la stringa [Application lable]:INFO
- overlayPermessi — funzione non implementata (risposta all'esecuzione del comando — {«message»:«Not support»} o {«message»:«low sdk»})
- gesto — funzione non implementata (risposta all'esecuzione del comando — {«message»:«Not support»} oppure {«message»:«Low API»})
- autorizzazioni — questo comando è necessario per richiedere i permessi per l'applicazione. Tuttavia, la funzione di richiesta non è implementata, quindi il comando non ha senso. L'elenco dei permessi richiesti arriva come array JSON con la chiave «permissions». Elenco 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 — visualizzare una finestra phishing. In base al parametro ricevuto dal server, l'app potrebbe mostrare le seguenti finestre phishing:
- Mostra una finestra phishing, il cui contenuto è specificato nel file nella directory /hgps/. Il risultato dell'interazione dell'utente con la finestra sarà inviato all'indirizzo /records.php
- Mostra una finestra phishing, il cui contenuto viene caricato preventivamente dall'indirizzo ?id=&app=. Il risultato dell'interazione dell'utente con la finestra sarà inviato all'indirizzo /records.php
- Mostra una finestra phishing mascherata da Google Play Card.
- interactive — il team è progettato per interagire con gli elementi delle finestre di altre applicazioni tramite AccessibilityService. Per l'interazione, è stato implementato un servizio specifico. L'applicazione in esame può interagire con le finestre:
- Attivo al momento. In tal caso, il parametro contiene id o text (nome) dell'oggetto con cui è necessario interagire.
- Visibili all'utente al momento dell'esecuzione del comando. L'applicazione seleziona le finestre per id.
Ottenuti gli oggetti AccessibilityNodeInfo per gli elementi di interesse nella finestra, l'applicazione può eseguire azioni a seconda dei parametri:
- focus — impostare il focus sull'oggetto.
- click — fare clic sull'oggetto.
- actionId — eseguire un'azione tramite ID.
- setText — modificare il testo dell'oggetto. La modifica del testo è possibile in due modi: eseguendo l'azione ACTION_SET_TEXT (se la versione di Android del dispositivo infetto è inferiore o uguale a LOLLIPOP), oppure copiando una stringa negli appunti e incollandola nell'oggetto (per versioni superiori). Questo comando può essere utilizzato per cambiare i dati in un'applicazione bancaria.
2. PARAMS_ACTIONS — lo stesso di PARAMS_ACTION, solo che riceve un array JSON di comandi.
Sembra che a molti interesserà vedere come si presenta la funzione di interazione con gli elementi di una finestra di un altro applicativo. Questa è la modalità in cui è stata implementata tale funzionalità in 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));
}Funzione di sostituzione del testo:
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;
}Pertanto, con una corretta configurazione del server di gestione, Gustuff è in grado di compilare i campi di testo in un'app bancaria e premere i pulsanti necessari per completare le transazioni. Il trojan non ha nemmeno bisogno di autenticarsi nell'app — basta inviare un comando per visualizzare una notifica PUSH e quindi aprire l'app bancaria precedentemente installata. L'utente eseguirà l'autenticazione, dopo di che Gustuff sarà in grado di effettuare l'autofill.
Modulo di elaborazione SMS
L'applicazione imposta un gestore di eventi per ricevere messaggi SMS da dispositivi infetti. L'applicazione in esame può ricevere comandi dall'operatore, che arrivano nel corpo del messaggio SMS. I comandi arrivano nel formato:
7!5=<%Base64 encoded command%>
L'applicazione cerca in tutti i messaggi SMS in arrivo la stringa 7!5=, e se trova la stringa – decodifica la stringa da Base64 con uno spostamento di 4 e esegue il comando. I comandi sono simili ai comandi CnC. Il risultato dell'esecuzione viene inviato al stesso numero da cui è arrivato il comando. Il formato della risposta:
7*5=<%Base64 encode of «result_code command»%>
Facoltativamente, l'applicazione può inviare tutti i messaggi ricevuti a un numero Root. Per fare ciò, nel file delle preferenze deve essere specificato il numero Root e deve essere attivato il flag di reindirizzamento dei messaggi. Il messaggio SMS viene inviato al numero dell'attaccante nel formato:
—
Inoltre, opzionalmente, l'applicazione può inviare messaggi a CnC. Il messaggio SMS viene inviato al server in formato JSON:
{
"id":,
"sms":
{
"text":,
"number":,
"date":
}
}Se è attivato il flag nameGenerator(«DEFAULT_APP_SMS») – l'applicazione interrompe l'elaborazione dei messaggi SMS e svuota l'elenco dei messaggi in arrivo.
Modulo Proxy
Nell'applicazione analizzata è presente un modulo Backconnect Proxy (di seguito chiamato Modulo Proxy), che ha una classe separata contenente campi statici con la configurazione. I dati di configurazione sono memorizzati nel campione in chiaro:

Tutte le azioni effettuate dal Modulo Proxy vengono registrate in file. A tal fine, l'applicazione crea nella Memoria Esterna una directory chiamata «logs» (campo ProxyConfigClass.logsDir nella classe di configurazione), in cui vengono memorizzati i file di log. La registrazione avviene in file con i nomi:
- main.txt – in questo file viene registrato il funzionamento della classe chiamata CommandServer. In seguito, registrando la stringa str in questo file la chiameremo mainLog(str).
- session-<%id%>.txt – in questo file vengono salvati i dati di log relativi a una specifica sessione di proxy. In seguito, registrando la stringa str in questo file la chiameremo sessionLog(str).
- server.txt – in questo file viene registrato tutti i dati scritti nei file sopra descritti.
Formato dei dati di log:
<%Date%> [Thread[<%thread id%>], id[]]: log-string
Le eccezioni che si verificano durante l'operazione del modulo Proxy vengono registrate in un file. A tal fine, l'applicazione genera un oggetto JSON nel seguente formato:
{
"uncaughtException":<%short description of throwable%>
"thread":<%thread%>
"message":<%detail message of throwable%>
"trace": //Stack trace info
[
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
},
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
}
]
}Successivamente, converte questo in una rappresentazione stringa e lo registra.
L'avvio del modulo Proxy avviene dopo la ricezione del comando appropriato. Al ricevimento del comando per avviare il modulo Proxy, l'applicazione avvia il servizio chiamato MainService, che è responsabile della gestione del funzionamento del modulo Proxy – avvio e arresto.
Fasi di avvio del servizio:
1. Avvia un timer che scatta ogni minuto e verifica l'attività del modulo Proxy. Se il modulo non è attivo, lo avvia.
Inoltre, quando si verifica l'evento android.net.conn.CONNECTIVITY_CHANGE viene avviato il modulo Proxy.
2. L'applicazione crea un wake-lock con il parametro PARTIAL_WAKE_LOCK e lo acquisisce. In questo modo impedisce al CPU del dispositivo di entrare in modalità sospensione.
3. Avvia la classe di gestione dei comandi del modulo Proxy, registrando prima la stringa mainLog("start server") e
Server::start() host[], commandPort[], proxyPort[]
dove proxy_cnc, command_port e proxy_port – parametri ottenuti dalla configurazione del server Proxy.
La classe di gestione dei comandi si chiama CommandConnection. Subito dopo l'avvio esegue le seguenti azioni:
4. Si connette a ProxyConfigClass.host: ProxyConfigClass.commandPort e invia lì i dati sul dispositivo compromesso in formato JSON:
{
"id":,
"imei":,
"imsi":,
"model":,
"manufacturer":,
"androidVersion":,
"country":,
"partnerId":,
"packageName":,
"networkType":,
"hasGsmSupport":,
"simReady":,
"simCountry":,
"networkOperator":,
"simOperator":,
"version":
}Dove:
- id – identificatore, cerca di ottenere dal file di preferenze condivise un valore con il campo "id" da un file chiamato "x". Se non riesce a ottenere questo valore, genera uno nuovo. In questo modo, il modulo Proxy ha il suo identificatore, generato in modo simile all'ID del Bot.
- imei — IMEI del dispositivo. Se si verifica un errore durante il recupero del valore, verrà registrato un messaggio di errore in questo campo.
- imsi — International Mobile Subscriber Identity del dispositivo. Se si verifica un errore durante il recupero del valore, verrà registrato un messaggio di errore in questo campo.
- model — Il nome visibile per l'utente finale del prodotto finale.
- manufacturer — Il produttore del prodotto/hardware (Build.MANUFACTURER).
- androidVersion — stringa nel formato « (),»
- country — posizione attuale del dispositivo.
- partnerId – stringa vuota.
- packageName – nome del pacchetto.
- networkType — tipo di connessione di rete attuale (esempio: «WIFI», «MOBILE»). In caso di errore restituisce null.
- hasGsmSupport – true – se il telefono supporta GSM, altrimenti false.
- simReady – stato della SIM.
- simCountry — codice ISO del paese (basato sul provider della SIM).
- networkOperator — nome dell'operatore. Se si verifica un errore durante il recupero del valore, verrà registrato un messaggio di errore in questo campo.
- simOperator — The Service Provider Name (SPN). Se si verifica un errore durante il recupero del valore, verrà registrato un messaggio di errore in questo campo.
- version — questo campo è memorizzato nella classe di configurazione, per le versioni del bot analizzate era pari a "1.6".
5. Passa alla modalità di attesa dei comandi dal server. I comandi dal server arrivano nel formato:
- 0 offset – comando
- 1 offset – sessionId
- 2 offset – lunghezza
- 4 offset — dati
All'arrivo di un comando l'applicazione registra:
mainLog("Header { sessionId, type, length }")
Sono possibili i seguenti comandi dal server:
| Name | Comando | Data | Descrizione |
|---|---|---|---|
| connectionId | 0 | Connection ID | Creare una nuova connessione |
| SLEEP | 3 | Tempo | Sospendere il funzionamento del modulo Proxy |
| PING_PONG | 4 | — | Inviare un messaggio PONG |
Un messaggio PONG consiste di 4 byte e appare come segue: 0x04000000.
All'arrivo del comando connectionId (per creare una nuova connessione) CommandConnection crea un'istanza della classe ProxyConnection.
- Nella proxying sono coinvolte due classi: ProxyConnection e end. Durante la creazione della classe ProxyConnection si connette all'indirizzo ProxyConfigClass.host: ProxyConfigClass.proxyPort e trasmette l'oggetto JSON:
{
"id":
}In risposta il server invia un messaggio SOCKS5, che contiene l'indirizzo del server remoto con cui è necessario stabilire la connessione. L'interazione con questo server avviene tramite la classe end. Linearmente, l'instaurazione della connessione può essere rappresentata come segue:

Interazioni di rete
Per prevenire l'analisi del traffico da parte di sniffatori di rete, l'interazione tra il server CnC e l'applicazione può essere protetta tramite il protocollo SSL. Tutti i dati trasmessi sia dal server che verso il server sono presentati in formato JSON. Durante il suo funzionamento, l'applicazione esegue le seguenti richieste:
- http:///api/v1/set_state.php — risultato dell'esecuzione del comando.
- http:///api/v1/get.php — ricezione del comando.
- http:///api/v1/load_sms.php — estrazione degli SMS dal dispositivo compromesso.
- http:///api/v1/load_ab.php — estrazione dell'elenco dei contatti dal dispositivo compromesso.
- http:///api/v1/aevents.php – richiesta effettuata durante l'aggiornamento delle impostazioni presenti nel file di preferenze.
- http:///api/v1/set_card.php — estrazione dei dati ottenuti tramite una finestra di phishing che si maschera da Google Play Market.
- http:///api/v1/logs.php – estrazione dei dati di log.
- http:///api/v1/records.php – estrazione dei dati ottenuti tramite finestre di phishing.
- http:///api/v1/set_error.php – notifica di errore verificatosi.
Raccomandazioni
Per proteggere i propri clienti dalla minaccia dei trojan mobili, le aziende devono adottare soluzioni complete che consentano di monitorare e prevenire attività dannose senza la necessità di installare software aggiuntivo sui dispositivi degli utenti.
A tal fine, i metodi basati su firme per l'individuazione dei trojan mobili devono essere potenziati con tecnologie di analisi comportamentale sia del cliente che dell'app stessa. Inoltre, la protezione deve includere una funzione di identificazione dei dispositivi utilizzando la tecnologia delle impronte digitali, che permette di rilevare quando un account viene utilizzato su un dispositivo non tipico e che potrebbe essere caduto nelle mani di un truffatore.
Un aspetto cruciale è la possibilità di un'analisi cross-channel, che consente alle aziende di controllare i rischi che si presentano non solo attraverso il canale internet, ma anche quello mobile, ad esempio nelle app di mobile banking, nelle transazioni di criptovalute e in qualsiasi altro contesto in cui possa avvenire una transazione finanziaria.
Regole di sicurezza per gli utenti:
- non installare applicazioni per dispositivi mobili con sistema operativo Android da fonti diverse da Google Play, prestare particolare attenzione ai permessi richiesti dall'applicazione;
- installare regolarmente gli aggiornamenti del sistema operativo Android;
- prestare attenzione alle estensioni dei file scaricati;
- non visitare risorse sospette;
- non seguire i link ricevuti nei messaggi SMS.
Partecipazione Semena Rogacheva, specialista junior nella ricerca di codice malevolo del Laboratorio di criminalistica informatica Group-IB.
Fonte: habr.com
