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