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 size_t emptySeries = 0;
100 while (parsedSize < maxSize) {
101 RelocEntryWrapper* entry = new RelocEntryWrapper(this->m_Exe, this, entryId++);
102 if (!entry->getPtr()) {
103 delete entry;
104 break;
105 }
106 if (entry->isValid()) {
107 invalidSeries = 0;
108 }
109 else {
111 this->invalidEntries++;
113 if (invalidEntries >= INVALID_ENTRIES_LIMIT) break;
114 }
115 if (!entry->isEmpty()) {
116 emptySeries = 0;
117 } else {
118 emptySeries++;
120 this->invalidEntries++;
121 break;
122 }
123 }
124 this->parsedSize += sizeof(pe::BASE_RELOCATION_ENTRY);
125 this->entries.push_back(entry);
126 }
127 return true;
128}
129
131{
132 if (this->invalidEntries > 0) return false;
133
134 if (!parentDir) return false;
135 PEFile *m_PE = parentDir->m_PE;
136 if (!m_PE) return false;
137
138 bool isOk = false;
140 if (!isOk) return false;
141
142 const bool isValidRVA = (pageRva < m_PE->getImageSize()) ? true : false;
143 return isValidRVA;
144}
145
147{
148 if (this->parentDir == NULL) return NULL;
149 IMAGE_BASE_RELOCATION* reloc = this->parentDir->reloc();
150 if (!reloc) return NULL;
151
153 BYTE *ptr = NULL;
154
155 // use my cached:
156 if (this->cachedRaw != INVALID_ADDR) {
157 ptr = m_Exe->getContentAt(this->cachedRaw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
158 return ptr;
159 }
160
161 // use previous cached to calculate my cached
162 size_t prevNum = this->entryNum - 1;
163
164 RelocBlockWrapper *prevEntry = dynamic_cast<RelocBlockWrapper*> (this->parentDir->getEntryAt(prevNum));
165 if (prevEntry) {
166 offset_t prevRaw = prevEntry->cachedRaw;
167
169 raw = prevRaw + prevReloc->SizeOfBlock;
170
171 if (prevRaw != INVALID_ADDR) {
173
174 if (ptr != NULL) {
175 this->cachedRaw = raw;
176 return ptr;
177 }
178 }
179 }
180 // previous cached not avaliable, calculate...
181 offset_t firstRaw = this->getOffset(reloc);
182 offset_t blockSize = reloc->SizeOfBlock;
183
184 raw = firstRaw;
185 ptr = (BYTE*) reloc;
186
187 for ( size_t i = 0; i < this->entryNum; i++) { //TODO: make caching
188 raw += blockSize;
189
191 if (!ptr) return NULL;
192
193 reloc = (IMAGE_BASE_RELOCATION*) ptr;
194 blockSize = reloc->SizeOfBlock;
195 }
196
197 this->cachedRaw = raw;
198 return ptr;
199}
200
202{
203 if (this->parentDir == NULL) return 0;
205 if (!reloc) return 0;
206
207 if (reloc->SizeOfBlock > 0) return reloc->SizeOfBlock;
208
209 return sizeof(IMAGE_BASE_RELOCATION);
210}
211
213{
215 if (!reloc) return NULL;
216
217 switch (fieldId) {
218 case PAGE_VA: return (void*) &reloc->VirtualAddress;
219 case BLOCK_SIZE : return (void*) &reloc->SizeOfBlock;
220 case ENTRIES_PTR :
221 {
222 BYTE *blockSizePtr = (BYTE*) &reloc->SizeOfBlock;
223 return blockSizePtr + sizeof(DWORD);
224 }
225 }
226 return getPtr();
227}
228
230{
231 switch (fieldId) {
232 case BLOCK_SIZE : return "Block Size";
233 case PAGE_VA: return "Page RVA";
234 case ENTRIES_PTR: return "Entries";
235 }
236 return getName();
237}
238
240{
241 switch (fieldId) {
242 case PAGE_VA:
243 return Executable::RVA;
244 }
246}
247
255
257{
260
261 if (entriesPtr == NULL || entriesSize == 0) return NULL;
262
264 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, sizeof(WORD));
265
266 return ptr;
267}
268
270{
271 if (this->cachedMaxNum > 0) return this->cachedMaxNum;
272
274 if (!reloc) return 0;
275
278
279 offset_t fileSize = m_Exe->getRawSize();
280 if (entriesOffset + entriesSize > fileSize) {
281 entriesSize = fileSize - entriesOffset; // truncate to fileSize
282 }
283
284 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, entriesSize);
285
287 if (ptr) {
288 entriesNum = entriesSize / sizeof(WORD); //sizeof(BASE_RELOCATION_ENTRY);
289 }
290 this->cachedMaxNum = entriesNum;
291 return entriesNum;
292}
293//-------------------------------------------------------------------------------------------------
295{
296 if (!getPtr()) return false;
297
298 bool isOk = false;
300 if (!isOk) return false;
301
303 if (relocType != 0 && relocType != 3 && relocType != 10) {
304 return false;
305 }
306 return true;
307}
308
310{
311 if (!getPtr()) return true;
312
313 bool isOk = false;
315 if (!isOk) return true;
316
317 if (val == 0) return true;
318
320 if (relocType == 0) {
321 return true;
322 }
323 return false;
324}
325
327{
328 if (this->parentDir == NULL) return NULL;
329
330 size_t maxNum = this->parentDir->maxEntriesNumInBlock();
331 if (this->entryNum >= maxNum) return NULL;
332
333 WORD* entriesPtr = (WORD* ) parentDir->getEntriesPtr();
334 if (entriesPtr == NULL) return NULL;
335
336 WORD* ptr = &entriesPtr[this->entryNum];
337 return ptr;
338}
339
341{
342 if (this->parentDir == NULL) return 0;
343 return sizeof(WORD);
344}
345
347{
348 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
349 return entry->Type;
350}
351
353{
354 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
355 return entry->Offset;
356}
357
359{
360 switch (relocType) {
361 case 0 : return "Padding (skipped)";
362 case 1 : return "High WORD of 32-bit field";
363 case 2 : return "Low WORD of 32-bit field";
364 case 3 : return "32 bit field";
365 case 4 : return "HighAdj";
366 case 5 : return "MIPS JumpAddr";
367 case 6 : case 7 : return "Reserved";
368 case 9 : return "MIPS16 JumpAddr";
369 case 10 : return "64 bit field";
370 }
371 return "";
372}
373
375{
376 if (this->parentDir == NULL) return INVALID_ADDR;
377
378 IMAGE_BASE_RELOCATION* reloc = parentDir->myReloc();
379 if (reloc == NULL) return INVALID_ADDR;
380
381 offset_t offset = static_cast<offset_t>(reloc->VirtualAddress + delta);
382 return offset;
383}
384
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)