BearParser
Portable Executable parsing library (from PE-bear)
RelocDirWrapper.cpp
Go to the documentation of this file.
1 #include "pe/RelocDirWrapper.h"
2 #include "pe/PEFile.h"
3 
4 size_t RelocDirWrapper::EntriesLimit = 10000;
5 
6 /*
7 // Based relocation format.
8 
9 typedef struct _IMAGE_BASE_RELOCATION {
10  DWORD VirtualAddress;
11  DWORD SizeOfBlock;
12  // WORD TypeOffset[1];
13 } IMAGE_BASE_RELOCATION;
14 typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
15 
16 
17 //Based relocation types.
18 
19 enum 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 
60 IMAGE_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 
107  offset_t raw = INVALID_ADDR;
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 
167 void* 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 
184 QString 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  }
200  return Executable::NOT_ADDR;
201 }
202 
204 {
205  if (fieldId == ENTRIES_PTR){
206  return WrappedValue::COMPLEX;
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 
270 WORD RelocEntryWrapper::getType(WORD relocEntryVal)
271 {
272  pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
273  return entry->Type;
274 }
275 
276 WORD 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)