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