Minima Anonyma Tabularia Ex Reti

nihil vacuum neque sine signo apud MATER

Liber Tertius

 

 

Salve, vera Turingus 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 ! 

 

 

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)

 

 

 

 § MATER Liber Tertius §

 

Editoriale # 1

Innanzitutto grazie a tutti.

MATER ha ricevuto un'accoglienza calorosa e di questo ve ne siamo grati. Abbiamo ricevuto auguri da amici, incoraggiamenti da conoscenti e fuggevoli saluti da surfnetisti solitari. Molte sono state le domande,e per evitare in futuro imbarazzanti incomprensioni, proviamo a rispondere ad alcune di esse.Vari ad esempio ci hanno chiesto chi siamo cosa facciamo.

Vediamo un po' cosa è questa nebulosa Familia. Familia NON è un gruppo di virusvriters o di pirati informatici o, come qualcuno, utilizzando erroneamente il termine, definisce Hackers. Familia è un gruppo composto da studiosi del software, il cui interesse comune è accrescere la propria conoscenza relativa alle tecniche virali. I virus ci interessano  per il loro contenuto tecnico e non per i loro effetti. La nostra attività è lo studio. Non abbiamo alcun interesse a creare o diffondere nuovi virus. Anzi, in questo senso la nostra attività potrebbe essere assimilata,  guarda un po', più ad una casa di AV.

Di conseguenza qui non troverete codice virale inedito, né metodi per crakkare programmi o penetrare in siti senza autorizzazione. MATER, e qui qualcuno storcerà il naso, non contiene materiale nuovo: questa zine si limita a raccogliere, vagliare, analizzare. Niente nuovi sorgenti, quindi, ma nuovi commenti e relazioni. Non la distruzione di dati, ma la costruzione del sapere.

Ciao a tutti.  

Milla/Familia

 

 

Editoriale # 2

nullum malum gaudium est. Come quelli che se la prendono con il mio ablativo bastardo (che tuttavia rimarrà: non tutto è deus ex machina, nessuna perversione è gioiosa), bisogna chinare la testa ed accettare la realtà. La realtà si chiama Windows, ormai presente nel Tela Totius Terrae (o preferite WEB ?).  Purtroppo, quisquis se multum Windowsae dedit ingente sibi materiam perturbationis et inexplicabilem fecit. Chi si è affidato alle flatulenze gatiane non avrà vita facile. Gli anelli della libertà si stringono (quoque tu, Ring0), le API ci sovrastano con i loro sciami, il nostro meraviglioso limbo degli Interrupt si allontana…dovremmo quindi abbandonare ogni speranza ?

La risposta la conosciamo tutti. Quindi, figlioli, al lavoro. Solo lo studio ci salverà. Ricordiamoci che per questa via… itur ad astra !

Valete.

S3n3ca~/Familia

 

 

indice

1.      Un mondo nuovo

2.      Il formato PE

3.      Un po’ di pratica

 

 

L’AMBIENTE WIN 32 – un mondo nuovo

 

Questo è un mondo nuovo. Scordatevi il DOS, scordatevi di quelle zone buie e fredde dello schermo dove i comandi di sistema brillavano solitari, magari allietati dai fotoni di fosfori monocromatici. Scordatevi dei cari, buoni 64K nel cui caldo abbraccio amavamo (ma di certo maledicendo) rigirarci. Scordatevi di quelle miniature a 16 bit che erano i “vecchi” registri, esili zattere sulle quali scivolavamo tranquilli. Scordatevi (ma sul serio ?) di quelle chiamate repentine a INT21, con le quali eravamo abituati a strapazzare RAM e HD, periferiche e device (ma qualcuno dice che siano la stessa cosa). Scordatevi del passato. Ora c’è Windows.

Ora c’è il faccione rubicondo del suo padroncino che ce lo rifila come il sistema più stabile (sic) dell’universo, che ci dirà cosa, dove, come codificare, se e quando farlo, qui-si-può-là-già-non-si-può-più, quello è “reserved” e quell’altro no ma lascialo stare… Insomma la goduria è finita.

Ma è davvero finita ?

 

Non staremo qui a sproloquiare sul perché e sul percome, o a riportare una storia che ormai conoscono anche i sassi. Che Windows ammazzi le bisce morte non è più un segreto. Tuttavia Windows a 32 bit è qui tra noi, e sebbene mandi a f****** una quindicina di volte al giorno il suo ideatore, il 99,999% del pianeta continua ad usarlo. Ed anche i virus lo fanno. E siccome MATER studia i virus, MATER seguirà questa strada.

 

Ordunque. Individuiamo a questo punto tre importanti novità:

 

1.      da 16 a 32

