BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
ExportDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4#define INVALID_NAME "<invalid>"
5#define INVALID_ID (-1)
6
7/*
8typedef 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
23IMAGE_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 return i;
60}
61
63{
64 clear();
65 mapNames();
66
67 IMAGE_EXPORT_DIRECTORY* exp = exportDir();
68 if (exp == NULL) return 0;
69
70 size_t maxFunc = exp->NumberOfFunctions;
71
72 for (size_t i = 0; i < maxFunc; i++) {
73 //TODO: build entries...
74 ExportEntryWrapper *entry = new ExportEntryWrapper(m_Exe, this, i);
75 if (entry->getPtr() == NULL) {
76 delete entry;
77 break;
78 }
79 this->entries.push_back(entry);
80 }
81 return true;
82}
83
85{
86 if (getPtr() == NULL) return 0;
87 return sizeof(IMAGE_EXPORT_DIRECTORY);
88}
89
91{
92 QString infoName = "Export";
93 QString libName = this->getLibraryName();
94 if (libName.length() >= 0) {
95 infoName += ": "+ libName;
96 }
97 return infoName;
98}
99
100void* ExportDirWrapper::getFieldPtr(size_t fId, size_t subField)
101{
102 IMAGE_EXPORT_DIRECTORY* d = exportDir();
103 if (d == NULL) return NULL;
104
105 switch (fId) {
106 case CHARACTERISTIC: return &d->Characteristics;
107 case TIMESTAMP: return &d->TimeDateStamp;
108 case MAJOR_VER: return &d->MajorVersion;
109 case MINOR_VER: return &d->MinorVersion;
110 case NAME_RVA: return &d->Name;
111 case BASE: return &d->Base;
112 case FUNCTIONS_NUM: return &d->NumberOfFunctions;
113 case NAMES_NUM: return &d->NumberOfNames;
114 case FUNCTIONS_RVA: return &d->AddressOfFunctions;
115 case FUNC_NAMES_RVA: return &d->AddressOfNames;
116 case NAMES_ORDINALS_RVA: return &d->AddressOfNameOrdinals;
117 }
118 return this->getPtr();
119}
120
121QString ExportDirWrapper::getFieldName(size_t fieldId)
122{
123 switch (fieldId) {
124 case CHARACTERISTIC: return "Characteristics";
125 case TIMESTAMP: {
126 PEFile* myPe = dynamic_cast<PEFile*>(this->m_Exe);
127 if (myPe && myPe->isReproBuild()) {
128 return "ReproChecksum";
129 }
130 return "TimeDateStamp";
131 }
132 case MAJOR_VER: return "MajorVersion";
133 case MINOR_VER: return "MinorVersion";
134 case NAME_RVA: return "Name";
135 case BASE: return "Base";
136 case FUNCTIONS_NUM: return "NumberOfFunctions";
137 case NAMES_NUM: return "NumberOfNames";
138 case FUNCTIONS_RVA: return "AddressOfFunctions";
139 case FUNC_NAMES_RVA: return "AddressOfNames";
140 case NAMES_ORDINALS_RVA: return "AddressOfNameOrdinals";
141 }
142 return getName();
143}
144
146{
147 switch (fieldId) {
148 case NAME_RVA:
149 case FUNCTIONS_RVA:
150 case FUNC_NAMES_RVA:
152 return Executable::RVA;
153 }
155}
156
158{
159 bool isOk = false;
160 offset_t offset = this->getNumValue(NAME_RVA, &isOk);
161 if (!isOk) return NULL;
162
164 if (aT == Executable::NOT_ADDR) return NULL;
165
166 char *ptr = (char*) m_Exe->getContentAt(offset, aT, 1);
167 if (!ptr) return NULL;
168
169 return ptr;
170}
171
173{
174 char *name = this->_getLibraryName();
175 if (!name) return name;
176
177 if (pe_util::isStrLonger(name, 100)) {
178 return INVALID_NAME;
179 }
180 return QString(name);
181}
182
183//----------------------------------------------------------------------------------------------------
184void* ExportEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
185{
186 switch (fieldId) {
187 case FUNCTION_RVA: return getFuncRvaPtr();
188 case NAME_RVA: return getFuncNameRvaPtr();
189 }
190 return getPtr();
191}
192
193DWORD* ExportEntryWrapper::getFuncRvaPtr()
194{
195 if (this->parentDir == NULL) return NULL;
196 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
197 if (exp == NULL) return NULL;
198
199 uint64_t funcRva = exp->AddressOfFunctions;
200 funcRva += (this->entryNum * sizeof(DWORD));
201
202 DWORD *ptr = (DWORD*) m_Exe->getContentAt(funcRva, Executable::RVA, sizeof(DWORD));
203 return ptr;
204}
205
207{
208 if (this->parentDir == NULL || parentDir->exportDir() == NULL) {
209 return 0;
210 }
211 return sizeof(DWORD);
212}
213
215{
216 if (getFuncName() == NULL) return true;
217 return false;
218}
219
221{
222 if (isByOrdinal()) {
223 uint32_t val = getOrdinal();
224 QString ordStr;
225 QTextStream(&ordStr) << "<ord: " << QString::number(val, 16) << ">";
226 return ordStr;
227 }
228 char* name = getFuncName();
229 if (name == NULL) return "";
230 return QString(name);
231}
232
233QString ExportEntryWrapper::getFieldName(size_t fieldId)
234{
235 switch (fieldId) {
236 case FUNCTION_RVA: return "FuncRva";
237 case NAME_RVA: return "FuncNameRva";
238 }
239 return "";
240}
241
243{
244 DWORD *ptr = this->getFuncRvaPtr();
245 if (ptr == NULL) return INVALID_ADDR;
246 offset_t addr = static_cast<offset_t>(*ptr);
247 return addr;
248}
249
251{
252 if (this->parentDir == NULL) return 0;
253 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
254 if (exp == NULL) return 0;
255
256 uint32_t ordinal = static_cast<uint32_t>(this->entryNum) + exp->Base;
257 return ordinal;
258}
259
260uint32_t ExportEntryWrapper::getFuncNameId()
261{
262 if (this->parentDir == NULL) return INVALID_ID;
263
264 WORD ord = static_cast<WORD>(this->entryNum);
265 std::map<WORD, DWORD>::iterator found = parentDir->ordToNameId.find(ord);
266 if (found == parentDir->ordToNameId.end()) {
267 return INVALID_ID;
268 }
269 return found->second;
270}
271
272void* ExportEntryWrapper::getFuncNameRvaPtr()
273{
274 uint32_t nameId = getFuncNameId();
275 if (nameId == INVALID_ID) return NULL;
276
277 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
278 if (exp == NULL) return NULL;
279
280 if (nameId >= exp->NumberOfNames) return NULL;
281
282 uint64_t nameAddrRVA = exp->AddressOfNames + (nameId * sizeof(DWORD));
283 DWORD* valuePtr = (DWORD*) this->m_Exe->getContentAt(nameAddrRVA, Executable::RVA, sizeof(DWORD));
284 return valuePtr;
285}
286
288{
289 DWORD* valuePtr = (DWORD*) getFuncNameRvaPtr();
290 if (valuePtr == NULL) return INVALID_ADDR;
291 DWORD value = (*valuePtr);
292 return static_cast<offset_t>(value);
293}
294
296{
297 uint64_t funcRva = getFuncNameRva();
298 if (funcRva == INVALID_ADDR) return NULL;
299
300 char* name = (char*) this->m_Exe->getContentAt(funcRva, Executable::RVA, 1);
301 if (name == NULL) return NULL;
302 //TODO.... verify
303 return name;
304}
305
307{
308 if (this->parentDir == NULL) return NULL;
309 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
310 if (exp == NULL) return NULL;
311
312 DWORD* funcRvaPtr = (DWORD*) this->getFuncRvaPtr();
313 if (funcRvaPtr == NULL) return NULL;
314
315 char* strPtr = (char*) m_Exe->getContentAt( (*funcRvaPtr), Executable::RVA, 1);
316 if (strPtr == NULL) return NULL;
317
318 uint64_t offset = m_Exe->getOffset((BYTE*) strPtr);
319 if (offset == INVALID_ADDR) return NULL;
320
321 size_t maxLen = m_Exe->getRawSize() - offset;
322 size_t forwarderNameLen = pe_util::forwarderNameLen(strPtr, maxLen);
323 if (forwarderNameLen > 0) {
324 return strPtr;
325 }
326 return NULL;
327}
328
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:65
virtual offset_t getRawSize() const
Definition Executable.h:62
virtual QString getLibraryName()
virtual void * getPtr()
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 QString getFieldName(size_t fieldId)
char * getFuncName()
uint32_t getOrdinal()
virtual void * getPtr()
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()
bool isReproBuild()
Definition PEFile.h:336
size_t forwarderNameLen(const char *ptr, size_t max_len)
Definition Util.cpp:116
bool isStrLonger(const char *inp, size_t maxLen)
Definition Util.cpp:38