Declarations for PEB:
Code
1typedef struct _PEB {
2 BOOLEAN InheritedAddressSpace;
3 BOOLEAN ReadImageFileExecOptions;
4 BOOLEAN BeingDebugged;
5 BOOLEAN Spare;
6 HANDLE Mutant;
7 PVOID ImageBaseAddress;
8 PPEB_LDR_DATA LoaderData;
9 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
10 PVOID SubSystemData;
11 PVOID ProcessHeap;
12 PVOID FastPebLock;
13 PPEBLOCKROUTINE FastPebLockRoutine;
14 PPEBLOCKROUTINE FastPebUnlockRoutine;
15 ULONG EnvironmentUpdateCount;
16 PVOID *KernelCallbackTable;
17 PVOID EventLogSection;
18 PVOID EventLog;
19 PPEB_FREE_BLOCK FreeList;
20 ULONG TlsExpansionCounter;
21 PVOID TlsBitmap;
22 ULONG TlsBitmapBits[0x2];
23 PVOID ReadOnlySharedMemoryBase;
24 PVOID ReadOnlySharedMemoryHeap;
25 PVOID *ReadOnlyStaticServerData;
26 PVOID AnsiCodePageData;
27 PVOID OemCodePageData;
28 PVOID UnicodeCaseTableData;
29 ULONG NumberOfProcessors;
30 ULONG NtGlobalFlag;
31 BYTE Spare2[0x4];
32 LARGE_INTEGER CriticalSectionTimeout;
33 ULONG HeapSegmentReserve;
34 ULONG HeapSegmentCommit;
35 ULONG HeapDeCommitTotalFreeThreshold;
36 ULONG HeapDeCommitFreeBlockThreshold;
37 ULONG NumberOfHeaps;
38 ULONG MaximumNumberOfHeaps;
39 PVOID **ProcessHeaps;
40 PVOID GdiSharedHandleTable;
41 PVOID ProcessStarterHelper;
42 PVOID GdiDCAttributeList;
43 PVOID LoaderLock;
44 ULONG OSMajorVersion;
45 ULONG OSMinorVersion;
46 ULONG OSBuildNumber;
47 ULONG OSPlatformId;
48 ULONG ImageSubSystem;
49 ULONG ImageSubSystemMajorVersion;
50 ULONG ImageSubSystemMinorVersion;
51 ULONG GdiHandleBuffer[0x22];
52 ULONG PostProcessInitRoutine;
53 ULONG TlsExpansionBitmap;
54 BYTE TlsExpansionBitmapBits[0x80];
55 ULONG SessionId;
56} PEB, *PPEB;
The LoaderData member of PEB structure is of type PEB_LDR_DATA,as you can see,it's at the 0x0c offset from the head of PEB,and it is defined as below:
1typedef struct _PEB {
2 BOOLEAN InheritedAddressSpace;
3 BOOLEAN ReadImageFileExecOptions;
4 BOOLEAN BeingDebugged;
5 BOOLEAN Spare;
6 HANDLE Mutant;
7 PVOID ImageBaseAddress;
8 PPEB_LDR_DATA LoaderData;
9 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
10 PVOID SubSystemData;
11 PVOID ProcessHeap;
12 PVOID FastPebLock;
13 PPEBLOCKROUTINE FastPebLockRoutine;
14 PPEBLOCKROUTINE FastPebUnlockRoutine;
15 ULONG EnvironmentUpdateCount;
16 PVOID *KernelCallbackTable;
17 PVOID EventLogSection;
18 PVOID EventLog;
19 PPEB_FREE_BLOCK FreeList;
20 ULONG TlsExpansionCounter;
21 PVOID TlsBitmap;
22 ULONG TlsBitmapBits[0x2];
23 PVOID ReadOnlySharedMemoryBase;
24 PVOID ReadOnlySharedMemoryHeap;
25 PVOID *ReadOnlyStaticServerData;
26 PVOID AnsiCodePageData;
27 PVOID OemCodePageData;
28 PVOID UnicodeCaseTableData;
29 ULONG NumberOfProcessors;
30 ULONG NtGlobalFlag;
31 BYTE Spare2[0x4];
32 LARGE_INTEGER CriticalSectionTimeout;
33 ULONG HeapSegmentReserve;
34 ULONG HeapSegmentCommit;
35 ULONG HeapDeCommitTotalFreeThreshold;
36 ULONG HeapDeCommitFreeBlockThreshold;
37 ULONG NumberOfHeaps;
38 ULONG MaximumNumberOfHeaps;
39 PVOID **ProcessHeaps;
40 PVOID GdiSharedHandleTable;
41 PVOID ProcessStarterHelper;
42 PVOID GdiDCAttributeList;
43 PVOID LoaderLock;
44 ULONG OSMajorVersion;
45 ULONG OSMinorVersion;
46 ULONG OSBuildNumber;
47 ULONG OSPlatformId;
48 ULONG ImageSubSystem;
49 ULONG ImageSubSystemMajorVersion;
50 ULONG ImageSubSystemMinorVersion;
51 ULONG GdiHandleBuffer[0x22];
52 ULONG PostProcessInitRoutine;
53 ULONG TlsExpansionBitmap;
54 BYTE TlsExpansionBitmapBits[0x80];
55 ULONG SessionId;
56} PEB, *PPEB;
Code
1typedef struct _PEB_LDR_DATA {
2 ULONG Length;
3 BOOLEAN Initialized;
4 PVOID SsHandle;
5 LIST_ENTRY InLoadOrderModuleList;
6 LIST_ENTRY InMemoryOrderModuleList;
7 LIST_ENTRY InInitializationOrderModuleList;
8} PEB_LDR_DATA, *PPEB_LDR_DATA;
9
Declaration for LIST_ENTRY:
1typedef struct _PEB_LDR_DATA {
2 ULONG Length;
3 BOOLEAN Initialized;
4 PVOID SsHandle;
5 LIST_ENTRY InLoadOrderModuleList;
6 LIST_ENTRY InMemoryOrderModuleList;
7 LIST_ENTRY InInitializationOrderModuleList;
8} PEB_LDR_DATA, *PPEB_LDR_DATA;
9
1
typedef
struct
_LIST_ENTRY
2 {
3 struct _LIST_ENTRY *Flink;
4 struct _LIST_ENTRY *Blink;
5} LIST_ENTRY, * PLIST_ENTRY;
All the modules loaded by the process is cascaded by a list member InInitializationOrderModuleList,and "Kernel32.dll" is always the second item.
2 {
3 struct _LIST_ENTRY *Flink;
4 struct _LIST_ENTRY *Blink;
5} LIST_ENTRY, * PLIST_ENTRY;
The element type of InInitializationOrderModuleList is defined like this:
Code
1typedef struct _LDR_MODULE {
2 LIST_ENTRY InLoadOrderModuleList;
3 LIST_ENTRY InMemoryOrderModuleList;
4 LIST_ENTRY InInitializationOrderModuleList;
5 PVOID BaseAddress;
6 PVOID EntryPoint;
7 ULONG SizeOfImage;
8 UNICODE_STRING FullDllName;
9 UNICODE_STRING BaseDllName;
10 ULONG Flags;
11 SHORT LoadCount;
12 SHORT TlsIndex;
13 LIST_ENTRY HashTableEntry;
14 ULONG TimeDateStamp;
15} LDR_MODULE, *PLDR_MODULE;
So,to get the base address of "kernel32.dll",you can try this:
1typedef struct _LDR_MODULE {
2 LIST_ENTRY InLoadOrderModuleList;
3 LIST_ENTRY InMemoryOrderModuleList;
4 LIST_ENTRY InInitializationOrderModuleList;
5 PVOID BaseAddress;
6 PVOID EntryPoint;
7 ULONG SizeOfImage;
8 UNICODE_STRING FullDllName;
9 UNICODE_STRING BaseDllName;
10 ULONG Flags;
11 SHORT LoadCount;
12 SHORT TlsIndex;
13 LIST_ENTRY HashTableEntry;
14 ULONG TimeDateStamp;
15} LDR_MODULE, *PLDR_MODULE;
Code
1FIND_KERNEL32:
2PUSH ESI;Preserve the ESI register
3XOR EAX,EAX;Zero the EAX register
4MOV EAX,FS:[EAX+0X30];Store the address of PEB in EAX
5TEST EAX,EAX;Bitwidth compare eax with itself
6JS FIND_KERNEL32_9X;If SF is 1 then it is operating on Windows 9x system,other wise it's running on NT.
7MOV EAX,[EAX+0X0C];Extract the pointer to Load data structure.
8MOV ESI,[EAX+0X1C];Extract the first entry in the initialization module list.
9LODSD;Grab the next entry in the list which points to kernel32.dll
10MOV EAX,[EAX+0X08];Grab the module base address and store in EAX
11JMP FIND_KERNEL32_FINISHED;Jump the the end as kernel32.dll has been done.
12FIND_KERNEL32_9X:
13MOV EAX,[EAX+0X34];Stores the pointer at offset 0x34 in EAX
14LEA EAX,[EAX+0X7C];Load the effective address at EAX plus 0x7c to keep us in signed byte range in order to avoid nulls.
15MOV EAX,[EAX+0X3C];Extract the base address of kernel32.dll
16FIND_KERNEL32_FINISHED:
17POP ESI;Restore ESI register
18RET;Return the caller
1FIND_KERNEL32:
2PUSH ESI;Preserve the ESI register
3XOR EAX,EAX;Zero the EAX register
4MOV EAX,FS:[EAX+0X30];Store the address of PEB in EAX
5TEST EAX,EAX;Bitwidth compare eax with itself
6JS FIND_KERNEL32_9X;If SF is 1 then it is operating on Windows 9x system,other wise it's running on NT.
7MOV EAX,[EAX+0X0C];Extract the pointer to Load data structure.
8MOV ESI,[EAX+0X1C];Extract the first entry in the initialization module list.
9LODSD;Grab the next entry in the list which points to kernel32.dll
10MOV EAX,[EAX+0X08];Grab the module base address and store in EAX
11JMP FIND_KERNEL32_FINISHED;Jump the the end as kernel32.dll has been done.
12FIND_KERNEL32_9X:
13MOV EAX,[EAX+0X34];Stores the pointer at offset 0x34 in EAX
14LEA EAX,[EAX+0X7C];Load the effective address at EAX plus 0x7c to keep us in signed byte range in order to avoid nulls.
15MOV EAX,[EAX+0X3C];Extract the base address of kernel32.dll
16FIND_KERNEL32_FINISHED:
17POP ESI;Restore ESI register
18RET;Return the caller