Dall’ambiente a 16 bit a quello a 32 bit cambiano alcune cosine. Fermo restando che vi consigliamo di procurarvi un manuale che tratta tale argomento (ce ne sono di ottimi in circolazione), vi spiegheremo in poche righe e per quello che ci riguarda, i cambiamenti più eclatanti.

Nella programmazione vengono utilizzate double words  invece che words, e ciò ha aperto parecchie possibilità ai vwriters. Abbiamo due segmenti da aggiungere ai già conosciuti CS, DS, ES e SS: FS e GS. Abbiamo anche nuovi registri a 32 bit:  EAX, EBX, ECX, EDX, ESI, EDI, EBP e ESP. Vediamo come funzionano. Immaginiamo di dover accedere alla parola meno significativa di EAX. Cosa dobbiamo fare ? A questa porzione di registro  si può accedere usando il registro AX che contiene la parola LSW. Immaginiamo di avere EAX = 00000000. Se vogliamo inserire 1234h nella LSW di EAX dobbiamo eseguire un "mov ax,1234h" e tutto è a posto. Ma se volessimo accedere alla MSW (Most Significant Word) di EAX ?. In questo caso non possiamo usare un registro. Dovremo invece utilizzare l’istruzione ROL (o SHL).

 

2.      API

Il secondo cambiamento importante sono le API. Esse saranno l’argomento del numero successivo.

 

3.      PE

La terza novità riguarda il formato dei files eseguibili. Andiamo oltre il formato COM, oltre l’EXE del DOS (trattati negli scorsi numeri) e il NE di Win16.

Approderemo ora al formato Portable Executable (PE). E di questo parleremo ora.

 

2. il file PE

 

Con l’avvento dei sistemi multipiattaforma dell’ambiente Win32, quei cari ragazzi della Microsoft hanno pensato di studiare un formato di file eseguibile che andasse bene un po’ per tutti. Dopo un periodo di pensoso travaglio, è nato così il formato PE, assai diverso dai precedenti (COM, EXE DOS, NE, etc.) e un pochino più complicato. E’ molto importante capire questa struttura per studiare i virus di Win32.

 

Ecco, tanto per iniziare, un piccolo schema:

 

 
offset 0__________________________________MZ_________   MS_DOS Header
        ________________________________PE\0\0_______   Signature  ___________             
                  IMAGE_FILE_HEADER                                           |
        _____________________________________________ _                       | 
                                                       |                      |        
        _____________________________________________  | IMAGE_OPTIONAL_HEADER| 
                                                       |                      |
                    Data Directory                     |                      | 
        _____________________________________________ _|  ____________________|
      +-_____________________________________________  |              
     +|-_____________________________________________  |  
    +||-_____________________________________________  |  Section Table (array di
   +|||-_____________________________________________  |  IMAGE_SECTION_HEADERs)
  +||||-_____________________________________________  |  
  |||||                                                |
  ||||>______________________________________________ _|
  ||||                     
  ||||                    .text
  |||+> _____________________________________________
  |||
  |||                     .data 
  ||+-> _____________________________________________
  ||
  ||                      .edata
  |+->  _____________________________________________
  |                       .idata
  +-à  _____________________________________________
                          .reloc
        _____________________________________________
 
        _____________________________________________
 
                   numeri di linea COFF      
        _____________________________________________
 
                       Simboli COFF
        _____________________________________________
 
              informazioni del Debug CodeView
        _____________________________________________
 
Ora, qualche spiegazione:
 
DOS-stub e Signature (vecchio header EXE) – DOS HEADER
 
off dim.  nome               descrizione
+0  WORD e_magic;            Magic (sigla MZ)
 2  WORD e_cblp;             Bytes dell’ultima pagina del file
 4  WORD e_cp;               Pagine nel file
 6  WORD e_crlc;             Rilocazioni
 8  WORD e_cparhdr;          Misura dell’header nei paragrafi
 A  WORD e_minalloc;         Memoria extra minima per i paragrafi
 C  WORD e_maxalloc;         Memoria extra massima per i paragrafi
 E  WORD e_ss;               Valore iniziale di SS (relativo) 
10  WORD e_sp;               Valore iniziale di SP 
12  WORD e_csum;             Checksum
14  WORD e_ip;               Valore iniziale di IP 
16  WORD e_cs;               Valore iniziale di CS (relativo) 
18  WORD e_lfarlc;           Indirizzo nel file della tabella di rilocazione
1A  WORD e_ovno;             numero di overlay 
1C  WORD e_res[4];           Riservato (words)
24  WORD e_oemid;            Identificatore OEM 
26  WORD e_oeminfo;          Informazione OEM 
28  WORD e_res2[10];         Riservato (words)
3C  DWORD e_lfanew;          Indirizzo nel file del nuovo header exe 
 
