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