BearParser
Portable Executable parsing library (from PE-bear)
ExportDirWrapper.cpp
Go to the documentation of this file.
1 #include "pe/ExportDirWrapper.h"
2 #include "pe/PEFile.h"
3 
4 #define INVALID_NAME "<invalid>"
5 #define INVALID_ID (-1)
6 
7 /*
8 typedef struct _IMAGE_EXPORT_DIRECTORY {
9  DWORD Characteristics;
10  DWORD TimeDateStamp;
11  WORD MajorVersion;
12  WORD MinorVersion;
13  DWORD Name;
14  DWORD Base;
15  DWORD NumberOfFunctions;
16  DWORD NumberOfNames;
17  DWORD AddressOfFunctions; // RVA from base of image
18  DWORD AddressOfNames; // RVA from base of image
19  DWORD AddressOfNameOrdinals; // RVA from base of image
20 } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
21 */
22 
23 IMAGE_EXPORT_DIRECTORY* ExportDirWrapper::exportDir()
24 {
26  BYTE *ptr = m_Exe->getContentAt(rva, Executable::RVA, sizeof(IMAGE_EXPORT_DIRECTORY));
27  if (ptr == NULL) return NULL;
28 
29  return (IMAGE_EXPORT_DIRECTORY*) ptr;
30 }
31 
33 {
35  this->ordToNameId.clear();
36 }
37 
39 {
40  IMAGE_EXPORT_DIRECTORY* exp = exportDir();
41  if (exp == NULL) return 0;
42 
43  size_t maxNames = exp->NumberOfNames;
44 
45  offset_t nameOrdRVA = exp->AddressOfNameOrdinals;
46  //uint64_t nameRVA = exp->AddressOfNames;
47  size_t i = 0;
48  for (i = 0; i < maxNames; i++) {
49 
50  WORD* nameOrd = (WORD*) this->m_Exe->getContentAt(nameOrdRVA, Executable::RVA, sizeof(WORD));
51  //DWORD* name = (DWORD*) this->m_Exe->getContentAt(nameRVA, Executable::RVA, sizeof(DWORD));
52  if (nameOrd == NULL) break;
53 
54  this->ordToNameId[*nameOrd] = i;//*name;
55 
56  nameOrdRVA += sizeof(WORD);
57  //nameRVA += sizeof(DWORD);
58  }
59  //printf("parsed num: %d\n", this->ordToNameRVA.size());
60  return i;
61 }
62 
64 {
65  clear();
66  size_t mapNum = mapNames();
67 
68  IMAGE_EXPORT_DIRECTORY* exp = exportDir();
69  if (exp == NULL) return 0;
70 
71  size_t maxFunc = exp->NumberOfFunctions;
72 
73  for (size_t i = 0; i < maxFunc; i++) {
74  //TODO: build entries...
75  ExportEntryWrapper *entry = new ExportEntryWrapper(m_Exe, this, i);
76  if (entry->getPtr() == NULL) {
77  delete entry;
78  break;
79  }
80  this->entries.push_back(entry);
81  }
82  return true;
83 }
84 
86 {
87  if (getPtr() == NULL) return 0;
88  return sizeof(IMAGE_EXPORT_DIRECTORY);
89 }
90 
92 {
93  QString infoName = "Export";
94  QString libName = this->getLibraryName();
95  if (libName.length() >= 0) {
96  infoName += ": "+ libName;
97  }
98  return infoName;
99 }
100 
101 void* ExportDirWrapper::getFieldPtr(size_t fId, size_t subField)
102 {
103  IMAGE_EXPORT_DIRECTORY* d = exportDir();
104  if (d == NULL) return NULL;
105 
106  switch (fId) {
107  case CHARACTERISTIC: return &d->Characteristics;
108  case TIMESTAMP: return &d->TimeDateStamp;
109  case MAJOR_VER: return &d->MajorVersion;
110  case MINOR_VER: return &d->MinorVersion;
111  case NAME_RVA: return &d->Name;
112  case BASE: return &d->Base;
113  case FUNCTIONS_NUM: return &d->NumberOfFunctions;
114  case NAMES_NUM: return &d->NumberOfNames;
115  case FUNCTIONS_RVA: return &d->AddressOfFunctions;
116  case FUNC_NAMES_RVA: return &d->AddressOfNames;
117  case NAMES_ORDINALS_RVA: return &d->AddressOfNameOrdinals;
118  }
119  return this->getPtr();
120 }
121 
122 QString ExportDirWrapper::getFieldName(size_t fieldId)
123 {
124  switch (fieldId) {
125  case CHARACTERISTIC: return "Characteristics";
126  case TIMESTAMP: return "TimeDateStamp";
127  case MAJOR_VER: return "MajorVersion";
128  case MINOR_VER: return "MinorVersion";
129  case NAME_RVA: return "Name";
130  case BASE: return "Base";
131  case FUNCTIONS_NUM: return "NumberOfFunctions";
132  case NAMES_NUM: return "NumberOfNames";
133  case FUNCTIONS_RVA: return "AddressOfFunctions";
134  case FUNC_NAMES_RVA: return "AddressOfNames";
135  case NAMES_ORDINALS_RVA: return "AddressOfNameOrdinals";
136  }
137  return getName();
138 }
139 
141 {
142  switch (fieldId) {
143  case NAME_RVA:
144  case FUNCTIONS_RVA:
145  case FUNC_NAMES_RVA:
146  case NAMES_ORDINALS_RVA:
147  return Executable::RVA;
148  }
149  return Executable::NOT_ADDR;
150 }
151 
153 {
154  bool isOk = false;
155  offset_t offset = this->getNumValue(NAME_RVA, &isOk);
156  if (!isOk) return NULL;
157 
159  if (aT == Executable::NOT_ADDR) return NULL;
160 
161  char *ptr = (char*) m_Exe->getContentAt(offset, aT, 1);
162  if (!ptr) return NULL;
163 
164  return ptr;
165 }
166 
168 {
169  char *name = this->_getLibraryName();
170  if (!name) return name;
171 
172  if (pe_util::isStrLonger(name, 100)) {
173  return INVALID_NAME;
174  }
175  return QString(name);
176 }
177 
178 //----------------------------------------------------------------------------------------------------
179 void* ExportEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
180 {
181  switch (fieldId) {
182  case FUNCTION_RVA: return getFuncRvaPtr();
183  case NAME_RVA: return getFuncNameRvaPtr();
184  }
185  return getPtr();
186 }
187 
188 DWORD* ExportEntryWrapper::getFuncRvaPtr()
189 {
190  if (this->parentDir == NULL) return NULL;
191  IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
192  if (exp == NULL) return NULL;
193 
194  uint64_t funcRva = exp->AddressOfFunctions;
195  funcRva += (this->entryNum * sizeof(DWORD));
196 
197  DWORD *ptr = (DWORD*) m_Exe->getContentAt(funcRva, Executable::RVA, sizeof(DWORD));
198  return ptr;
199 }
200 
202 {
203  if (this->parentDir == NULL || parentDir->exportDir() == NULL) {
204  return 0;
205  }
206  return sizeof(DWORD);
207 }
208 
210 {
211  if (getFuncName() == NULL) return true;
212  return false;
213 }
214 
216 {
217  if (isByOrdinal()) {
218  uint32_t val = getOrdinal();
219  QString ordStr;
220  QTextStream(&ordStr) << "<ord: " << QString::number(val, 16) << ">";
221  return ordStr;
222  }
223  char* name = getFuncName();
224  if (name == NULL) return "";
225  return QString(name);
226 }
227 
228 QString ExportEntryWrapper::getFieldName(size_t fieldId)
229 {
230  switch (fieldId) {
231  case FUNCTION_RVA: return "FuncRva";
232  case NAME_RVA: return "FuncNameRva";
233  }
234  return "";
235 }
236 
238 {
239  DWORD *ptr = this->getFuncRvaPtr();
240  if (ptr == NULL) return INVALID_ADDR;
241  offset_t addr = static_cast<offset_t>(*ptr);
242  return addr;
243 }
244 
246 {
247  if (this->parentDir == NULL) return 0;
248  IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
249  if (exp == NULL) return 0;
250 
251  uint32_t ordinal = static_cast<uint32_t>(this->entryNum) + exp->Base;
252  return ordinal;
253 }
254 
255 uint32_t ExportEntryWrapper::getFuncNameId()
256 {
257  if (this->parentDir == NULL) return INVALID_ID;
258 
259  WORD ord = static_cast<WORD>(this->entryNum);
260  std::map<WORD, DWORD>::iterator found = parentDir->ordToNameId.find(ord);
261  if (found == parentDir->ordToNameId.end()) {
262  return INVALID_ID;
263  }
264  return found->second;
265 }
266 
267 void* ExportEntryWrapper::getFuncNameRvaPtr()
268 {
269  uint32_t nameId = getFuncNameId();
270  if (nameId == INVALID_ID) return NULL;
271 
272  IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
273  if (exp == NULL) return NULL;
274 
275  if (nameId >= exp->NumberOfNames) return NULL;
276 
277  uint64_t nameAddrRVA = exp->AddressOfNames + (nameId * sizeof(DWORD));
278  DWORD* valuePtr = (DWORD*) this->m_Exe->getContentAt(nameAddrRVA, Executable::RVA, sizeof(DWORD));
279  return valuePtr;
280 }
281 
283 {
284  DWORD* valuePtr = (DWORD*) getFuncNameRvaPtr();
285  if (valuePtr == NULL) return INVALID_ADDR;
286  DWORD value = (*valuePtr);
287  return static_cast<offset_t>(value);
288 }
289 
291 {
292  uint64_t funcRva = getFuncNameRva();
293  if (funcRva == INVALID_ADDR) return NULL;
294 
295  char* name = (char*) this->m_Exe->getContentAt(funcRva, Executable::RVA, 1);
296  if (name == NULL) return NULL;
297  //TODO.... verify
298  return name;
299 }
300 
302 {
303  if (this->parentDir == NULL) return NULL;
304  IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
305  if (exp == NULL) return NULL;
306 
307  DWORD* funcRvaPtr = (DWORD*) this->getFuncRvaPtr();
308  if (funcRvaPtr == NULL) return NULL;
309 
310  char* strPtr = (char*) m_Exe->getContentAt( (*funcRvaPtr), Executable::RVA, 1);
311  if (strPtr == NULL) return NULL;
312 
313  uint64_t offset = m_Exe->getOffset((BYTE*) strPtr);
314  if (offset == INVALID_ADDR) return NULL;
315 
316  size_t maxLen = m_Exe->getRawSize() - offset;
317  size_t forwarderNameLen = pe_util::forwarderNameLen(strPtr, maxLen);
318  if (forwarderNameLen > 0) {
319  return strPtr;
320  }
321  return NULL;
322 }
323 
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
#define INVALID_NAME
#define INVALID_ID
virtual offset_t getOffset(void *ptr, bool allowExceptions=false)
offset_t getDirEntryAddress()
virtual uint64_t getNumValue(size_t fieldId, size_t subField, bool *isOk)
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 getLibraryName()
std::map< WORD, DWORD > ordToNameId
virtual void * getFieldPtr(size_t fieldId, size_t subField)
IMAGE_EXPORT_DIRECTORY * exportDir()
virtual QString getName()
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField=FIELD_NONE)
virtual QString getFieldName(size_t fieldId)
virtual bufsize_t getSize()
friend class ExportEntryWrapper
virtual void * getPtr()
virtual QString getFieldName(size_t fieldId)
virtual void * getPtr()
char * getFuncName()
uint32_t getOrdinal()
bool isByOrdinal()
virtual bufsize_t getSize()
offset_t getFuncNameRva()
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
offset_t getFuncRva()
@ FUNCTION_RVA
@ NAME_RVA
char * getForwarder()
virtual QString getName()
size_t forwarderNameLen(const char *ptr, size_t max_len)
Definition: Util.cpp:81
bool isStrLonger(const char *inp, size_t maxLen)
Definition: Util.cpp:38