BearParser
Portable Executable parsing library (from PE-bear)
RelocDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4size_t RelocDirWrapper::EntriesLimit = 10000;
5
6/*
7// Based relocation format.
8
9typedef struct _IMAGE_BASE_RELOCATION {
10 DWORD VirtualAddress;
11 DWORD SizeOfBlock;
12 // WORD TypeOffset[1];
13} IMAGE_BASE_RELOCATION;
14typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
15
16
17//Based relocation types.
18
19enum reloc_based {
20 RELB_ABSOLUTE = 0,
21 RELB_HIGH = 1,
22 RELB_LOW = 2,
23 RELB_HIGHLOW = 3,
24 RELB_HIGHADJ = 4,
25 RELB_MIPS_JMPADDR = 5,
26 RELB_SECTION = 6,
27 RELB_REL32 = 7,
28 RELB_MIPS_JMPADDR16 = 9,
29 RELB_IA64_IMM64 = 9,
30 RELB_DIR64 = 10,
31 RELB_HIGH3ADJ = 11
32};
33
34*/
35
37{
38 clear();
39 parsedSize = 0;
40 bufsize_t maxSize = getDirEntrySize();
41
42 for (size_t i = 0; i < RelocDirWrapper::EntriesLimit && parsedSize < maxSize; i++) {
43 RelocBlockWrapper* entry = new RelocBlockWrapper(this->m_Exe, this, i);
44
45 if (entry->getPtr() == NULL) {
46 delete entry;
47 break;
48 }
49 bool isOk = false;
51
52 this->parsedSize += val;
53 this->entries.push_back(entry);
54
55 }
56 return true;
57}
58
59
60IMAGE_BASE_RELOCATION* RelocDirWrapper::reloc()
61{
63
64 BYTE *ptr = m_Exe->getContentAt(rva, Executable::RVA, sizeof(IMAGE_BASE_RELOCATION));
65 if (ptr == NULL) return NULL;
66
67 IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION*) ptr;
68 return reloc;
69}
70
71//----------------
72
74{
75 clear();
76 parsedSize = 0;
77
78 IMAGE_BASE_RELOCATION* reloc = myReloc();
79 if (!reloc) return false;
80
81 size_t maxSize = reloc->SizeOfBlock;
82 parsedSize = sizeof(reloc->VirtualAddress) + sizeof(reloc->SizeOfBlock);
83
84 for (size_t i = 0; i < RelocDirWrapper::EntriesLimit && parsedSize < maxSize; i++) {
85 RelocEntryWrapper* entry = new RelocEntryWrapper(this->m_Exe, this, i);
86
87 if (entry->getPtr() == NULL) {
88 delete entry;
89 break;
90 }
91 bool isOk = false;
92 size_t val = sizeof(WORD);
93
94 this->parsedSize += val;
95 this->entries.push_back(entry);
96 }
97 return true;
98}
99
100
102{
103 if (this->parentDir == NULL) return NULL;
104 IMAGE_BASE_RELOCATION* reloc = this->parentDir->reloc();
105 if (!reloc) return NULL;
106
108 BYTE *ptr = NULL;
109
110 // use my cached:
111 if (this->cachedRaw != INVALID_ADDR) {
112 ptr = m_Exe->getContentAt(this->cachedRaw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
113 return ptr;
114 }
115
116 // use previous cached to calculate my cached
117 size_t prevNum = this->entryNum - 1;
118
119 RelocBlockWrapper *prevEntry = dynamic_cast<RelocBlockWrapper*> (this->parentDir->getEntryAt(prevNum));
120 if (prevEntry) {
121 offset_t prevRaw = prevEntry->cachedRaw;
122
123 IMAGE_BASE_RELOCATION* prevReloc = (IMAGE_BASE_RELOCATION*) prevEntry->getPtr();
124 raw = prevRaw + prevReloc->SizeOfBlock;
125
126 if (prevRaw != INVALID_ADDR) {
127 ptr = m_Exe->getContentAt(raw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
128
129 if (ptr != NULL) {
130 this->cachedRaw = raw;
131 return ptr;
132 }
133 }
134 }
135 // previous cached not avaliable, calculate...
136 offset_t firstRaw = this->getOffset(reloc);
137 offset_t blockSize = reloc->SizeOfBlock;
138
139 raw = firstRaw;
140 ptr = (BYTE*) reloc;
141
142 for ( size_t i = 0; i < this->entryNum; i++) { //TODO: make caching
143 raw += blockSize;
144
145 ptr = m_Exe->getContentAt(raw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
146 if (!ptr) return NULL;
147
148 reloc = (IMAGE_BASE_RELOCATION*) ptr;
149 blockSize = reloc->SizeOfBlock;
150 }
151
152 this->cachedRaw = raw;
153 return ptr;
154}
155
157{
158 if (this->parentDir == NULL) return 0;
159 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
160 if (!reloc) return 0;
161
162 if (reloc->SizeOfBlock > 0) return reloc->SizeOfBlock;
163
164 return sizeof(IMAGE_BASE_RELOCATION);
165}
166
167void* RelocBlockWrapper::getFieldPtr(size_t fieldId, size_t subField)
168{
169 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
170 if (!reloc) return NULL;
171
172 switch (fieldId) {
173 case PAGE_VA: return (void*) &reloc->VirtualAddress;
174 case BLOCK_SIZE : return (void*) &reloc->SizeOfBlock;
175 case ENTRIES_PTR :
176 {
177 BYTE *blockSizePtr = (BYTE*) &reloc->SizeOfBlock;
178 return blockSizePtr + sizeof(DWORD);
179 }
180 }
181 return getPtr();
182}
183
184QString RelocBlockWrapper::getFieldName(size_t fieldId)
185{
186 switch (fieldId) {
187 case BLOCK_SIZE : return "Block Size";
188 case PAGE_VA: return "Page RVA";
189 case ENTRIES_PTR: return "Entries";
190 }
191 return getName();
192}
193
195{
196 switch (fieldId) {
197 case PAGE_VA:
198 return Executable::RVA;
199 }
201}
202
204{
205 if (fieldId == ENTRIES_PTR){
207 }
208 return WrappedValue::INT;
209}
210
212{
213 void *entriesPtr = getFieldPtr(ENTRIES_PTR);
214 size_t entriesSize = getFieldSize(ENTRIES_PTR);
215
216 if (entriesPtr == NULL || entriesSize == 0) return NULL;
217
218 offset_t entriesOffset = getFieldOffset(ENTRIES_PTR);
219 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, sizeof(WORD));
220
221 return ptr;
222}
223
225{
226 if (this->cachedMaxNum > 0) return this->cachedMaxNum;
227
228 IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*) this->getPtr();
229 if (!reloc) return 0;
230
231 bufsize_t entriesSize = getFieldSize(ENTRIES_PTR);
232 offset_t entriesOffset = getFieldOffset(ENTRIES_PTR);
233
234 offset_t fileSize = m_Exe->getRawSize();
235 if (entriesOffset + entriesSize > fileSize) {
236 entriesSize = fileSize - entriesOffset; // truncate to fileSize
237 }
238
239 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, entriesSize);
240
241 bufsize_t entriesNum = 0;
242 if (ptr) {
243 entriesNum = entriesSize / sizeof(WORD); //sizeof(BASE_RELOCATION_ENTRY);
244 }
245 this->cachedMaxNum = entriesNum;
246 return entriesNum;
247}
248//-------------------------------------------------------------------------------------------------
249
251{
252 if (this->parentDir == NULL) return NULL;
253
254 size_t maxNum = this->parentDir->maxEntriesNumInBlock();
255 if (this->entryNum >= maxNum) return NULL;
256
257 WORD* entriesPtr = (WORD* ) parentDir->getEntriesPtr();
258 if (entriesPtr == NULL) return NULL;
259
260 WORD* ptr = &entriesPtr[this->entryNum];
261 return ptr;
262}
263
265{
266 if (this->parentDir == NULL) return 0;
267 return sizeof(WORD);
268}
269
270WORD RelocEntryWrapper::getType(WORD relocEntryVal)
271{
272 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
273 return entry->Type;
274}
275
276WORD RelocEntryWrapper::getDelta(WORD relocEntryVal)
277{
278 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
279 return entry->Offset;
280}
281
283{
284 switch (type) {
285 case 0 : return "Padding (skipped)";
286 case 1 : return "High WORD of 32-bit field";
287 case 2 : return "Low WORD of 32-bit field";
288 case 3 : return "32 bit field";
289 case 4 : return "HighAdj";
290 case 5 : return "MIPS JumpAddr";
291 case 6 : case 7 : return "Reserved";
292 case 9 : return "MIPS16 JumpAddr";
293 case 10 : return "64 bit field";
294 }
295 return "";
296}
297
299{
300 if (this->parentDir == NULL) return INVALID_ADDR;
301
302 IMAGE_BASE_RELOCATION* reloc = parentDir->myReloc();
303 if (reloc == NULL) return INVALID_ADDR;
304
305 offset_t offset = static_cast<offset_t>(reloc->VirtualAddress + delta);
306 return offset;
307}
308
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
bufsize_t getDirEntrySize()
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 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 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)