All'offset 1Ch del PEB (Process Enviroment Block) troviamo il puntatore ai dati del loader (PEB_LDR_DATA)
Questi dati sono strutturati in questo modo:
PEB_LDR_DATA = packed record
Length: Cardinal; //Dimensione struttura
Initialized: BOOLEAN;
SsHandle: Pointer;
FirstInLoadOrderModuleList: PLDR_MODULE; //Puntatore al primo LDR_MODULE in ordine di caricamento
LastInLoadOrderModuleList: PLDR_MODULE; //Puntatore all'ultimo LDR_MODULE in ordine di caricamento
FirstInMemoryOrderModuleList: PLDR_MODULE; //Puntatore al primo LDR_MODULE in ordine di posizione in memoria
LastInMemoryOrderModuleList: PLDR_MODULE; //Puntatore all'ultimo LDR_MODULE in ordine di posizione in memoria
FirstnInitializationOrderModuleList: PLDR_MODULE; //Puntatore al primo LDR_MODULE in ordine di inizializzazione
LastnInitializationOrderModuleList: PLDR_MODULE; //Puntatore all'ultimo LDR_MODULE in ordine di inizializzazione
end;
PPEB_LDR_DATA =^PEB_LDR_DATA;
Un esempio di PEB_LDR_DATA è il seguente
Dump - 00240000..00245FFF
Indirizzo Dati Dati dec. Commenti
00241EA0 28 00 00 00 00000028 //Length
00241EA4 01 F0 AD BA BAADF001 //Initialized
00241EA8 00 00 00 00 00000000 //SsHandle
00241EAC E0 1E 24 00 00241EE0 //InLoadOrderModuleList primo elemento
00241EB0 60 25 24 00 00242560 //InLoadOrderModuleList ultimo elemento
00241EB4 E8 1E 24 00 00241EE8 //InMemoryOrderModuleList primo elemento
00241EB8 68 25 24 00 00242568 //InMemoryOrderModuleList ultimo elemento
00241EBC 58 1F 24 00 00241F58 //InInitializationOrderModuleList primo elemento
00241EC0 E8 20 24 00 002420E8 //InInitializationOrderModuleList ultimo elemento
00241EC4 00 00 00 00 00000000
I dati più importanti contenuti sono sicuramente i puntatori agli LDR_MODULE i quali saranno tanti quanti sono i moduli caricati in memoria. Questi dati sui moduli sono collegati in liste concatenate.
Le liste che contengono le informazioni sui moduli differiscono solo l'ordine in cui vengono elencati.
La prima lista li elenca in ordine di caricamento, la seconda in ordine di disposizione in memoria, la terza in ordine di inizializzazione, ma i nodi della lista sono sempre gli stessi.
Vediamo la struttura di un nodo LDR_MODULE:
LDR_MODULE = packed record
NextInLoadOrderModuleList: PLDR_MODULE; //puntatore al successivo in ordine di caricamento
PreviousInLoadOrderModuleList: PLDR_MODULE; //puntatore al precedente in ordine di caricamento
NextInMemoryOrderModuleList: PLDR_MODULE; //puntatore al successivo in ordine di posizione in memoria
PreviousInMemoryOrderModuleList: PLDR_MODULE; //puntatore al precedente in ordine di posizione in memoria
NextInInitializationOrderModuleList: PLDR_MODULE; //puntatore al successivo in ordine di inizializzazione
PreviousInInitializationOrderModuleList: PLDR_MODULE; //puntatore al precedente in ordine di inizializzazione
BaseAddress: pointer;
EntryPoint: pointer;
SizeOfImage: cardinal;
FullDllName: UNICODE_STRING ;
BaseDllName: UNICODE_STRING ;
Flags: cardinal;
LoadCount: word;
TlsIndex: word;
HashTableEntry: PLDR_MODULE;
HashTableEntry: PLDR_MODULE;
TimeDateStamp: cardinal;
end;
PLDR_MODULE = ^LDR_MODULE
Esempio pratico, prendiamo il primo LDR_MODULE che corrisponde proprio allo stesso eseguibile, il quale viene sempre caricato per primo in memoria:
Dump - 00240000..00245FFF
Indirizzo Dati Dati dec. Commenti
00241EE0 48 1F 24 00 00241F48 //puntatore al successivo in ordine di caricamento
00241EE4 AC 1E 24 00 00241EAC //puntatore al precedente in ordine di caricamento
00241EE8 50 1F 24 00 00241F50 //puntatore al successivo in ordine di posizione in memoria
00241EEC B4 1E 24 00 00241EB4 //puntatore al precedente in ordine di posizione in memoria
00241EF0 00 00 00 00 00000000 //puntatore al successivo in ordine di inizializzazione
00241EF4 00 00 00 00 00000000 //puntatore al precedente in ordine di inizializzazione
00241EF8 00 00 40 00 00400000 //BaseAddress
00241EFC 34 91 40 00 00409134 //EntryPoint
00241F00 00 50 01 00 00015000 //SizeOfImage
//FullDllName: UNICODE_STRING ; (nome completo eseguibile)
00241E04 74 00 0074 //Length
00241E04 76 00 0076 //MaxLength
00241E08 58 08 02 00 00020858 //FullDllName - puntatore al nome
//BaseDllName: UNICODE_STRING ; (nome eseguibile)
00241E0C 3A 00 003A //Length
00241E0C 3C 00 003C //MaxLength
00241F10 92 08 02 00 00020892 //BaseDllName - puntatore al nome
00241E14 00 50 00 00 00005000 //Flags: cardinal;
00241E18 FF FF FFFF //LoadCount: word;
00241E1A FF FF FFFF //TlsIndex: word;
00241E1C 4C 20 24 00 0024204C //HashTableEntry
00241F20 10 C2 98 7C 7C98C210 //HashTableEntry
00241E24 CF DA 13 4B 4B13DACF //TimeDateStamp
00241E28 00 00 00 00 00000000
00241E2C 00 00 00 00 00000000
Se seguiamo la lista concatenata, per esempio in ordine di caricamento troveremo i dati relativi al modulo ntdll.dll:
Indirizzo Dati Dati dec. Commenti
00241F48 10 20 24 00 00242010 | //puntatore al successivo in ordine di caricamento
00241F4C E0 1E 24 00 00241EE0 | //puntatore al precedente in ordine di caricamento
00241F50 18 20 24 00 00242018 | //puntatore al successivo in ordine di posizione in memoria
00241F54 E8 1E 24 00 00241EE8 | //puntatore al precedente in ordine di posizione in memoria
00241F58 20 20 24 00 00242020 | //puntatore al successivo in ordine di inizializzazione
00241F5C BC 1E 24 00 00241EBC | //puntatore al precedente in ordine di inizializzazione
00241F60 00 00 91 7C 7C910000 | //BaseAddress
00241F64 56 31 92 7C 7C923156 | //EntryPoint
00241F68 00 60 0B 00 000B6000 | //SizeOfImage
00241F6C 3A 00 003A | //FullDllName: UNICODE_STRING ;
00241F6E 08 02 0208 | //FullDllName - length
00241F70 E8 DE 98 7C 7C98DEE8 | //FullDllName - puntatore
00241F74 12 00 0012 | //BaseDllName: UNICODE_STRING ; ntdll.dll
00241F76 14 00 0014 | //BaseDllName - length
00241F78 A4 26 93 7C 7C9326A4 | //BaseDllName - puntatore
00241F7C 04 40 08 80 80084004 | //Flags: cardinal;
00241F80 FF FF FFFF | //LoadCount
00241F82 00 00 0000 | //TlsIndex
00241F84 28 C2 98 7C 7C98C228 | //HashTableEntry
00241F88 28 C2 98 7C 7C98C228 | //HashTableEntry
00241F8C 01 2C 25 41 41252C01 | //TimeDateStamp
00241F90 00 00 00 00 00000000 |
Per verificare i puntatori delle unicode string riportiamo il dump dell'area di memoria puntata:
Dump - ntdll:.data
Indirizzo Dati ASCII
7C98DEE8 46 00 3A 00|5C 00 57 00|49 00 4E 00|44 00 4F 00| F.:.\.W.I.N.D.O.
7C98DEF8 57 00 53 00|5C 00 73 00|79 00 73 00|74 00 65 00| W.S.\.s.y.s.t.e.
7C98DF08 6D 00 33 00|32 00 5C 00|6E 00 74 00|64 00 6C 00| m.3.2.\.n.t.d.l.
7C98DF18 6C 00 2E 00|64 00 6C 00|6C 00 00 00| l...d.l.l...
Dump - ntdll:.text
Indirizzo Dati ASCII
7C9326A4 6E 00 74 00|64 00 6C 00|6C 00 2E 00|64 00 6C 00| n.t.d.l.l...d.l.
7C9326B4 6C 00 00 00| l...
Se seguiamo ulteriormente la lista concatenata, per esempio in ordine di caricamento, troveremo i dati relativi al modulo kernel32.dll:
Dump - 00240000..00245FFF
Indirizzo Dati Dati dec. Commenti
00242010 D8 20 24 00 002420D8 //puntatore al successivo in ordine di caricamento
00242014 48 1F 24 00 00241F48 //puntatore al precedente in ordine di caricamento
00242018 E0 20 24 00 002420E0 //puntatore al successivo in ordine di posizione in memoria
0024201C 50 1F 24 00 00241F50 //puntatore al precedente in ordine di posizione in memoria
00242020 A8 21 24 00 002421A8 //puntatore al successivo in ordine di inizializzazione
00242024 58 1F 24 00 00241F58 //puntatore al precedente in ordine di inizializzazione
00242028 00 00 80 7C 7C800000 //BaseAddress
0024202C AE B5 80 7C 7C80B5AE //EntryPoint
00242030 00 00 10 00 00100000 //SizeOfImage
00242034 40 00 0040 //FullDllName: UNICODE_STRING ;
00242036 42 00 0042 //FullDllName - length
00242038 B0 1F 24 00 00241FB0 //FullDllName - puntatore
0024203C 18 00 0018 //BaseDllName: UNICODE_STRING ;
0024203E 1A 00 001A //BaseDllName - length
00242040 D8 1F 24 00 00241FD8 //BaseDllName - puntatore
00242044 04 40 08 80 80084004 //Flags: cardinal;
00242048 FF FF FFFF //LoadCount
0024204A 00 00 0000 //TlsIndex
0024204C 10 C2 98 7C 7C98C210 //HashTableEntry
00242050 1C 1F 24 00 00241F1C //HashTableEntry
00242054 E9 09 00 45 450009E9 //TimeDateStamp
Verifichiamo il nome della libreria:
Dump - 00240000..00245FFF
Indirizzo Dati ASCII
00241FD8 6B 00 65 00|72 00 6E 00|65 00 6C 00|33 00 32 00| k.e.r.n.e.l.3.2.
00241FE8 2E 00 64 00|6C 00 6C 00|00 00 ..d.l.l...
E così via per tutti i moduli caricati in memoria.





