BearParser
Portable Executable parsing library (from PE-bear)
ImportDirWrapper.cpp
Go to the documentation of this file.
1 #include "pe/ImportDirWrapper.h"
2 #include "pe/PEFile.h"
3 
4 using namespace imports_util;
5 
7 {
8  void *ptr = getValuePtr(ImportEntryWrapper::ORIG_FIRST_THUNK);
9  if (!ptr) ptr = getValuePtr(ImportEntryWrapper::FIRST_THUNK);
10  return ptr;
11 }
12 
14 {
15  bool isOk = false;
16  uint64_t offset = this->getNumValue(ImportedFuncWrapper::ORIG_THUNK, &isOk);
17  if (!isOk || offset == INVALID_ADDR) {
18  offset = this->getNumValue(ImportedFuncWrapper::THUNK, &isOk);
19  }
20  if (!isOk) return NULL;
21  BYTE *ptr = this->m_Exe->getContentAt(offset, Executable::RVA, sizeof(IMAGE_IMPORT_BY_NAME));
22  return (IMAGE_IMPORT_BY_NAME*) ptr;
23 }
24 
26 {
27  if (!parentNode) return 0;
28  bool is32 = isBit32();
29 
30  bool isOk;
31  uint64_t thunkRva = parentNode->getNumValue(fId, &isOk);
32  if (!isOk) return 0; //TODO
33 
34  if (is32) thunkRva = (int32_t)(thunkRva);
35  if (thunkRva == 0 || thunkRva == (-1)) return 0; //TODO
36 
37  size_t thunkValSize = this->getThunkValSize();
38  offset_t offset = this->entryNum * thunkValSize;
39 
40  offset_t fieldRVA = thunkRva + offset;
41  return fieldRVA;
42 }
43 
45 {
46  if (!parentNode) return NULL;
47  bool is64 = isBit64();
48 
49  bool isOk;
50  uint64_t thunkRva = parentNode->getNumValue(fId, &isOk);
51  if (!isOk) {
52  //printf("Failed getting value!\n");
53  return NULL;
54  }
55  if (!is64) thunkRva = (int32_t)(thunkRva);
56  if (thunkRva == 0 || thunkRva == -1) return NULL;
57 
58  bufsize_t thunkValSize = this->getThunkValSize();
59  offset_t offset = static_cast<offset_t>(this->entryNum) * thunkValSize;
60 
61  offset_t thunkAddr = m_Exe->toRaw(thunkRva + offset, Executable::RVA);
62  void* thunkPtr = m_Exe->getContentAt(thunkAddr, thunkValSize);
63  return thunkPtr;
64 }
65 
67 {
68  bool isOk = false;
69  bool is64 = (m_Exe->getBitMode() == Executable::BITS_64) ? true : false;
70 
71  uint64_t ordinal = 0;
72  void* thunkPtr = getPtr();
73  if (!thunkPtr) return 0;
74 
75  if (is64) {
76  uint64_t* ptr = (uint64_t*) thunkPtr;
77  ordinal = *ptr;
78  if (ordinal & ORDINAL_FLAG64) ordinal ^= ORDINAL_FLAG64;
79 
80  } else {
81  uint32_t* ptr = (uint32_t*) thunkPtr;
82  ordinal = *ptr;
83  if (uint32_t(ordinal) & ORDINAL_FLAG32) ordinal ^= ORDINAL_FLAG32;
84  }
85 
86  return ordinal;
87 }
88 
90 {
91  bool isOk = false;
92 
93  void *p = getValuePtr(ImportEntryWrapper::ORIG_FIRST_THUNK);
94  if (!p) p = getValuePtr(ImportEntryWrapper::FIRST_THUNK);
95  if (!p) return false;
96 
97  if (isBit64()) {
98  uint64_t* ptr = (uint64_t*) p;
99  if ((*ptr) & ORDINAL_FLAG64) return true;
100 
101  } else {
102  uint32_t* ptr = (uint32_t*) p;
103  if ((*ptr) & ORDINAL_FLAG32) return true;
104  }
105  return false;
106 }
107 
108 
110 {
111  if (isByOrdinal()) return NULL;
112 
113  IMAGE_IMPORT_BY_NAME* dataPtr = this->getImportByNamePtr();
114  if (!dataPtr) return NULL;
115  char *name = (char*) dataPtr->Name;
116  return name;
117 }
118 
120 {
121  return getAddrSize();
122 }
123 
124 void* ImportedFuncWrapper::getFieldPtr(size_t fId, size_t subField)
125 {
126  bool is64 = isBit64();
127  void *entryPtr = this->getPtr();
128  if (entryPtr == NULL) return NULL;
129 
130  IMAGE_THUNK_DATA32* en32 = is64 ? NULL : (IMAGE_THUNK_DATA32*) entryPtr;
131  IMAGE_THUNK_DATA64* en64 = is64 ? (IMAGE_THUNK_DATA64*) entryPtr : NULL;
132 
133  switch (fId) {
134  case ORIG_THUNK: return (void*) getValuePtr(ImportEntryWrapper::ORIG_FIRST_THUNK);
135  case THUNK: return (void*) getValuePtr(ImportEntryWrapper::FIRST_THUNK);
136  case FORWARDER: return (void*) getValuePtr(ImportEntryWrapper::FORWARDER);
137  case HINT :
138  {
139  if (isByOrdinal()) return NULL;
140  IMAGE_IMPORT_BY_NAME* dataPtr = this->getImportByNamePtr();
141  return (void*) &dataPtr->Hint;
142  }
143  };
144  return entryPtr;
145 }
146 
147 bufsize_t ImportedFuncWrapper::getFieldSize(size_t fieldId, size_t subField)
148 {
149  if (fieldId == HINT) return sizeof (WORD);
150  bufsize_t entrySize = (isBit64()) ? sizeof(uint64_t) : sizeof(uint32_t);
151  return entrySize;
152 }
153 
155 {
156  switch (fId) {
157  case ORIG_THUNK: return "Original Thunk";
158  case THUNK: return "Thunk";
159  case FORWARDER: return "Forwarder";
160  case HINT : return "Hint";
161  };
162  return "";
163 }
164 
166 {
167  if (this->isByOrdinal()) {
168  return Executable::NOT_ADDR;
169  }
170  switch (fId) {
171  case ORIG_THUNK:
172  case THUNK:
173  return Executable::RVA;
174  }
175  return Executable::NOT_ADDR;
176 }
177 //-------------------------------------------------------------------------------
178 
179 
180  bool ImportEntryWrapper::loadNextEntry(size_t entryNum)
181  {
182  ImportedFuncWrapper* func = new ImportedFuncWrapper(m_PE, this, entryNum);
183  offset_t thunk = func->getThunkValue();
184 
185  if (thunk == 0 || thunk == INVALID_ADDR) {
186  delete func;
187  func = NULL;
188  return false;
189  } else {
190  entries.push_back(func);
191  addMapping(func);
192  }
193  return true;
194  }
195 
196 
198 {
199  if (m_PE == NULL) return NULL;
200  IMAGE_DATA_DIRECTORY *d = m_PE->getDataDirectory();
201  if (!d) return NULL;
202 
203  offset_t importRva = static_cast<offset_t>(d[pe::DIR_IMPORT].VirtualAddress);
204  if (importRva == 0) return NULL;
205 
206  offset_t descAddr = this->m_Exe->toRaw(importRva, Executable::RVA);
207  if (descAddr == INVALID_ADDR) {
208  return NULL; // address invalid
209  }
210  BYTE *dirPtr = this->m_Exe->getContentAt(descAddr, Executable::RAW, sizeof(IMAGE_IMPORT_DESCRIPTOR));
211  if (dirPtr == NULL) return NULL; // address invalid
212 
213  offset_t entryOffset = descAddr + (this->entryNum * sizeof(IMAGE_IMPORT_DESCRIPTOR));
214 
215  BYTE *content = this->m_Exe->getContentAt(entryOffset, Executable::RAW, sizeof(IMAGE_IMPORT_DESCRIPTOR));
216  if (!content) return NULL;
217  return (void*) content;
218 }
219 
221 {
222  return sizeof(IMAGE_IMPORT_DESCRIPTOR);
223 }
224 
226 {
227  char *name = getLibraryName();
228  if (!name) return "";
229  return name;
230 }
231 
233 {
234  void *ptr = this->getPtr();
235  IMAGE_IMPORT_DESCRIPTOR* desc = (IMAGE_IMPORT_DESCRIPTOR*) ptr;
236  if (!desc) return false;
237 
238  if (desc->TimeDateStamp == (-1)) return true;
239  return false;
240 }
241 
242 void* ImportEntryWrapper::getFieldPtr(size_t fId, size_t subField)
243 {
244  void *ptr = this->getPtr();
245  IMAGE_IMPORT_DESCRIPTOR* desc = (IMAGE_IMPORT_DESCRIPTOR*) ptr;
246  if (!desc) return NULL;
247 
248  switch (fId) {
249  case ORIG_FIRST_THUNK: return (void*) &desc->OriginalFirstThunk;
250  case TIMESTAMP: return (void*) &desc->TimeDateStamp;
251  case FORWARDER: return (void*) &desc->ForwarderChain;
252  case NAME: return (void*) &desc->Name;
253  case FIRST_THUNK: return (void*) &desc->FirstThunk;
254  }
255  return desc;
256 }
257 
259 {
260  switch (fId) {
261  case ORIG_FIRST_THUNK: return "OriginalFirstThunk";
262  case TIMESTAMP: return "TimeDateStamp";
263  case FORWARDER: return "Forwarder";
264  case NAME: return "NameRVA";
265  case FIRST_THUNK: return "FirstThunk";
266  }
267  return this->getName();
268 }
269 
271 {
272  switch (fId) {
273  case ORIG_FIRST_THUNK:
274  case NAME:
275  case FIRST_THUNK:
276  return Executable::RVA;
277  }
278  return Executable::NOT_ADDR;
279 }
280 
282 {
283  IMAGE_IMPORT_DESCRIPTOR* desc = (IMAGE_IMPORT_DESCRIPTOR*) getPtr();
284  if (!desc) {
285  return NULL;
286  }
287 
288  offset_t nameRVA = desc->Name;
289  offset_t nAddr = m_Exe->toRaw(nameRVA, Executable::RVA);
290  if (nAddr == INVALID_ADDR) return NULL;
291 
292  //TODO: reimplement it:
293  char *name = (char*) m_Exe->getContentAt(nAddr, sizeof(char));
294  offset_t peSize = m_Exe->getRawSize();
295 
296  bufsize_t upperLimit = m_Exe->getMaxSizeFromPtr((BYTE*) name);
297  uint32_t HARD_LIMIT = ImportEntryWrapper::NameLenLimit;
298  int32_t limit = (uint32_t) upperLimit < HARD_LIMIT ? upperLimit : HARD_LIMIT;
299 
300  if (pe_util::isStrLonger(name, limit)) {
301  if (upperLimit < HARD_LIMIT) {
302  return name; // Name at the end of File. FileBuffer secures it with appended \0
303  }
304  return NULL;
305  }
306  return name;
307 }
308 
309 //---------------------------------
310 
311 IMAGE_DATA_DIRECTORY* ImportDirWrapper::getDataDirectory()
312 {
313  PEFile *pe = dynamic_cast<PEFile*> (this->m_Exe);
314  if (pe == NULL) return NULL;
315 
316  IMAGE_DATA_DIRECTORY *d = pe->getDataDirectory();
317  return d;
318 }
319 
320 IMAGE_IMPORT_DESCRIPTOR* ImportDirWrapper::firstDescriptor()
321 {
322  IMAGE_DATA_DIRECTORY *d = getDataDirectory();
323  if (!d) return NULL;
324 
325  uint32_t importRva = d[pe::DIR_IMPORT].VirtualAddress;
326  if (importRva == 0) return NULL;
327 
328  offset_t descAddr = this->m_Exe->toRaw(importRva, Executable::RVA);
329  if (descAddr == INVALID_ADDR) return NULL; // address invalid
330 
331  BYTE *dirPtr = this->m_Exe->getContentAt(descAddr, Executable::RAW, sizeof(IMAGE_IMPORT_DESCRIPTOR));
332  if (dirPtr == NULL) return NULL; // address invalid
333  return (IMAGE_IMPORT_DESCRIPTOR*) dirPtr;
334 }
335 
337 {
338  ImportEntryWrapper* imp = new ImportEntryWrapper(m_PE, this, cntr);
339  if (!imp || !imp->getPtr()) {
340  delete imp;
341  return false;
342  }
343  bool isOk = false;
344  uint64_t thunk = imp->getNumValue(ImportEntryWrapper::FIRST_THUNK, &isOk);
345  if (!isOk) {
346  delete imp;
347  return false;
348  }
349  uint64_t oThunk = imp->getNumValue(ImportEntryWrapper::ORIG_FIRST_THUNK, &isOk);
350  if (!isOk) {
351  delete imp;
352  return false;
353  }
354  if (!thunk && !oThunk) {
355  delete imp;
356  return false;
357  }
358  entries.push_back(imp);
359  return true;
360 }
361 
363 {
364  size_t fields = getFieldsCount() + 1; //fields + terminating field
365  return static_cast<bufsize_t>(fields) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
366 }
367 
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
virtual uint64_t getNumValue(size_t fieldId, size_t subField, bool *isOk)
static bufsize_t NameLenLimit
IMAGE_DATA_DIRECTORY * getDataDirectory()
virtual bufsize_t getSize()
virtual bool loadNextEntry(size_t cntr)
IMAGE_IMPORT_DESCRIPTOR * firstDescriptor()
bool isBound()
FieldID
@ FIRST_THUNK
@ FORWARDER
@ ORIG_FIRST_THUNK
virtual QString getName()
char * getLibraryName()
virtual QString getFieldName(size_t fieldId)
bool loadNextEntry(size_t entryNum)
virtual void * getPtr()
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField=FIELD_NONE)
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
virtual bufsize_t getSize()
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
virtual void * getPtr()
virtual bufsize_t getSize()
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField=FIELD_NONE)
virtual QString getFieldName(size_t fieldId)
void * getValuePtr(ImportEntryWrapper::FieldID fId)
offset_t getFieldRVA(ImportEntryWrapper::FieldID fId)
virtual IMAGE_IMPORT_BY_NAME * getImportByNamePtr()
virtual bufsize_t getFieldSize(size_t fieldId, size_t subField=FIELD_NONE)
Definition: PEFile.h:41
IMAGE_DATA_DIRECTORY * getDataDirectory()
Definition: PEFile.cpp:195
bool isStrLonger(const char *inp, size_t maxLen)
Definition: Util.cpp:38