Hola MCKSys Argentina, gracias por el pdf, tras verlo esto es hasta donde yo llego a entender:
Inicio realizando un desplazamiento desde la estructura TEB hasta la estructura PEB que es la que contiene los módulos cargados:
0:000> dt ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 BitField : UChar
+0x003 ImageUsesLargePages : Pos 0, 1 Bit
+0x003 IsProtectedProcess : Pos 1, 1 Bit
+0x003 IsLegacyProcess : Pos 2, 1 Bit
+0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
+0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
+0x003 SpareBits : Pos 5, 3 Bits
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
El código es el siguiente:
xor eax, eax
mov eax, dword ptr fs:[eax + 30h]
De este modo tengo en el registro eax un puntero hacia la estructura PEB.
El campo que nos interesa es "PPEB_LDR_DATA Ldr" cuyo desplazamiento es 0x0C, su estructura es la siguiente:
0:000> dt ntdll!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void
+0x028 ShutdownInProgress : UChar
+0x02c ShutdownThreadId : Ptr32 Void
Esta estructura contiene los módulos cargados en memoria los cuales hace uso el hilo, entre ellos tendremos kernel32 que se carga con todos los procesos.
mov eax, [eax + 0Ch]
Con este código tenemos en eax el puntero hacia esa estructura. A partir de aquí podemos hacer uso de tres tipo de listas diferentes para poder acceder a los módulos según la opción que mas nos interese:
1) En el orden en el que fueron cargados. (offset 0Ch)
2) En memoria. (offset 14h)
3) En modo en el que fueron inicializados. (offset 1Ch)
Dependiendo de la lista que utilicemos tendremos que hacérselo saber en el desplazacimento de este, y dependiendo de la lista que se utilice tendra unas variaciones a la hora de hacer uso de la estructura "LDR_DATA_TABLE_ENTRY" para obtener el nombre de la librería(modulo).
El código que tengo hasta aquí es el siguiente:
xor eax, eax
mov eax, [fs:eax + 30h]
mov eax, [eax + 0Ch]
lea eax, [eax + 14h]
Hasta aquí tengo el registro eax apuntando hacia la lista "InMemoryOrderModuleList" a partir de aquí es donde me pierdo, según tengo entendido hay que hacer un bucle recorriendo cada una de las tablas "LDR_DATA_TABLE_ENTRY" en busca del modulo kernel32.(no se si hay una tabla para todos los módulos, o una tabla para cada modulo).
Por lo que veo en códigos que veo por Internet siguen de la siguiente manera(valido para windows 7):
xor ebx, ebx // clear ebx
mov ebx, fs:[ 0x30 ] // get a pointer to the PEB
mov ebx, [ ebx + 0x0C ] // get PEB->Ldr
mov ebx, [ ebx + 0x14 ] // get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) -----Aquí-----
mov ebx, [ ebx ] // get the next entry (2nd entry)
mov ebx, [ ebx ] // get the next entry (3rd entry)
mov ebx, [ ebx + 0x10 ] // get the 3rd entries base address (kernel32.dll)
La parte que pongo
aquí por lo que leo en el comentario tiene lo mismo que yo pero dice que ya tiene el Flink? es decir la estructura es esta:
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
Es que tras seleccionar "InMemoryOrderModuleList" ya tengo un puntero hacia la primera entrada de "LDR_DATA_TABLE_ENTRY" sin necesidad de tocar Flink?