Analisi del malware Remcos veicolato tramite packer Delphi

11/03/2019

malware analysis remcos

Remcos è un RAT (Remote Administration Trojan) disponibile in vari forum di cracking, oltre alle caratteristiche funzionalità di un RAT presenta feature più specifiche (come la possibilità di riprodurre file audio) che unite al suo facile utilizzo lo rendono appetibile ai criminali alle prime armi.

Il malware Remcos di per sè non presenta nessun tipo di offuscamento e adotta un rudimentale meccanismo anti VM ed anti debugger, tutto ciò ne rende estremamente facile il reverse engineering e la rilevazione da parte degli antivirus. Per questo motivo Remcos è spesso veicolato tramite un packer (o loader, che dir si voglia) il cui compito è quello di evadere gli antivirus e rilevare la presenza di software antidebug e di VM.

Il malware analizzato utilizza un packer scritto in Delphi, di cui sono note delle varianti, contenente una serie di controlli volti ad integrare le scarse potenzialità di quelli effettuati da Remcos stesso.

Come la maggior parte dei packer anche questo contiene moduli (Unit nel gergo tecnico Pascal/Delphi) per funzionalità benigne, come la GUI, comunicazioni, grafica e simili, per risultare meno sospetti. Le Unit possono contenere del codice di inizializzazione che viene invocato dal runtime Delphi tramite Sysinit.InitExe attraverso una tabella di puntatori a funzioni di inizializzazione.

 

E’ probabile che la funzione di inizializzazione malevola si trovi verso la fine dell’array poichè l’ordine in cui le Unit sono inizializzate dipende dall’ordine in cui esse sono compilate e quest’ordine non è facilmente modificabile in tutti gli IDE Delphi, inoltre mettendo la funzione in fondo all’array tutte le Unit precedenti sono utilizzabili.

Determinare quale funzione di inizializzazione sia quella malevola richiede comunque un’ispezione manuale, potenzialmente di tutti gli elementi dell’array, e la capacità da parte dell’analista di determinare codice scritto da un cracker. Tipicamente l’analista cerca codice che utilizza funzioni sospette (come l’allocazione di aree di memoria RWX, collezione delle informazione sull’utente o sulla macchina, pause artificiali e così via). In questo packer l’evidenza lampante per l’analista è il codice mostrato di seguito che si trova vicino all’inizio della procedura di inizializzazione:

Questo codice… non fa lavora!

ScaleWindowExtEx è chiamata con tutti i parametri NULL, il che di per sè è un’evidenza forte del fatto che il codice non può essere legittimo delle librarie Borland (o affini), inoltre vi è un ciclo che esegue due GdiFlush per iterazione, con lo scopo di effettuare una pausa al fine di far andare in timeout alcune sandbox (l’utilizzo delle API consone a fare pause è facilmente rilevato ed aggirato dalle sandbox moderne).  A conferma del tutto, è presente all’inizio della procedura un controllo sul nome dell’eseguibile; nel caso essi soddisfi la regex SE??\. il packer termina senza procedere con l’infezione.

Sono presenti altri controlli

  • un controllo per il disinnesco del malware che si attiva se è possibile caricare la procedura kCmIWDu43R4o6 dalla DLL qceNiAsWpiiByicQ75wKZH.
  • un controllo antiVM che consiste nell’allocare circa 500MiB di memoria, toccarne ogni pagina e poi deallocarla, alcune sandbox non consentono un tal utilizzo di memoria.
  • un controllo sull’attività dell’utente tramite GetCursorPos ed un semplice algoritmo per determinare se l’utente utilizza il mouse.

Se tutti i controlli vengono soddisfatti, si arriva alla procedura che carica il secondo stadio e lo esegue:

 

Il codice è offuscato banalmente con uno xor (con 0xe3) e si trova al VA 0x469ee0 (dentro la sezione dei dati), dopodichè è facile vedere come l’OEP del codice malevolo sia all’offset 0x8f4.

Dal momento che viene eseguito il codice malevolo non è più necessaria una conoscenza del runtime Delphi, questo semplifica l’analisi. Tuttavia il codice è sparso di salti incondizionali, il che rende difficile seguire il flusso se si adotta una vista sequenziale del codice (il problema può essere risolto con una vista a grafo).

