BearParser
Portable Executable parsing library (from PE-bear)
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 //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
101void* 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
122QString 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:
147 return Executable::RVA;
148 }
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//----------------------------------------------------------------------------------------------------
179void* 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
188DWORD* 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
228QString 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
255uint32_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
267void* 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()
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()
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