Zaczne od tego, ze system WinXP 32-bit, x86.
Bawiac sie na Windowsie dzisiaj natrafilem na pewna nie scislosc, ktorej nie moge za zadne skarby rozwiazac, a mianowicie.
Mamy sobie strukture TEB(z FG wyciagam adresik), a w niej na offsecie 0x30 mamy adres PEB'a. Udaje sie do tego PEB'a, bo chce sobie adresik kernel32 nabyc, na razie standardowo bez SEH.
Struktura PEB wyglada tak(wersja krotsza z MSDN):
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
No i dobra tu wszystko jest zrozumiale, wiec udaje sie do struktury PPEB_LDR_DATA, poniewaz w niej maja byc zapisane informacje o zaladowanych do przestrzeni adresowej modulach/bibliotekach.
W roznych zrodlach juz ta struktura sie rozni, ale doszedlem do wniosku, ze ta wersja bedzie najwlasciwsza.
typedef struct _PEB_LDR_DATA
{
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
Tutaj juz zaczynaja pojawiac sie moje watpliwosci. Wzoruje sie na tym opisie.
http://undocumented.ntinternals.net/UserMode/Structures/PEB_LDR_DATA.html
Natomiast wszystko staje sie zagmatwane, gdy mam taki kod:
find_kernel_32:
push esi
xor eax, eax
mov eax, [fs:0x30] ; FS + 0x30 -> PEB
mov eax, [eax+0x0C] ; PEB->Ldr
mov esi, [eax+0x1C] ; ?????
lodsd ; z DS:ESI do EAX
mov eax, [eax+0x08] ; PEB->Ldr.???.flink.base_address
pop esi
Lecialem sobie po kolei w Olly'm ogarnac jak to jest po kolei ale za malo na razie mam informacji.
Czytalem i wywnioskowalem ze z PEB->Ldr udaje sie do InInitializationOrderModuleList; w PEB_LDR_DATA, czyli kod mov esi, [eax+0x1C].
Na OpenRC znalazlem fajna tabelke z tymi strukturami, ale to tez nie rozwiewa moich watpliwosci.
Chodzi o to, ze InInitializationOrderModuleList; jest typu LIST_ENTRY, czyli jak podaje nirsoft.net:
typedef struct _LIST_ENTRY
{
PLIST_ENTRY Flink;
PLIST_ENTRY Blink;
} LIST_ENTRY, *PLIST_ENTRY;
Wedlug mnie flink wskazuje na pierwszy element listy, a blink na wlasnie nie wiem jaki ?
Do tego dochodzi taki potworek, ktory nie rozumiem zupelnie jak jest powiazany z tym skoro ta struktura tak wyglada i nie ma zadnego w oczy rzucajacego sie zwiazku z ponizsza, poza takimi samymi polami typu LIST_ENTRY.
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint; ; :)
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
Interesuje mnie to LDR_MODULE, ale jesli z PEB_LDR_DATA ide do LIST_ENTRY InInitializationOrderModuleList; to jakim cudem w nastepnym kroku trafiam do _LDR_MODULE ?
Nie rozumiem za bardzo mozliwosci aby sie w ten sposob przemiescic. Skoro to _LDR_MODULE zawiera pola LIST_ENTRY, a ja juz z PEB_LDR_DATA trafiam do LIST_ENTRY, ktore wskazuje tylko na pola LIST_ENTRY wiec jak to sie dzieje ?
Bede wdzieczny nawet za krotkie wyjasnienie, bo takie cos nie wiele mi mowi:
InMemoryOrderModuleList
The head of a doubly-linked list that contains the loaded modules for the process. Each item in the list is a pointer to an LDR_DATA_TABLE_ENTRY structure. For more information, see Remarks.
Zwlaszcza, ze inaczej PEB_LDR_DATA wyglada na kazdej z tych 3 stron, tj nirsoft, undocument i msdn.