Reverse engineering McAfee Virus Scan - Parte I: L'installer
Con questo articolo voglio riassumere alcuni dettagli che ho trovato durante l’analisi del software McAfee Virus Scan, storicamente parlando, si tratta di uno dei primi antivirus commerciali. Studiarne i dettagli e il funzionamento potrebbe rivelare alcune scelte di progettazione che mostrano come i primi antivirus funzionarono. In particolar modo siamo interessati a capire come avveniva la detection dei malware, nonché alle particolari caratteristiche che il prodotto McAfee offriva.

Ottenere il binario
Il prodotto McAfee Virus Scan è stato uno dei primi antivirus sviluppato dall’omonimo fondatore dell’azienda John McAfee ed è divenuto successivamente il prodotto della McAfee Corporation. Seppur il prodotto venne commercializzato prestissimo (parliamo del 1988 come primo anno di rilascio), è possibile ancora trovarne alcune copie online. Per recuperare uno dei primi binari, sono andato su web.archive.org che dispone di una vasta gamma di archivi di materiali tra cui software, ma anche libri, documenti, film e molto altro.
Il binario a cui siamo interessati si chiama “McAfee Virus Scan” ed è l’installer del prodotto di antivirus, versione pubblicata il 10 ottobre 2002. Dal momento che siamo interessati ad ispezionarne il contenuto, scarichiamo il binario in locale e incominciamo l’analisi del software. Il binario scaricato VSHENU702D30.exe è un archivio autoestraente chiamato “InstallShield self-extracting archive”.
InstallShield è una piattaforma per la creazione di programmi di installazione e distribuzione di software. Sviluppato da Flexera Software, viene utilizzato dalle aziende per creare programmi di installazione per prodotti software. Comunemente parlando, un installer è composto da due principali sezioni. La prima sezione è la serie di informazioni che serve al binario per estrarre il contenuto (e quindi effettivamente installare il software), mentre la seconda sezione è dato dal contenuto stesso (i file che il programma deve installare). In questo caso siamo interessati ad estrarre dal programma il contenuto della suite McAfee.
Come è composto un binario di InstallShield?
Un binario PE (Portable Executable) creato con InstallShield consta di vari elementi:
- il file eseguibile che consente all’utente di installare il software;
- una intestazione con stringa magic
InstallShieldche segue l’ultima sezione del file PE; - una serie di strutture dati per specificare il contenuto dell’installer:
IS_HEADER(InstallShield Header) che consente di recuperare la firma del file, il numero di file, il tipo di instestazione;IS_FILE_ATTRIBUTESche specifica una serie di attributi file secondari (come il nome del file originale, alcune flag - principalmente i permessi);
- il contenuto di ogni file specificato da un offset;
Esempi di strutture dati che possiamo trovare all’interno del binario di InstallShield:
typedef struct IS_HEADER {
char signature[14];
uint16_t num_files;
uint32_t type; // used by "ISSetupStream" format
uint8_t unknown[26];
} IS_HEADER;
dove:
- signature è una sorta di firma del binario, comunemente è “InstallShield” (stringa C codificata ASCII e termina con
\0) - num_files specifica quanti file sono contenuti all’interno dell’installer
- type rappresenta il tipo di file (se è un installer e che tipo di installer,
0per produzione,1per testing e2per sviluppo) - unknown sono una serie di byte di cui si ignora l’utilizzo
Un’altra struttura importante è rappresentata dagli attributi del file.
typedef struct IS_FILE_ATTRIBUTES {
char file_name[_MAX_PATH]; // _MAX_PATH è definito come
uint32_t encoded_flags; // flag come i permessi del file
uint32_t x3;
uint32_t file_len;
uint8_t unknown_2[8];
} IS_FILE_ATTRIBUTES;
dove:
- file_name rappresenta il nome del file
- encoded_flags
- x3: riservato
- file_len è la lunghezza del file
- unknown_2: riservato
Il contenuto di ogni file è compresso utilizzando l’algoritmo LZMA, Lempel Ziv Markov, un algoritmo utilizzato per la compressione dei dati. L’algoritmo LZMA utilizza una codifica tramite un dizionario per memorizzare le occorrenze e i riferimenti ad un pattern di stringhe comuni. L’idea è quella di avere un dizionario che rappresenti le coppie <Stringa, NumeroDiOccorrenze>. Una serie di strutture dati ausiliarie vengono utilizzate per memorizzare l’offset dell’occorrenza. Per saperne di più sulla specifica dell’algoritmo vi consiglio la lettura “LZMA specification”.
L’estrazione dei file viene effettuata tramite questo semplice algoritmo (ricavato tramite IDA Free ❤️ ):
GetTempFileNameA(lpPathName, PrefixString, 0, TempFileName);
v3 = (void *)sub_401756(TempFileName, 33025);
result = -1;
if ( v3 != NULL ){
sub_40182F(v3, lpBuffer, nNumberOfBytesToWrite);
sub_401851(v3);
v5 = LZOpenFileA(TempFileName, &ReOpenBuf, 0);
v6 = LZOpenFileA(lpFileName, &v9, 0x1001u);
v7 = LZCopy(v5, v6);
LZClose(v5);
LZClose(v6);
DeleteFileA(TempFileName);
return v7;
}
I passi dell’algoritmo sono i seguenti:
- Otteniamo il nome del file contenuto nella cartella temporanea
- Creiamo un nuovo file all’interno della cartella temporanea utilizzando
TempFileNamee la routinesub_401756 - Scriviamo il contenuto (compresso) del file attraverso la routine
sub_40182F - Apriamo il file compresso (v5) e il file che andrà ad essere utilizzato per scompattare il contenuto (v6)
- Estriamo il contenuto dal buffer v5 al buffer v6
- Chiudiamo i relativi handle
- Eliminiamo il file temporaneo (conteneva il file compresso incluso nel binario)
È ovviamente possibile estrarre il contenuto del file semplicemente avviando un qualsiasi debugger e impostando diversi breakpoint sulle funzioni di interesse (in questo caso LZOpenFileA e LZCopy).
Dal momento che stiamo lavorando su un installer creato molti anni fa (quasi 21!) le strutture dati dell’installer potrebbero non essere le stesse utilizzate nell’ultima versione di InstallShield. Per estrarre il contenuto del binario non è necessario fare nulla di straordinariamente difficile. È sufficiente eseguire il comando 7z x nome-binario che utilizza il software 7zip: in questo modo possiamo ricavare i binari che andrebbero installati all’interno della cartella C:\Programmi (x86)\McAfee Virus Scan. Il contenuto del binario è il seguente:
[5]SummaryInformation' Binary.EpocDetect.dll Icon.VsMain.exe
'!ActionText' Binary.Exclaim '!IniFile'
'!AdminExecuteSequence' Binary.McAfeeCA.dll '!InstallExecuteSequence'
'!AdminUISequence' Binary.McAfeeCA.Dll.03723396_538B_11D4_B355_00B0D04BB45E '!InstallShield'
'!AdvtExecuteSequence' Binary.McAfeeCA.Dll.E2288E6B_6CA7_11D4_B37B_00B0D04BB45E '!InstallUISequence'
'!AppSearch' Binary.NAILogo_Top.bmp '!LaunchCondition'
'!Binary' Binary.SetAllUsers.dll '!Media'
Binary.ACCEPTLICENSE Binary.side16 '!ModuleComponents'
Binary.AxdistEXE Binary.VSCLogo_Left.bmp '!ModuleDependency'
Binary.Binary20 Binary.VSCTop_NoLogo.bmp '!ModuleSignature'
Binary.Binary21 '!CheckBox' '!MoveFile'
Binary.Binary22 '!Class' '!ProgId'
Binary.Binary23 '!_Columns' '!Property'
Binary.Binary24 '!Component' '!RadioButton'
Binary.Binary25 '!Condition' '!Registry'
Binary.Binary26 '!Control' '!RegLocator'
Binary.Binary27 '!ControlCondition' '!RemoveFile'
Binary.Binary28 '!ControlEvent' '!RemoveRegistry'
Binary.Binary29 '!CreateFolder' '!SelfReg'
Binary.Binary30 '!CustomAction' '!ServiceControl'
Binary.Binary31 Data.Cab '!ServiceInstall'
Binary.Binary32 '!Dialog' '!Shortcut'
Binary.Binary33 '!Directory' '!Signature'
Binary.Binary34 '!DrLocator' '!_StringData'
Binary.Callca_vsc '!Error' '!_StringPool'
Binary.Callca_vsc_nt '!EventMapping' '!_Tables'
Binary.Callimmediate '!Feature' '!TextStyle'
Binary.Callmsi_inst '!FeatureComponents' '!TypeLib'
Binary.Callritual '!File' '!UIText'
Binary.Callwiseapi '!Icon' '!Upgrade'
Binary.DELETE.EXE Icon._B291A24037AB_11D7_BAF5_00B0D0C6893B.exe '!_Validation'
Binary.Dll_.ini Icon._C050255A3944_11D7_99DE_00605B102CFB.exe VSC.msi
Binary.DLLWRAP.DLL Icon.Icon63CB76201.exe
Binary.DontInstall.ico Icon.Icon63CB7620.exe
Come è possibile notare, 7zip ha estratto tutto il contenuto del file binario, comprese alcune informazioni secondarie che specificano alcune impostazioni all’installer. Queste impostazioni sono codificate in una serie di file a cui non siamo interessati (ad esempio '!Dialog o !File). Questi file sono denotati dall’iniziale del nome del file '!: possiamo quindi procedere a spostare/cancellare tali file. Per cancellarli possiamo utilizzare il comando rm \!*. Tutto ciò invece che è possibile ricavare sono i file che rappresentano il programma McAfee Virus Scan.
Successivamente possiamo filtrare i binari per tipo: non vogliamo che la nostra analisi si concentri su file che consentono grafica (icone, immagini). Possiamo quindi eseguire file nome_file per capire meglio la natura del file. I file eseguibili, le librerie e il codice nativo su Windows di solito sono contenuti all’interno del formato file PE e presentano una dicitura molto simile a:
PE32 executable (DLL|GUI) Intel 80386, for MS Windows
Nel prossimo articolo ci focalizzeremo sull’effettuare un primo reverse engineering del motore interno di McAfee per la scansione dei file e delle directory F324_SCAN.EXE. Se avete qualche commento, curiosità o critica, potete scrivermi una e-mail.