Il codice malevolo è piuttosto lungo ed è impossibile riportarlo per intero in una news, in sintesi le azione compiute sono:

  1. Ottiene gli indirizzi delle API di cui necessita tramite il consueto uso della struttura PEB->Ldr->InLoadOrderModuleList. Per evitare di essere facilmente rilevato dagli AV, la selezione della procedura da importare da una specifica DLL avviene tramite la nota tecnica dell’hash del nome.
  2. Ottiene uno snapshot dei processi in esecuzione (da notare che se è presente un processo il cui nome è più lungo di 64 caratteri, il malware si disinnesca).
  3. Utilizza la funzione foglia 0x40000000 dell’istruzione cpuid (nota: le funzioni foglia da 0x40000000 a 0x4fffffff sono esplicitamente marcate come non implementate nei manuali Intel) per determinare il tipo di VM. Molte VM (VMBox, MS HV, Xen, KVM, PERL HV) utilizzano queste funzioni foglia per ritornare informazioni al guest.
  4. Utilizza la funzione foglia 0 di cpuid per determinare se la marca della CPU corrisponde alle marche fittizie usate dai VMM KVM e Xen.
  5. Controlla se il nome dell’eseguibile è uno tra: malware, sandbox, sample, virus, self (usati da alcune sandbox).
  6. Controlla se nello snapshot del punto 2 sono presenti alcuni processi AV (avastsvc.exe, aavastui.exe, avgsvc.exe, iavgui.exe)
  7. Controlla se nello snapshot del punto 2 sono presenti alcuni processi debugger (exp64.exe, procmon.exe, procmon64.exe, ollydbg.exe, procexp.exe, windbg.exe)
  8. Utilizza le classi non documentate 0x1f (ProcessDebugFlags) e 0x1e (ProcessDebugObjectHandle) di NtQueryInformationProcess per determinare se è presente un debugger.
  9. Il packer accetta 3 argomenti da linea di comando, il primo determina l’azione da eseguire e gli altri sono passati alla procedura scelta. Se il primo argomento inizia con il carattere 1 viene eseguita una procedura che sembra cancellare il file passatogli tramite gli altri argomenti, se inizia con il carattere 2 viene controllato se esiste un processo con un dato PID ed eventualmente rilancia sè stesso. Non sono state fatte analisi approfondite su queste due modalità.
  10. Viene controllato se è stata caricata la DLL SBIEDLL.dll usata dal programma Sandboxie,
  11. Viene controllata la presenza di un debugger tramite i soliti campi del PEB.

Se tutti questi controlli sono soddisfatti il packer inizia a decodificare il payload. Tutta la configurazione del malware avviene tramite i dati codificati nelle risorse:

Le risorse sono codificate tramite un semplice xor a scorrimento, i primi 16 byte della risorsa sono la chiave per lo xor, il resto sono i dati cifrati.

La risorsa con id 1000 è la risorsa che contiene la configurazione principale, in particolare all’offset 0x18 è presente il numero di risorse in cui è diviso il payload, all’offset 0x2e è presente l’ID della prima risorsa del payload. La configurazione contiene svariati parametri che abilitano (o meno) pause, alcuni dei controlli già visti sopra e la chiave per decifrare le risorse del payload (l’algoritmo di cifratura è sempre uno xor a scorrimento ma non tutta la risorsa è usata, solo un pezzo la cui grandezza è indicata dalla configurazione).

Il risultato finale è il PE del RAT Remcos

Anzichè essere lanciato direttamente il packer utilizza la tecnica del Process Hollowing: lancia una copia di sè stesso in stato sospeso, rimuove tutte le aree di memoria allocate dal loader di Windows dal processo sospeso e vi rimappa le sezioni del payload, dopodichè riprende l’esecuzione del thread principale.

 

Il packer in fine termina l’esecuzione.

Il payload finale è quindi Remcos, un’analisi di questi è stata già effettuata dalla comunità. Il malware è facilmente identificabile:

Remcos non presenta difficoltà per l’analista (salvo il fatto di essere scritto in C++), ci limitiamo quindi ad esporre brevemente le sue funzionalità e la configurazione del caso specifico incontrato dal CERT-PA. La configurazione del malware si trova nella risorsa cifrata SETTINGS e contiene, tra l’altro, la lista dei C&C con relativa password per comunicazioni cifrate (in RC4):

Tra le funzionalità riscontrate sono presenti

  • Keylogger (con incluso titolo della finestra in foreground)
  • Autostart tramite le usuali chiavi di registro (Run, Policies\Explorer\Run, Explorer\User Shell Folders, Winlogon, Software\Classes\mscfile\shell\open\command)
  • Screenshot, Cattura da fotocamera, Cattura da microfono, riproduzione audio
  • Disabilitazione UAC
  • Rilevazione VMBox tramite chiave HARDWARE\acpi\dsdt\vbox__
  • Rilevazione Process Monitor
  • Funzioni per lo spegnimento, sospensione, riavvio del computer
  • Ping all’indirizzo locale per ottenere informazioni sull’host
  • Furto dei DB delle credenziali di Firefox e Chrome
  • Funzionalità per interagire con processi e finestre (creazione, chiusura e simili)
  • Upload, Download ed esecuzione di file
  • Funzionalità per la gestione del registro di sistema
  • Possibilità di cercare file nel computer della vittima

data la semplicità di Remcos, l’onere di scrivere un report più dettagliato è lasciato come compito per il lettore. Di seguito sono riportati due estratti a titolo illustrativo (uno della connessione al C&C e uno scorcio del ciclo dei comandi):

 

Indicatori di compromissione

IoC (.txt) – File globale : Domini, hash files (SHA1, MD5 e SHA256), IPv4

Indicatori di compromissione aggiornati

IoC (.txt) – File globale : Domini, hash files (SHA1, MD5 e SHA256), IPv4