qui è inserito lo STUB (mozzicone MS-DOS, che è opzionale, ed è un programmino per il messaggio di incompatibilità del PE file con l’ambiente DOS (avete mai provato a lanciare un eseguibile windows da DOS ?).
    
FILE HEADER (IMAGE FILE HEADER)
 
+0 PE      Signature: PE\0\0
 4 WORD    Machine: 
 6 WORD    NumberOfSections: 
 8 DWORD   TimeDateStamp: 
 C DWORD   PointerToSymbolTable: 
10 DWORD   NumberOfSymbols: 
14 WORD    SizeOfOptionalHeader: 
16 WORD    Characteristics: 
 

Totale:  18h BYTES

 

Segue una breve descrizione dei campi:

 

PE\0\0:

La marcatura che contraddistingue ogni file PE.

 

Machine:

Indica il tipo di processore. esempio:

  IMAGE_FILE_MACHINE_I386    equ  14Ch    ; Intel 386.

  IMAGE_FILE_MACHINE_R3000   equ  162h    ; MIPS little-endian,160h big-endian

  IMAGE_FILE_MACHINE_R4000   equ  166h    ; MIPS little-endian

  IMAGE_FILE_MACHINE_R10000  equ  168h    ; MIPS little-endian

  IMAGE_FILE_MACHINE_ALPHA   equ  184h    ; Alpha_AXP

  IMAGE_FILE_MACHINE_POWERPC equ  1F0h    ; IBM PowerPC Little-Endian

 

Number Of Sections:

numero delle. sezioni presenti e numero dielementi della tabella section headers.

 

Time Date Stamp:

time stamp usata per verificare la versione del modulo (dal 31.12.69) alla data del linkaggio.

 

Pointer To Symbol Table:

offset della tabella simboli COFF (OBJ).

 

Number Of Symbols:

numero dei simboli della tabella COFF (OBJ).

 

Size Of Optional header:

misura degli optional headers (di solito 0xE0). Somma dei bytes che IMAGE_OPTIONAL_HEADER occupa (vedi la descrizione di IMAGE_OPTIONAL_HEADER)

 

Characteristics:

informazioni sul file (se è un exe e non una lib, etc)
 
OPTIONAL HEADER (IMAGE OPTIONAL HEADER)
 
18 WORD    Magic: 
1a UCHAR   MajorLinkerVersion: 
1b UCHAR   MinorLinkerVersion: 
1c DWORD   SizeOfCode: 
20 DWORD   SizeOfInitializedData: 
24 DWORD   SizeOfUninitializedData; 
28 DWORD   AddressOfEntryPoint: 
2c DWORD   BaseOfCode: 
30 DWORD   BaseOfData: 
34 DWORD   ImageBase: 
38 DWORD   SectionAlignment: 
3c DWORD   FileAlignment: 
40 WORD    MajorOperatingSystemVersion: 
42 WORD    MinorOperatingSystemVersion: 
44 WORD    MajorImageVersion: 
46 WORD    MinorImageVersion: 
48 WORD    MajorSubsystemVersion: 
4a WORD    MinorSubsystemVersion: 
4c DWORD   Reserved1:  
50 DWORD   SizeOfImage: 
54 DWORD   SizeOfHeaders: 
58 DWORD   CheckSum: 
5c WORD    Subsystem:
5e WORD    DllCharacteristics;    
60 DWORD   SizeOfStackReserve: 
64 DWORD   SizeOfStackCommit: 
68 DWORD   SizeOfHeapReserve: 
6c DWORD   SizeOfHeapCommit: 
70 DWORD   LoaderFlags: 
74 DWORD   NumberOfRvaAndSizes: 

 

Totale : 78h BYTES (assieme a IMAGE_FILE_HEADER)

                 

Magic:

Magic: sempre 0x010B    

 

Major Linker Version and Minor Linker Version:

versione del linker che ha prodotto il file    

 

Size Of Code:

misura di tutte le sezioni codice (somma in bytes)    

 

Size Of Initialized Data:

somma delle sezioni dati inizializzati

 

Size Of Uninitialized Data:

somma delle sezioni dati non inizializzati   

 

 Address of EntryPoint:

RVA entry point del modulo (da cui il loader darà esecuzione del PE).
30 DWORD   BaseOfData: RVA della prima sezione di dati         

 

Base Of Code:

RVA della prima sezione di codice (.text, CODE). In memoria le sezioni codice vengono prima delle sezioni dati e dopo l’header PE. E’ usualmente 0x1000 nei Linker Microsoft.

 

Base Of Data:

RVA della prima sezione di dati. Di solito per ultima in memoria, dopo l’header e le sezioni codice.

 

Image Base:

indirizzo lineare indirizzamento linker (base di riferimento di tutti gli RVA). Quando il linker crea un eseguibile, assume che il file sarà mappato in memoria in una specifica locazione. Tale indirizzo è salvato in questo campo. Se il file è realmente mappato dal loader a quell’indirizzo, il codice non ha bisogno di alcun aggiustamento prima di essere eseguito. Negli eseguibili prodotti per Windows NT, L’image base  di default è 0x10000. Per le DLL, il default è 0x400000. In Win9X, l’indirizzo 0x10000 non può essere usato per caricare eseguibili a 32-bit perché tale indirizzo è situato in una regione condivisa da altri processi. Per questo motivo Microsoft  ha cambiato l’indirizzo di base di default per gli eseguibili Win32 a 0x400000. I vecchi programmi che erano stati linkati assumono come base l’inidirzzo 0x10000 saranno più lenti nel caricamento sotto Win9X perché il loader deve applicare la rilocazione della base. 

Questo campo e' di vitale importanza in quanto riporta la cosidetta "preferred imagebase" ovvero l'indirizzo lineare nello spazio di indirizzamento privato utilizzato dal linker per risolvere gran parte dei fixup nonche' la base a cui si riferiscono tutti gli RVA: questo significa che se il loader di Windows deve mappare l'immagine ad un indirizzo diverso sara' necessario applicare le base relocations.

 

Section Alignment:

modulo per allineamento delle sezioni per la mappatura in memoria. Quando ogni sezione è mappata in meoria, il sistema garantisce che la sezione comincerà a un indirizzo virtuale che è un multiplo di questo valore.Il default è 0x1000. Quando il loader di window mappa in memoria il file immagine fa in modo che occupi uno blocco consecutivo di memoria nello spazio di indirizzamento.Tuttavia per questioni di ottimizzazione nella gestione della memoria virtuale (ad exp. nello share di porzioni di codice, nel caricamento di pagine non presenti,ecc.) in w9x ogni sezione deve essere allineata ad un multiplo della unita' minima gestita dal VMM : 1 pagina x86 = 4096 = 1000h (attenzione a non confonderla con la granularita' di allocazione che e' di 64k). Questa limitazione non si applica a NT (il minimo e' 32byte) ma non credo che vogliate degli eseguibili "incompatibili".

 

