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 //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: {
127 PEFile* myPe = dynamic_cast<PEFile*>(this->m_Exe);
128 if (myPe && myPe->isReproBuild()) {
129 return "ReproChecksum";
130 }
131 return "TimeDateStamp";
132 }
133 case MAJOR_VER: return "MajorVersion";
134 case MINOR_VER: return "MinorVersion";
135 case NAME_RVA: return "Name";
136 case BASE: return "Base";
137 case FUNCTIONS_NUM: return "NumberOfFunctions";
138 case NAMES_NUM: return "NumberOfNames";
139 case FUNCTIONS_RVA: return "AddressOfFunctions";
140 case FUNC_NAMES_RVA: return "AddressOfNames";
141 case NAMES_ORDINALS_RVA: return "AddressOfNameOrdinals";
142 }
143 return getName();
144}
145
147{
148 switch (fieldId) {
149 case NAME_RVA:
150 case FUNCTIONS_RVA:
151 case FUNC_NAMES_RVA:
153 return Executable::RVA;
154 }
156}
157
159{
160 bool isOk = false;
161 offset_t offset = this->getNumValue(NAME_RVA, &isOk);
162 if (!isOk) return NULL;
163
165 if (aT == Executable::NOT_ADDR) return NULL;
166
167 char *ptr = (char*) m_Exe->getContentAt(offset, aT, 1);
168 if (!ptr) return NULL;
169
170 return ptr;
171}
172
174{
175 char *name = this->_getLibraryName();
176 if (!name) return name;
177
178 if (pe_util::isStrLonger(name, 100)) {
179 return INVALID_NAME;
180 }
181 return QString(name);
182}
183
184//----------------------------------------------------------------------------------------------------
185void* ExportEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
186{
187 switch (fieldId) {
188 case FUNCTION_RVA: return getFuncRvaPtr();
189 case NAME_RVA: return getFuncNameRvaPtr();
190 }
191 return getPtr();
192}
193
194DWORD* ExportEntryWrapper::getFuncRvaPtr()
195{
196 if (this->parentDir == NULL) return NULL;
197 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
198 if (exp == NULL) return NULL;
199
200 uint64_t funcRva = exp->AddressOfFunctions;
201 funcRva += (this->entryNum * sizeof(DWORD));
202
203 DWORD *ptr = (DWORD*) m_Exe->getContentAt(funcRva, Executable::RVA, sizeof(DWORD));
204 return ptr;
205}
206
208{
209 if (this->parentDir == NULL || parentDir->exportDir() == NULL) {
210 return 0;
211 }
212 return sizeof(DWORD);
213}
214
216{
217 if (getFuncName() == NULL) return true;
218 return false;
219}
220
222{
223 if (isByOrdinal()) {
224 uint32_t val = getOrdinal();
225 QString ordStr;
226 QTextStream(&ordStr) << "<ord: " << QString::number(val, 16) << ">";
227 return ordStr;
228 }
229 char* name = getFuncName();
230 if (name == NULL) return "";
231 return QString(name);
232}
233
234QString ExportEntryWrapper::getFieldName(size_t fieldId)
235{
236 switch (fieldId) {
237 case FUNCTION_RVA: return "FuncRva";
238 case NAME_RVA: return "FuncNameRva";
239 }
240 return "";
241}
242
244{
245 DWORD *ptr = this->getFuncRvaPtr();
246 if (ptr == NULL) return INVALID_ADDR;
247 offset_t addr = static_cast<offset_t>(*ptr);
248 return addr;
249}
250
252{
253 if (this->parentDir == NULL) return 0;
254 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
255 if (exp == NULL) return 0;
256
257 uint32_t ordinal = static_cast<uint32_t>(this->entryNum) + exp->Base;
258 return ordinal;
259}
260
261uint32_t ExportEntryWrapper::getFuncNameId()
262{
263 if (this->parentDir == NULL) return INVALID_ID;
264
265 WORD ord = static_cast<WORD>(this->entryNum);
266 std::map<WORD, DWORD>::iterator found = parentDir->ordToNameId.find(ord);
267 if (found == parentDir->ordToNameId.end()) {
268 return INVALID_ID;
269 }
270 return found->second;
271}
272
273void* ExportEntryWrapper::getFuncNameRvaPtr()
274{
275 uint32_t nameId = getFuncNameId();
276 if (nameId == INVALID_ID) return NULL;
277
278 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
279 if (exp == NULL) return NULL;
280
281 if (nameId >= exp->NumberOfNames) return NULL;
282
283 uint64_t nameAddrRVA = exp->AddressOfNames + (nameId * sizeof(DWORD));
284 DWORD* valuePtr = (DWORD*) this->m_Exe->getContentAt(nameAddrRVA, Executable::RVA, sizeof(DWORD));
285 return valuePtr;
286}
287
289{
290 DWORD* valuePtr = (DWORD*) getFuncNameRvaPtr();
291 if (valuePtr == NULL) return INVALID_ADDR;
292 DWORD value = (*valuePtr);
293 return static_cast<offset_t>(value);
294}
295
297{
298 uint64_t funcRva = getFuncNameRva();
299 if (funcRva == INVALID_ADDR) return NULL;
300
301 char* name = (char*) this->m_Exe->getContentAt(funcRva, Executable::RVA, 1);
302 if (name == NULL) return NULL;
303 //TODO.... verify
304 return name;
305}
306
308{
309 if (this->parentDir == NULL) return NULL;
310 IMAGE_EXPORT_DIRECTORY* exp = parentDir->exportDir();
311 if (exp == NULL) return NULL;
312
313 DWORD* funcRvaPtr = (DWORD*) this->getFuncRvaPtr();
314 if (funcRvaPtr == NULL) return NULL;
315
316 char* strPtr = (char*) m_Exe->getContentAt( (*funcRvaPtr), Executable::RVA, 1);
317 if (strPtr == NULL) return NULL;
318
319 uint64_t offset = m_Exe->getOffset((BYTE*) strPtr);
320 if (offset == INVALID_ADDR) return NULL;
321
322 size_t maxLen = m_Exe->getRawSize() - offset;
323 size_t forwarderNameLen = pe_util::forwarderNameLen(strPtr, maxLen);
324 if (forwarderNameLen > 0) {
325 return strPtr;
326 }
327 return NULL;
328}
329
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()
Definition: PEFile.h:41
bool isReproBuild()
Definition: PEFile.h:241
size_t forwarderNameLen(const char *ptr, size_t max_len)
Definition: Util.cpp:113
bool isStrLonger(const char *inp, size_t maxLen)
Definition: Util.cpp:38