Reverse engineering McAfee Virus Scan - Parte I: L'installer

17 agosto 2023 – 6 min – 1159 parole

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.

Screenshot di VirusScan Console

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:

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:

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:

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:

  1. Otteniamo il nome del file contenuto nella cartella temporanea
  2. Creiamo un nuovo file all’interno della cartella temporanea utilizzando TempFileName e la routine sub_401756
  3. Scriviamo il contenuto (compresso) del file attraverso la routine sub_40182F
  4. Apriamo il file compresso (v5) e il file che andrà ad essere utilizzato per scompattare il contenuto (v6)
  5. Estriamo il contenuto dal buffer v5 al buffer v6
  6. Chiudiamo i relativi handle
  7. 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.