File Alignment:

modulo per allineamento sezioni su disco. In un PE, il sistema garantisce che dati su disco che identificano ogni sezioni partano da un multiplo di questo valore. Il default è 0x200 bytes,probabilmente per assicurare che le sezioni partano all’inizio di un settore del disco (che è 0x200  bytes). Questo campo è equivalente all’allineamento segment/resource nei files NE  files. A differenza di un  NE, il PE non ha centinaia di sezioni, così lo spazio non viene sprecato. Questo campo e' un antico retaggio di quando Windows95 utilizzava il filesystem FAT, e per ottimizzare i caricamenti si era pensato di allineare i dati delle sezioni su disco ad un multiplo della grandezza di un settore (200h = 512 b).

 

 

Major Operating System Version and Minor Operating System Version:

versione del SO minima richiesta per  l’eseguibile (1.0)

 

Major Image Version and Minor Image Version:

campo definibile dall’utente (switch /version del linker)

 

Major Subsystem Version and Minor Subsystem Version:

massimo e minimo sub sistema (es. Win NT 3.1)    

 

Reserved1:

sempre = 0  (molto usato dai code writers per un infection mark)

 

Size Of Image:

grandezza immagine in memoria (header+VirtualSize sezioni). Questo campo riporta la grandezza dell'immagine una volta  in memoria e quindi lo spazio totale che il loader deve riservare per il suo caricamento. E' costituita dalla somma dell'header + le VirtualSize delle sezioni presenti ed arrotondata al multiplo piu' vicino della SectionAlignment. Quest'ultimo fatto e' stato fonte di problemi per molti coders che avevano testato il loro virus solo con win95 dato che questo ignora l'allineamento continuando pacificamente mentre per  NT  questo non va bene. 

 

Size Of Headers:

somma delle dimensioni headers che precedono i dati delle sezioni. Il valore qui riportato altro non e' che la somma delle dimensioni dei vari headers che precedono i dati delle sections (DosHeader+ Stub+ NtHeaders, SectionHeaders): in sostanza e' una sorta di puntatore ai rawdata dato che ImageBase+ SizeOfHeaders vi porta direttamente all'inizio della prima sezione, sia che stiate lavorando con l'immagine di un processo in memoria,o su disco.

 

Checksum:

