libPeConv
A library to load, manipulate, dump PE files.
peb_lookup.cpp
Go to the documentation of this file.
1#include "ntddk.h"
2
3#include <peconv/peb_lookup.h>
4
6public:
7 SectionLocker(RTL_CRITICAL_SECTION &_section)
8 : section(_section)
9 {
11 }
12
14 {
16 }
17
18protected:
19 RTL_CRITICAL_SECTION &section;
20};
21
22//here we don't want to use any functions imported form extenal modules
23
24typedef struct _LDR_MODULE {
25 LIST_ENTRY InLoadOrderModuleList;// +0x00
26 LIST_ENTRY InMemoryOrderModuleList;// +0x08
28 void* BaseAddress; // +0x18
29 void* EntryPoint; // +0x1c
33 ULONG Flags;
34 SHORT LoadCount;
35 SHORT TlsIndex;
37 ULONG CheckSum;
40
41inline PPEB get_peb()
42{
43#if defined(_WIN64)
44 return (PPEB)__readgsqword(0x60);
45#else
46 return (PPEB)__readfsdword(0x30);
47/*
48//alternative way to fetch it:
49 LPVOID PEB = NULL;
50 __asm {
51 mov eax, fs:[30h]
52 mov PEB, eax
53 };
54 return (PPEB)PEB;
55
56 or:
57 LPVOID PEB = RtlGetCurrentPeb();
58*/
59#endif
60}
61
62inline WCHAR to_lowercase(WCHAR c1)
63{
64 if (c1 <= L'Z' && c1 >= L'A') {
65 c1 = (c1 - L'A') + L'a';
66 }
67 return c1;
68}
69
70bool is_wanted_module(LPWSTR curr_name, LPWSTR wanted_name)
71{
72 if (wanted_name == NULL || curr_name == NULL) return false;
73
74 WCHAR *curr_end_ptr = curr_name;
75 while (*curr_end_ptr != L'\0') {
76 curr_end_ptr++;
77 }
78 if (curr_end_ptr == curr_name) return false;
79
80 WCHAR *wanted_end_ptr = wanted_name;
81 while (*wanted_end_ptr != L'\0') {
82 wanted_end_ptr++;
83 }
84 if (wanted_end_ptr == wanted_name) return false;
85
86 while ((curr_end_ptr != curr_name) && (wanted_end_ptr != wanted_name)) {
87
88 if (to_lowercase(*wanted_end_ptr) != to_lowercase(*curr_end_ptr)) {
89 return false;
90 }
91 wanted_end_ptr--;
92 curr_end_ptr--;
93 }
94 return true;
95}
96
97HMODULE peconv::get_module_via_peb(IN OPTIONAL LPWSTR module_name)
98{
99 PPEB peb = get_peb();
100 if (!peb) {
101 return NULL;
102 }
103 SectionLocker locker(*peb->LoaderLock);
104 LIST_ENTRY head = peb->Ldr->InLoadOrderModuleList;
105
106 const PLDR_MODULE first_module = *((PLDR_MODULE *)(&head));
107 PLDR_MODULE curr_module = first_module;
108 if (!module_name) {
109 return (HMODULE)(curr_module->BaseAddress);
110 }
111
112 // it is a cyclic list, so if the next record links to the initial one, it means we went throught the full loop
113 do {
114 // this should also work as a terminator, because the BaseAddress of the last module in the cycle is NULL
115 if (curr_module == NULL || curr_module->BaseAddress == NULL) {
116 break;
117 }
118 if (is_wanted_module(curr_module->BaseDllName.Buffer, module_name)) {
119 return (HMODULE)(curr_module->BaseAddress);
120 }
121 curr_module = (PLDR_MODULE)curr_module->InLoadOrderModuleList.Flink;
122
123 } while (curr_module != first_module);
124
125 return NULL;
126}
127
128size_t peconv::get_module_size_via_peb(IN OPTIONAL HMODULE hModule)
129{
130 PPEB peb = get_peb();
131 if (!peb) {
132 return 0;
133 }
134 SectionLocker locker(*peb->LoaderLock);
135 LIST_ENTRY head = peb->Ldr->InLoadOrderModuleList;
136
137 const PLDR_MODULE first_module = *((PLDR_MODULE *)(&head));
138 PLDR_MODULE curr_module = first_module;
139 if (!hModule) {
140 return (size_t)(curr_module->SizeOfImage);
141 }
142
143 // it is a cyclic list, so if the next record links to the initial one, it means we went throught the full loop
144 do {
145 // this should also work as a terminator, because the BaseAddress of the last module in the cycle is NULL
146 if (curr_module == NULL || curr_module->BaseAddress == NULL) {
147 break;
148 }
149 if (hModule == (HMODULE)(curr_module->BaseAddress)) {
150 return (size_t)(curr_module->SizeOfImage);
151 }
152 curr_module = (PLDR_MODULE)curr_module->InLoadOrderModuleList.Flink;
153
154 } while (curr_module != first_module);
155
156 return 0;
157}
158
159bool peconv::set_main_module_in_peb(HMODULE module_ptr)
160{
161 PPEB peb = get_peb();
162 if (peb == NULL) {
163 return false;
164 }
165 SectionLocker locker(*peb->FastPebLock);
166 peb->ImageBaseAddress = module_ptr;
167 return true;
168}
169
171{
172 PPEB peb = get_peb();
173 if (peb == NULL) {
174 return NULL;
175 }
176 SectionLocker locker(*peb->FastPebLock);
177 return (HMODULE) peb->ImageBaseAddress;
178}
SectionLocker(RTL_CRITICAL_SECTION &_section)
Definition: peb_lookup.cpp:7
RTL_CRITICAL_SECTION & section
Definition: peb_lookup.cpp:19
HMODULE get_main_module_via_peb()
Definition: peb_lookup.cpp:170
bool set_main_module_in_peb(HMODULE hModule)
Definition: peb_lookup.cpp:159
size_t get_module_size_via_peb(IN OPTIONAL HMODULE hModule=nullptr)
Definition: peb_lookup.cpp:128
HMODULE get_module_via_peb(IN OPTIONAL LPWSTR module_name=nullptr)
Definition: peb_lookup.cpp:97
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(IN PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(IN PRTL_CRITICAL_SECTION CriticalSection)
bool is_wanted_module(LPWSTR curr_name, LPWSTR wanted_name)
Definition: peb_lookup.cpp:70
struct _LDR_MODULE * PLDR_MODULE
PPEB get_peb()
Definition: peb_lookup.cpp:41
WCHAR to_lowercase(WCHAR c1)
Definition: peb_lookup.cpp:62
struct _LDR_MODULE LDR_MODULE
Functions for retrieving process information from PEB.
LIST_ENTRY InLoadOrderModuleList
Definition: peb_lookup.cpp:25
UNICODE_STRING FullDllName
Definition: peb_lookup.cpp:31
ULONG CheckSum
Definition: peb_lookup.cpp:37
ULONG SizeOfImage
Definition: peb_lookup.cpp:30
SHORT TlsIndex
Definition: peb_lookup.cpp:35
HANDLE SectionHandle
Definition: peb_lookup.cpp:36
ULONG TimeDateStamp
Definition: peb_lookup.cpp:38
void * EntryPoint
Definition: peb_lookup.cpp:29
LIST_ENTRY InMemoryOrderModuleList
Definition: peb_lookup.cpp:26
void * BaseAddress
Definition: peb_lookup.cpp:28
UNICODE_STRING BaseDllName
Definition: peb_lookup.cpp:32
SHORT LoadCount
Definition: peb_lookup.cpp:34
LIST_ENTRY InInitializationOrderModuleList
Definition: peb_lookup.cpp:27
LIST_ENTRY InLoadOrderModuleList
Definition: ntddk.h:2662
Definition: ntddk.h:2698
PRTL_CRITICAL_SECTION LoaderLock
Definition: ntddk.h:2769
PPEB_LDR_DATA Ldr
Definition: ntddk.h:2707
PVOID ImageBaseAddress
Definition: ntddk.h:2706
PRTL_CRITICAL_SECTION FastPebLock
Definition: ntddk.h:2711
PWSTR Buffer
Definition: ntddk.h:83