BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
RelocDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4/*
5// Based relocation format.
6
7typedef struct _IMAGE_BASE_RELOCATION {
8 DWORD VirtualAddress;
9 DWORD SizeOfBlock;
10 // WORD TypeOffset[1];
11} IMAGE_BASE_RELOCATION;
12typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
13
14
15//Based relocation types.
16
17enum reloc_based {
18 RELB_ABSOLUTE = 0,
19 RELB_HIGH = 1,
20 RELB_LOW = 2,
21 RELB_HIGHLOW = 3,
22 RELB_HIGHADJ = 4,
23 RELB_MIPS_JMPADDR = 5,
24 RELB_SECTION = 6,
25 RELB_REL32 = 7,
26 RELB_MIPS_JMPADDR16 = 9,
27 RELB_IA64_IMM64 = 9,
28 RELB_DIR64 = 10,
29 RELB_HIGH3ADJ = 11
30};
31
32*/
33
35{
36 clear();
37 this->parsedSize = 0;
38 this->invalidEntries = 0;
39
40 const size_t INVALID_SERIES_LIMIT = 10;
41 const size_t INVALID_ENTRIES_LIMIT = 20;
43 size_t entryId = 0;
44 size_t invalidSeries = 0;
45 while (parsedSize < maxSize) {
46 RelocBlockWrapper* entry = new RelocBlockWrapper(this->m_Exe, this, entryId++);
47 if (!entry) break;
48
49 bool isOk1 = false;
51 if (!isOk1 || !blockSize || !entry->getPtr()) {
52 delete entry;
53 break;
54 }
55 if (entry->isValid()) {
56 invalidSeries = 0;
57 }
58 else {
60 this->invalidEntries++;
62 if (invalidEntries >= INVALID_ENTRIES_LIMIT) break;
63 }
64 this->parsedSize += blockSize;
65 this->entries.push_back(entry);
66
67 }
68 return true;
69}
70
81
82//----------------
83
85{
86 clear();
87 this->parsedSize = 0;
88 this->invalidEntries = 0;
89
91 if (!reloc) return false;
92
93 const size_t INVALID_SERIES_LIMIT = 100;
94 const size_t INVALID_ENTRIES_LIMIT = 1000;
95 size_t maxSize = reloc->SizeOfBlock;
96 parsedSize = sizeof(IMAGE_BASE_RELOCATION); // the block begins with IMAGE_BASE_RELOCATION record
97 size_t entryId = 0;
98 size_t invalidSeries = 0;
99 while (parsedSize < maxSize) {
100 RelocEntryWrapper* entry = new RelocEntryWrapper(this->m_Exe, this, entryId++);
101 if (!entry->getPtr()) {
102 delete entry;
103 break;
104 }
105 if (entry->isValid() && !entry->isEmpty()) {
106 invalidSeries = 0;
107 }
108 else {
110 this->invalidEntries++;
112 if (invalidEntries >= INVALID_ENTRIES_LIMIT) break;
113 }
114 this->parsedSize += sizeof(pe::BASE_RELOCATION_ENTRY);
115 this->entries.push_back(entry);
116 }
117 return true;
118}
119
121{
122 if (this->invalidEntries > 0) return false;
123
124 if (!parentDir) return false;
125 PEFile *m_PE = parentDir->m_PE;
126 if (!m_PE) return false;
127
128 bool isOk = false;
130 if (!isOk) return false;
131
132 const bool isValidRVA = (pageRva < m_PE->getImageSize()) ? true : false;
133 return isValidRVA;
134}
135
137{
138 if (this->parentDir == NULL) return NULL;
139 IMAGE_BASE_RELOCATION* reloc = this->parentDir->reloc();
140 if (!reloc) return NULL;
141
143 BYTE *ptr = NULL;
144
145 // use my cached:
146 if (this->cachedRaw != INVALID_ADDR) {
147 ptr = m_Exe->getContentAt(this->cachedRaw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
148 return ptr;
149 }
150
151 // use previous cached to calculate my cached
152 size_t prevNum = this->entryNum - 1;
153
154 RelocBlockWrapper *prevEntry = dynamic_cast<RelocBlockWrapper*> (this->parentDir->getEntryAt(prevNum));
155 if (prevEntry) {
156 offset_t prevRaw = prevEntry->cachedRaw;
157
159 raw = prevRaw + prevReloc->SizeOfBlock;
160
161 if (prevRaw != INVALID_ADDR) {
163
164 if (ptr != NULL) {
165 this->cachedRaw = raw;
166 return ptr;
167 }
168 }
169 }
170 // previous cached not avaliable, calculate...
171 offset_t firstRaw = this->getOffset(reloc);
172 offset_t blockSize = reloc->SizeOfBlock;
173
174 raw = firstRaw;
175 ptr = (BYTE*) reloc;
176
177 for ( size_t i = 0; i < this->entryNum; i++) { //TODO: make caching
178 raw += blockSize;
179
181 if (!ptr) return NULL;
182
183 reloc = (IMAGE_BASE_RELOCATION*) ptr;
184 blockSize = reloc->SizeOfBlock;
185 }
186
187 this->cachedRaw = raw;
188 return ptr;
189}
190
192{
193 if (this->parentDir == NULL) return 0;
195 if (!reloc) return 0;
196
197 if (reloc->SizeOfBlock > 0) return reloc->SizeOfBlock;
198
199 return sizeof(IMAGE_BASE_RELOCATION);
200}
201
203{
205 if (!reloc) return NULL;
206
207 switch (fieldId) {
208 case PAGE_VA: return (void*) &reloc->VirtualAddress;
209 case BLOCK_SIZE : return (void*) &reloc->SizeOfBlock;
210 case ENTRIES_PTR :
211 {
212 BYTE *blockSizePtr = (BYTE*) &reloc->SizeOfBlock;
213 return blockSizePtr + sizeof(DWORD);
214 }
215 }
216 return getPtr();
217}
218
220{
221 switch (fieldId) {
222 case BLOCK_SIZE : return "Block Size";
223 case PAGE_VA: return "Page RVA";
224 case ENTRIES_PTR: return "Entries";
225 }
226 return getName();
227}
228
230{
231 switch (fieldId) {
232 case PAGE_VA:
233 return Executable::RVA;
234 }
236}
237
245
247{
250
251 if (entriesPtr == NULL || entriesSize == 0) return NULL;
252
254 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, sizeof(WORD));
255
256 return ptr;
257}
258
260{
261 if (this->cachedMaxNum > 0) return this->cachedMaxNum;
262
264 if (!reloc) return 0;
265
268
269 offset_t fileSize = m_Exe->getRawSize();
270 if (entriesOffset + entriesSize > fileSize) {
271 entriesSize = fileSize - entriesOffset; // truncate to fileSize
272 }
273
274 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, entriesSize);
275
277 if (ptr) {
278 entriesNum = entriesSize / sizeof(WORD); //sizeof(BASE_RELOCATION_ENTRY);
279 }
280 this->cachedMaxNum = entriesNum;
281 return entriesNum;
282}
283//-------------------------------------------------------------------------------------------------
285{
286 if (!getPtr()) return false;
287
288 bool isOk = false;
290 if (!isOk) return false;
291
293 if (relocType != 0 && relocType != 3 && relocType != 10) {
294 return false;
295 }
296 return true;
297}
298
300{
301 if (!getPtr()) return true;
302
303 bool isOk = false;
305 if (!isOk) return true;
306
307 if (val == 0) return true;
308
310 if (relocType == 0) {
311 return true;
312 }
313 return false;
314}
315
317{
318 if (this->parentDir == NULL) return NULL;
319
320 size_t maxNum = this->parentDir->maxEntriesNumInBlock();
321 if (this->entryNum >= maxNum) return NULL;
322
323 WORD* entriesPtr = (WORD* ) parentDir->getEntriesPtr();
324 if (entriesPtr == NULL) return NULL;
325
326 WORD* ptr = &entriesPtr[this->entryNum];
327 return ptr;
328}
329
331{
332 if (this->parentDir == NULL) return 0;
333 return sizeof(WORD);
334}
335
337{
338 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
339 return entry->Type;
340}
341
343{
344 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
345 return entry->Offset;
346}
347
349{
350 switch (relocType) {
351 case 0 : return "Padding (skipped)";
352 case 1 : return "High WORD of 32-bit field";
353 case 2 : return "Low WORD of 32-bit field";
354 case 3 : return "32 bit field";
355 case 4 : return "HighAdj";
356 case 5 : return "MIPS JumpAddr";
357 case 6 : case 7 : return "Reserved";
358 case 9 : return "MIPS16 JumpAddr";
359 case 10 : return "64 bit field";
360 }
361 return "";
362}
363
365{
366 if (this->parentDir == NULL) return INVALID_ADDR;
367
368 IMAGE_BASE_RELOCATION* reloc = parentDir->myReloc();
369 if (reloc == NULL) return INVALID_ADDR;
370
371 offset_t offset = static_cast<offset_t>(reloc->VirtualAddress + delta);
372 return offset;
373}
374
INT_TYPE _getNumValue(void *ptr)
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
bufsize_t getDirEntrySize(bool trimToExeSize=false)
offset_t getDirEntryAddress()
virtual bufsize_t getFieldSize(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getFieldOffset(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getOffset()
virtual uint64_t getNumValue(size_t fieldId, size_t subField, bool *isOk)
virtual ExeNodeWrapper * getEntryAt(size_t fieldId)
std::vector< ExeNodeWrapper * > entries
virtual void clear()
BYTE * getContentAt(offset_t offset, bufsize_t size, bool allowExceptions=false)
Definition Executable.h:57
virtual offset_t getRawSize() const
Definition Executable.h:54
virtual bufsize_t getImageSize()
Definition Executable.h:66
virtual QString getFieldName(size_t fieldId)
virtual WrappedValue::data_type containsDataType(size_t fieldId, size_t subField)
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
virtual void * getPtr()
virtual QString getName()
virtual bufsize_t getSize()
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField)
virtual bool isValid()
IMAGE_BASE_RELOCATION * myReloc()
friend class RelocBlockWrapper
IMAGE_BASE_RELOCATION * reloc()
offset_t deltaToRVA(WORD delta)
static QString translateType(WORD type)
@ RELOC_ENTRY_VAL
bool isEmpty()
virtual void * getPtr()
virtual bool isValid()
virtual bufsize_t getSize()
static WORD getDelta(WORD relocEntryVal)
static WORD getType(WORD relocEntryVal)