CheckSum: cheksum immagine file PE    

 

SubSystem:

1=nativo; 2=Win GUI; 3=Win CUI; 5=OS2; 7=POSIX

 

Dll Characteristics:

Un set di flags indicante in quale circostanza può essere chiamata una funzione di inizializzazione DLL (come DllMain). Questo valore sembra essere settato a 0. Altri valori:

 1      Call when DLL is first loaded into a process's address space

 2      Call when a thread terminates

 4      Call when a thread starts up

 8      Call when DLL exits

 

Size Of Stack Reserve:

memoria virtuale per lo stack (0x100000 – 1Mb)

 

Size Of Stack Commit:

memoria allocata inizialmente per lo stack (0x1000 – 1 pagina)

 

Size Of Heap Reserve:

memoria per heap (1 pagina)

 

Size Of Heap Commit:

vedi sopra. 1 pagina.

 

Loader Flags:

per debugging

 

Number Of Rva And Sizes:

Questo campo indica la dimensione dell'array di strutture IMAGE_DATA_DIRECTORY che inizia dal campo DataDirectory. Attualmente e' fissato a 16 elementi ma non è detto che rimanga così per sempre.

 

SECTION DIRECTORIES (SECTION TABLE)
 
   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    * IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 * 
Ogni elemento della struttura riporta l’RVA e la VirtualSIze di specifiche informazioni /strutture.
 
78 DWORD ExportDirectory VA      funzioni esportate dal modulo
7c DWORD ExportDirectory Size
80 DWORD ImportDirectory VA      funzioni importate dal modulo
84 DWORD ImportDirectory Size
88 DWORD ResourceDirectory VA    inizio della resource directory (resROOS) 
8c DWORD ResourceDirectory Size 
90 DWORD ExceptionDirectory VA   
94 DWORD ExceptionDirectory Size
98 DWORD SecurityDirectory VA
9c DWORD SecurityDirectory Size
a0 DWORD BaseRelocationTable VA
a4 DWORD BaseRelocationTable Size
a8 DWORD DebugDirectory VA
ac DWORD DebugDirectory Size
b0 DWORD ArchitectureSpecificData VA
b4 DWORD ArchitectureSpecificData Size
b8 DWORD RVAofGP VA
bc DWORD RVAofGP Size
c0 DWORD TLSDirectory VA
c4 DWORD TLSDirectory Size
c8 DWORD LoadConfigurationDirectory VA
cc DWORD LoadConfigurationDirectory Size
d0 DWORD BoundImportDirectoryinheaders VA
d4 DWORD BoundImportDirectoryinheaders Size
d8 DWORD ImportAddressTable VA
dc DWORD ImportAddressTable Size
e0 DWORD DelayLoadImportDescriptors VA
e4 DWORD DelayLoadImportDescriptors Size
e8 DWORD COMRuntimedescriptor VA
ec DWORD COMRuntimedescriptor Size
f0 DWORD 0
f4 DWORD 0
 

Come si può vedere ogni DataDirectory e' una struttura che rappresenta per il loader una sorta di shortcut per accedere velocemente alle informazioni piu' sensibili per la creazione/inizializzazione del processo. Ogni elemento (indici da 0 a 15) riporta l'RVA e la VirtualSize di specifiche informazioni/strutture. Le piu' importati sono:

 

           0 : funzioni esportate dal modulo (ET)

           1 : funzioni importate ma non bounded (IT)

           2 : inizio della resource directory (resROOT)

           5 : base relocations

           9 : blocco thread local storage (TLS)

           11: funzioni importate bound (BIT)

           12: import addresse table (IAT)

 

Il loader fa sempre riferimento a questa tabella per accedere ai dati del processo e non alla tabella dei section headers.
  
 
SECTION HEADERS (IMAGE SECTION HEADER)
 
di seguito all’ optional header (a +f8h) inizia l’array di strutture IMAGE_SECTION_HEADER noto come section table o tabella delle sezioni; ogni elemento dell’array descrive i dati essenziali di una sezione presente nel file.
 
+0 8byte ANSI name: 
+8 dword misc (actual size)
+C dword virtual address: 
10 dword sizeofrawdata: 
14 dword pointerToRawData:
18 dword pointerToRelocations: 
1C dword PointerToLinenumbers
20 word NumberOfRelocations
22 word NumberOfLineNumbers
24 dword Characteristics: alcuni dei flags possibili:
-         0x00000020 contiene codice
-         0x00000040 contiene dati initializati
-         0x00000080 contiene dati non inizial.
-         0x00000200 contiene commenti
-         0x02000000 puo’ essere discarded
-         0x10000000 la section è shareable
-         0x20000000 la section è executable
-         0x40000000 la section è readable
-         0x80000000 la section è writeable

