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
39 bufsize_t maxSize = getDirEntrySize(true);
40 size_t entryId = 0;
41 while (parsedSize < maxSize) {
42 RelocBlockWrapper* entry = new RelocBlockWrapper(this->m_Exe, this, entryId++);
43 if (!entry) break;
44
45 bool isOk1 = false;
46 const bufsize_t blockSize = (bufsize_t) entry->getNumValue(RelocBlockWrapper::BLOCK_SIZE, &isOk1);
47 if (!isOk1 || !blockSize || !entry->getPtr()) {
48 delete entry;
49 break;
50 }
51 this->parsedSize += blockSize;
52 this->entries.push_back(entry);
53 if (!entry->isValid()) {
54 break;
55 }
56 }
57 return true;
58}
59
60
61
62IMAGE_BASE_RELOCATION* RelocDirWrapper::reloc()
63{
65
66 BYTE *ptr = m_Exe->getContentAt(rva, Executable::RVA, sizeof(IMAGE_BASE_RELOCATION));
67 if (ptr == NULL) return NULL;
68
69 IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION*) ptr;
70 return reloc;
71}
72
73//----------------
74
76{
77 clear();
78 parsedSize = 0;
79
80 IMAGE_BASE_RELOCATION* reloc = myReloc();
81 if (!reloc) return false;
82
83 validatePage();
84 if (!this->isValidPage) return false;
85
86 size_t maxSize = reloc->SizeOfBlock;
87 parsedSize = sizeof(IMAGE_BASE_RELOCATION); // the block begins with IMAGE_BASE_RELOCATION record
88 size_t entryId = 0;
89
90 while (parsedSize < maxSize) {
91 RelocEntryWrapper* entry = new RelocEntryWrapper(this->m_Exe, this, entryId++);
92
93 if (!entry->getPtr()) {
94 delete entry;
95 break;
96 }
97 this->parsedSize += sizeof(pe::BASE_RELOCATION_ENTRY);
98 this->entries.push_back(entry);
99 }
100 return true;
101}
102
103void RelocBlockWrapper::validatePage()
104{
105 this->isValidPage = false;
106 if (!parentDir) return;
107 PEFile *m_PE = parentDir->m_PE;
108 if (!m_PE) return;
109
110 bool isOk = false;
111 const offset_t pageRva = this->getNumValue(RelocBlockWrapper::PAGE_VA, &isOk);
112 if (!isOk) return;
113
114 this->isValidPage = (pageRva < m_PE->getImageSize()) ? true : false;
115}
116
118{
119 return this->isValidPage;
120}
121
123{
124 if (this->parentDir == NULL) return NULL;
125 IMAGE_BASE_RELOCATION* reloc = this->parentDir->reloc();
126 if (!reloc) return NULL;
127
129 BYTE *ptr = NULL;
130
131 // use my cached:
132 if (this->cachedRaw != INVALID_ADDR) {
133 ptr = m_Exe->getContentAt(this->cachedRaw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
134 return ptr;
135 }
136
137 // use previous cached to calculate my cached
138 size_t prevNum = this->entryNum - 1;
139
140 RelocBlockWrapper *prevEntry = dynamic_cast<RelocBlockWrapper*> (this->parentDir->getEntryAt(prevNum));
141 if (prevEntry) {
142 offset_t prevRaw = prevEntry->cachedRaw;
143
144 IMAGE_BASE_RELOCATION* prevReloc = (IMAGE_BASE_RELOCATION*) prevEntry->getPtr();
145 raw = prevRaw + prevReloc->SizeOfBlock;
146
147 if (prevRaw != INVALID_ADDR) {
148 ptr = m_Exe->getContentAt(raw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
149
150 if (ptr != NULL) {
151 this->cachedRaw = raw;
152 return ptr;
153 }
154 }
155 }
156 // previous cached not avaliable, calculate...
157 offset_t firstRaw = this->getOffset(reloc);
158 offset_t blockSize = reloc->SizeOfBlock;
159
160 raw = firstRaw;
161 ptr = (BYTE*) reloc;
162
163 for ( size_t i = 0; i < this->entryNum; i++) { //TODO: make caching
164 raw += blockSize;
165
166 ptr = m_Exe->getContentAt(raw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
167 if (!ptr) return NULL;
168
169 reloc = (IMAGE_BASE_RELOCATION*) ptr;
170 blockSize = reloc->SizeOfBlock;
171 }
172
173 this->cachedRaw = raw;
174 return ptr;
175}
176
178{
179 if (this->parentDir == NULL) return 0;
180 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
181 if (!reloc) return 0;
182
183 if (reloc->SizeOfBlock > 0) return reloc->SizeOfBlock;
184
185 return sizeof(IMAGE_BASE_RELOCATION);
186}
187
188void* RelocBlockWrapper::getFieldPtr(size_t fieldId, size_t subField)
189{
190 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
191 if (!reloc) return NULL;
192
193 switch (fieldId) {
194 case PAGE_VA: return (void*) &reloc->VirtualAddress;
195 case BLOCK_SIZE : return (void*) &reloc->SizeOfBlock;
196 case ENTRIES_PTR :
197 {
198 BYTE *blockSizePtr = (BYTE*) &reloc->SizeOfBlock;
199 return blockSizePtr + sizeof(DWORD);
200 }
201 }
202 return getPtr();
203}
204
205QString RelocBlockWrapper::getFieldName(size_t fieldId)
206{
207 switch (fieldId) {
208 case BLOCK_SIZE : return "Block Size";
209 case PAGE_VA: return "Page RVA";
210 case ENTRIES_PTR: return "Entries";
211 }
212 return getName();
213}
214
216{
217 switch (fieldId) {
218 case PAGE_VA:
219 return Executable::RVA;
220 }
222}
223
225{
226 if (fieldId == ENTRIES_PTR){
228 }
229 return WrappedValue::INT;
230}
231
233{
234 void *entriesPtr = getFieldPtr(ENTRIES_PTR);
235 size_t entriesSize = getFieldSize(ENTRIES_PTR);
236
237 if (entriesPtr == NULL || entriesSize == 0) return NULL;
238
239 offset_t entriesOffset = getFieldOffset(ENTRIES_PTR);
240 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, sizeof(WORD));
241
242 return ptr;
243}
244
246{
247 if (this->cachedMaxNum > 0) return this->cachedMaxNum;
248
249 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
250 if (!reloc) return 0;
251
252 bufsize_t entriesSize = getFieldSize(ENTRIES_PTR);
253 offset_t entriesOffset = getFieldOffset(ENTRIES_PTR);
254
255 offset_t fileSize = m_Exe->getRawSize();
256 if (entriesOffset + entriesSize > fileSize) {
257 entriesSize = fileSize - entriesOffset; // truncate to fileSize
258 }
259
260 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, entriesSize);
261
262 bufsize_t entriesNum = 0;
263 if (ptr) {
264 entriesNum = entriesSize / sizeof(WORD); //sizeof(BASE_RELOCATION_ENTRY);
265 }
266 this->cachedMaxNum = entriesNum;
267 return entriesNum;
268}
269//-------------------------------------------------------------------------------------------------
270
272{
273 if (this->parentDir == NULL) return NULL;
274
275 size_t maxNum = this->parentDir->maxEntriesNumInBlock();
276 if (this->entryNum >= maxNum) return NULL;
277
278 WORD* entriesPtr = (WORD* ) parentDir->getEntriesPtr();
279 if (entriesPtr == NULL) return NULL;
280
281 WORD* ptr = &entriesPtr[this->entryNum];
282 return ptr;
283}
284
286{
287 if (this->parentDir == NULL) return 0;
288 return sizeof(WORD);
289}
290
291WORD RelocEntryWrapper::getType(WORD relocEntryVal)
292{
293 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
294 return entry->Type;
295}
296
297WORD RelocEntryWrapper::getDelta(WORD relocEntryVal)
298{
299 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
300 return entry->Offset;
301}
302
304{
305 switch (type) {
306 case 0 : return "Padding (skipped)";
307 case 1 : return "High WORD of 32-bit field";
308 case 2 : return "Low WORD of 32-bit field";
309 case 3 : return "32 bit field";
310 case 4 : return "HighAdj";
311 case 5 : return "MIPS JumpAddr";
312 case 6 : case 7 : return "Reserved";
313 case 9 : return "MIPS16 JumpAddr";
314 case 10 : return "64 bit field";
315 }
316 return "";
317}
318
320{
321 if (this->parentDir == NULL) return INVALID_ADDR;
322
323 IMAGE_BASE_RELOCATION* reloc = parentDir->myReloc();
324 if (reloc == NULL) return INVALID_ADDR;
325
326 offset_t offset = static_cast<offset_t>(reloc->VirtualAddress + delta);
327 return offset;
328}
329
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:65
virtual offset_t getRawSize() const
Definition Executable.h:62
virtual bufsize_t getImageSize()
Definition Executable.h:74
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)
IMAGE_BASE_RELOCATION * myReloc()
friend class RelocBlockWrapper
IMAGE_BASE_RELOCATION * reloc()
offset_t deltaToRVA(WORD delta)
static QString translateType(WORD type)
virtual void * getPtr()
virtual bufsize_t getSize()
static WORD getDelta(WORD relocEntryVal)
static WORD getType(WORD relocEntryVal)