BearParser
Portable Executable parsing library (from PE-bear)
ImportDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4using namespace imports_util;
5
7{
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
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
124void* 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) {
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
147bufsize_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()) {
169 }
170 switch (fId) {
171 case ORIG_THUNK:
172 case THUNK:
173 return Executable::RVA;
174 }
176}
177//-------------------------------------------------------------------------------
178
179
181 {
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
242void* 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 }
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
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
320IMAGE_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
bufsize_t getMaxSizeFromPtr(BYTE *ptr)
virtual uint64_t getNumValue(size_t fieldId, size_t subField, bool *isOk)
std::vector< ExeNodeWrapper * > entries
ExeNodeWrapper * parentNode
virtual exe_bits getBitMode()
Definition: Executable.h:49
virtual offset_t toRaw(offset_t offset, addr_type addrType, bool allowExceptions=false)
Definition: Executable.cpp:85
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 size_t getFieldsCount()
static bufsize_t NameLenLimit
void addMapping(ExeNodeWrapper *func)
IMAGE_DATA_DIRECTORY * getDataDirectory()
virtual bufsize_t getSize()
virtual bool loadNextEntry(size_t cntr)
IMAGE_IMPORT_DESCRIPTOR * firstDescriptor()
friend class ImportEntryWrapper
bool isBound()
FieldID
@ FIRST_THUNK
@ FORWARDER
@ ORIG_FIRST_THUNK
@ NAME
@ TIMESTAMP
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
PEFile * m_PE
Definition: PENodeWrapper.h:36
bool isStrLonger(const char *inp, size_t maxLen)
Definition: Util.cpp:38