Totale : 28h BYTES

 
 

Section Name:

Nome della sezione  ANSI  e non UNICODE.

 

Virtual Size:

convenzionalmente contiene la dimensione fisica (vedi SizeOfRawData) dei dati arrotondata ad un multiplo del section aligment. Questo campo in pratica dovrebbe dire al loader quanto spazio riservare in memoria per questa sezione. (dovrebbe perche' il loader sembra perfettamente ignorare questo campo in presenza di una rawsize "valida" ed effettuare da se i calcoli per una VSize corretta. Questo probabilmente spiega anche il fatto che la ImageSize venga ignorata da w9x. Cmq e' anche perfettamente lecito avere una rawsize = 0 e una VSize=0x1000,tant'e' che i packer sfruttano proprio questa caratteristica cambiando la rawsize ma lasciando inalterata la VSize (a dir il vero la VSize puo' anche sovrapporsi alla sezione successiva dato che e' cmq uno spazio solo "riservato" e non necessariamente utilizzato) purche' ovviamente non ci sia vera sovrascrizione.

 

Virtual Address:

RVA che permette di calcolare la posizione che avra' la sezione una volta caricata in memoria dal loader. Deve essere maggiore, o un multiplo, del section alignment (che lo ricordiano non puo' essere minore di 0x1000 per compatibilita' con 9x).

 

Size Of Raw Data:

la dimensione fisicamente occupata dai dati su disco solitamente allineata al file alignment. Questo campo puo' essere totalmente indipendente dalla Vsize. Per  esempio, assumiamo un file alignment di 0x200. Se il campo VirtualSize ci dice che la sezione è lunga 0x35A bytes questo campo riporterà che la sezione è lunga 0x400 bytes.

 

Pointer To Raw Data:

l'offset "fisico" a cui trovare i dati della sezione.

 

Pointer To Relocations:

in un EXE questo campo  (e il seguente) non è importante, ed è settato a 0.

 

Pointer To Line Numbers:

vedi sopra.

 

Number Of Relocations:

Questo campo sembra rilevante solo per gli OBJ.

 

Number Of Line Numbers:

numero di linee

 

 Characteristics:

i flag che identificano le caratteristiche (codice,dati,ecc.) e quindi le i flags e le protezioni di pagina che verranno applicate (writable,readable,ecc.). Alcuni dei flags possibili:

 

-        0x00000020 contiene codice
-        0x00000040 contiene dati initializati
-        0x00000080 contiene dati non inizial.
-        0x00000200 contiene commenti
-        0x02000000 puo’ essere discarded
-        0x10000000 la section è shareable
-        0x20000000 la section è executable
-        0x40000000 la section è readable
-        0x80000000 la section è writeable

 

 
Export Directory
 
+0 DWORD   Characteristics;
4  DWORD   TimeDateStamp;
8  WORD    MajorVersion;
a  WORD    MinorVersion;
c  DWORD   Name;
10 DWORD   Base;
14 DWORD   NumberOfFunctions;
18 DWORD   NumberOfNames;
1c DWORD   *AddressOfFunctions;
20 DWORD   *AddressOfNames;
24 DWORD   *AddressOfNameOrdinals;
 
Import Directory
 
+0 DWORD   OriginalFirstThunk;
 4 DWORD   TimeDateStamp;
 8 DWORD   ForwarderChain;
 c DWORD   Name;
10 DWORD   FirstThunk;
 
SEGUONO LE SEZIONI 
 
.text section: codice general-purpose 
.data section: dati inizializzati
.bss section: variabili non inizializzate
.rsrc section: risorse del modulo
.idata section: informazioni sulle funzioni e dati importati da DLL esterne
.edata section: lista delle funzioni e dati esportati ad altri moduli
.reloc section tabella di rilocazioni (delta offset)
 
 

ULTERIORI  LETTURE

Vi consigliamo di scovare la documentazione di Matt Pietrek: Peering Inside the PE: A Tour of the Win32 Portable Executable File Format, 1994 e di Luevelsmeyer 1998, che si trovano un po’ ovunque.

 

3. Dopo la teoria, la pratica

 

Ora, la pratica. Vediamo un po’ più da vicino la struttura di un file PE.

A tale scopo scriviamo il seguente programma:

 

.386

.model flat

locals

 extrn   ExitProcess:PROC

 

   .DATA

 

   var    db ?

 

   .CODE

 

CORTO:

 

   push    0

   call    ExitProcess

  

   Ends

End CORTO

 

Come possiamo vedere è un programma molto semplice, che si limita a inserire un valore nello stack e chiamare una sola funzione API (ExitProcess). Vedremo nel capitolo successivo cosa sono queste API.

Assembliamo e linkiamo il nostro programma, chiamato corto.asm, e produciamo il file PE corto.exe. Come viene memorizzato tale file eseguibile sul disco ? Sbirciando un pochino su disco dove è stato memorizzato corto.exe vedremmo qualcosa di simile:

 

0000:  4d 5a 50 00 02 00 00 00 04 00 0f 00 ff ff 00 00    "MZP............."

0010:  b8 00 00 00 00 00 00 00 40 00 1a 00 00 00 00 00    "........@......."

0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

0030:  00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00    "................"

…….

e così via. Ad una prima occhiata ci appare poco comprensibile; aggiungiamoci qualche definizione:

 

NOTA: ricordiamo che quel birichino dell’Intel memorizza i dati al contrario, dal byte meno significativo (o basso) al byte più significativo (o alto). Così dove vediamo:

                                    78 56  34  12 dobbiamo leggere: 12 34 56 78.

 

Dumping File: CORTO.EXE

 
vecchio header EXE – DOS HEADER

 

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0000:  4d 5a 50 00 02 00 00 00 04 00 0f 00 ff ff 00 00    "MZP............."

0010:  b8 00 00 00 00 00 00 00 40 00 1a 00 00 00 00 00    "........@......."

0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

0030:  00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00    "................"

 
+0  WORD e_magic;            Magic (sigla MZ)
 2  WORD e_cblp;             Bytes dell’ultima pagina del file (qui 50)
 4  WORD e_cp;               Pagine nel file (qui 2)
 6  WORD e_crlc;             Rilocazioni (0)
 8  WORD e_cparhdr;          Misura dell’header nei paragrafi (4)
 A  WORD e_minalloc;         Memoria extra minima per i paragrafi (f)
 C  WORD e_maxalloc;         Memoria extra massima per i paragrafi (ffff)
 E  WORD e_ss;               Valore iniziale di SS (relativo) (0)
10  WORD e_sp;               Valore iniziale di SP (b8)
12  WORD e_csum;             Checksum (0) 
14  WORD e_ip;               Valore iniziale di IP  (0)
16  WORD e_cs;               Valore iniziale di CS (0) 
18  WORD e_lfarlc;           Indirizzo nel file della tab. di rilocazione (40)
1A  WORD e_ovno;             numero di overlay  (1a)
1C  WORD e_res[4];           Riservato (words) (0)
24  WORD e_oemid;            Identificatore OEM 
26  WORD e_oeminfo;          Informazione OEM 
28  WORD e_res2[10];         Riservato (words)
3C  DWORD e_lfanew;          Indirizzo nel file del nuovo header exe  (100)
 
 
STUB DOS 

 

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0040:  ba 10 00 0e 1f b4 09 cd 21 b8 01 4c cd 21 90 90    "........!..L.!.."

0050:  54 68 69 73 20 70 72 6f 67 72 61 6d 20 6d 75 73    "This program mus"

0060:  74 20 62 65 20 72 75 6e 20 75 6e 64 65 72 20 57    "t be run under W"

0070:  69 6e 33 32 0d 0a 24 37 00 00 00 00 00 00 00 00    "in32..$7........"

0080:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

0090:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00a0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00b0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00c0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00d0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00e0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

00f0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    "................"

 

Questo sopra è lo STUB (mozzicone MS-DOS. E’ opzionale ed è un programmino per il messaggio di incompatibilità del PE file con l’ambiente DOS. Segue:
 
FILE HEADER (IMAGE FILE HEADER)

 

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0100:  50 45 00 00 4c 01 04 00 77 29 f1 86 00 00 00 00    "PE..L...w)......"

0110:  00 00 00 00 e0 00 8e 81

 

E cos’ via.

Ma vediamo l’output dello stesso eseguibile corto.exe fornito dal programma dumper di Matt Pietrek, Pedump:

 

Dump of file CORTO.EXE

 

File Header

  Machine:                      014C (i386)

  Number of Sections:           0004

  TimeDateStamp:                86F12977

  PointerToSymbolTable:         00000000

  NumberOfSymbols:              00000000

  SizeOfOptionalHeader:         00E0

  Characteristics:              818E

    EXECUTABLE_IMAGE

    LINE_NUMS_STRIPPED

    LOCAL_SYMS_STRIPPED

    BYTES_REVERSED_LO

    32BIT_MACHINE

    BYTES_REVERSED_HI

 

Optional Header

  Magic                         010B

  linker version                2.25

  size of code                  200

  size of initialized data      400

  size of uninitialized data    0

  entrypoint RVA                1000

  base of code                  1000

  base of data                  2000

  image base                    400000

  section align                 1000

  file align                    200

  required OS version           1.00

  image version                 0.00

  subsystem version             3.10

  Reserved1                     0

  size of image                 5000

  size of headers               400

  checksum                      0

  Subsystem                     0002 (Windows GUI)

  stack reserve size            100000

  stack commit size             2000

  heap reserve size             100000

  heap commit size              1000

  RVAs & sizes                  10

 

Data Directory

  EXPORT       rva: 00000000  size: 00000000

  IMPORT       rva: 00003000  size: 00000054

  RESOURCE     rva: 00000000  size: 00000000

  EXCEPTION    rva: 00000000  size: 00000000

  SECURITY     rva: 00000000  size: 00000000

  BASERELOC    rva: 00004000  size: 0000000C

  DEBUG        rva: 00000000  size: 00000000

  COPYRIGHT    rva: 00000000  size: 00000000

  GLOBALPTR    rva: 00000000  size: 00000000

  TLS          rva: 00000000  size: 00000000

  LOAD_CONFIG  rva: 00000000  size: 00000000

  BOUND_IMPORT rva: 00000000  size: 00000000

  IAT          rva: 00000000  size: 00000000

  unused       rva: 00000000  size: 00000000

  unused       rva: 00000000  size: 00000000

  unused       rva: 00000000  size: 00000000

 

Section Table

  01 CODE      VirtSize: 00001000  VirtAddr:  00001000

    raw data offs:   00000600  raw data size: 00000200

    relocation offs: 00000000  relocations:   00000000

    line # offs:     00000000  line #'s:      00000000

    characteristics: 60000020

      CODE  MEM_EXECUTE  MEM_READ

 

  02 DATA      VirtSize: 00001000  VirtAddr:  00002000

    raw data offs:   00000800  raw data size: 00000000

    relocation offs: 00000000  relocations:   00000000

    line # offs:     00000000  line #'s:      00000000

    characteristics: C0000040

      INITIALIZED_DATA  MEM_READ  MEM_WRITE

 

  03 .idata    VirtSize: 00001000  VirtAddr:  00003000

 

    raw data offs:   00000800  raw data size: 00000200

    relocation offs: 00000000  relocations:   00000000

    line # offs:     00000000  line #'s:      00000000

    characteristics: C0000040

      INITIALIZED_DATA  MEM_READ  MEM_WRITE

 

  04 .reloc    VirtSize: 00001000  VirtAddr:  00004000

    raw data offs:   00000A00  raw data size: 00000200

    relocation offs: 00000000  relocations:   00000000

    line # offs:     00000000  line #'s:      00000000

    characteristics: 50000040

      INITIALIZED_DATA  MEM_SHARED  MEM_READ

 

Imports Table:

  KERNEL32.dll

  Hint/Name Table: 00003028

  TimeDateStamp:   00000000

  ForwarderChain:  00000000

  First thunk RVA: 00003030

  Ordn  Name

     0  ExitProcess (IAT: 00003046)

 

base relocations:

 

Virtual Address: 00001000  size: 0000000C

  00001009 HIGHLOW

  00001000 ABSOLUTE

 

Section Hex Dumps

section 01 (CODE)  size: 00000200  file offs: 00000600

00000000:  6a 00 e8 00 00 00 00 ff  25 30 30 40 00 00 00 00 j.......%00@....

00000010:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ................

------   ------   ------ cut ------  ------  ------

000001F0:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ................

 

section 02 (DATA)  size: 00000000  file offs: 00000800

 

section 03 (.idata)  size: 00000200  file offs: 00000800

00000000:  28 30 00 00 00 00 00 00  00 00 00 00 38 30 00 00 (0..........80..

00000010:  30 30 00 00 00 00 00 00  00 00 00 00 00 00 00 00 00..............

00000020:  00 00 00 00 00 00 00 00  46 30 00 00 00 00 00 00 ........F0......

00000030:  46 30 00 00 00 00 00 00  4b 45 52 4e 45 4c 33 32 F0......KERNEL32

00000040:  2e 64 6c 6c 00 00 00 00  45 78 69 74 50 72 6f 63 .dll....ExitProc

00000050:  65 73 73 00 00 00 00 00  00 00 00 00 00 00 00 00 ess.............

------   ------   ------ cut ------  ------  ------

000001F0:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ................

 

section 04 (.reloc)  size: 00000200  file offs: 00000A00

00000000:  00 10 00 00 0c 00 00 00  09 30 00 00 00 00 00 00 .........0......

------   ------   ------ cut ------  ------  ------

000001F0:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ................

 

Come si può vedere, è abbastanza eloquente ed autoesplicativo e non necessita di ulteriori delucidazioni.