BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
SectHdrsWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4using namespace buf_util;
5
6const size_t SectionHdrWrapper::SECNAME_LEN = 8;
7
10
11std::map<DWORD, QString> SectionHdrWrapper::s_secHdrCharact;
12
14{
15 char rights[] = "---";
16
17 if (characteristics & SCN_MEM_READ)
18 rights[0] = 'r';
19 if (characteristics & SCN_MEM_WRITE)
20 rights[1] = 'w';
21 if (characteristics & SCN_MEM_EXECUTE)
22 rights[2] = 'x';
23 return rights;
24}
25
26void SectionHdrWrapper::initSecCharacter(std::map<DWORD, QString> &secHdrCharact)
27{
28 secHdrCharact[SCN_MEM_READ] = "readable";
29 secHdrCharact[SCN_MEM_WRITE] = "writeable";
30 secHdrCharact[SCN_MEM_EXECUTE] = "executable";
31
32 secHdrCharact[SCN_LNK_NRELOC_OVFL] = "contains extended relocations";
33 secHdrCharact[SCN_MEM_DISCARDABLE] = "discardable";
34 secHdrCharact[SCN_MEM_NOT_CACHED] = "not cachable";
35 secHdrCharact[SCN_MEM_NOT_PAGED] = "non-pageable";
36 secHdrCharact[SCN_MEM_SHARED] = "shareable";
37 secHdrCharact[SCN_CNT_CODE] = "code";
38 secHdrCharact[SCN_CNT_INITIALIZED_DATA] = "initialized data";
39 secHdrCharact[SCN_CNT_UNINITIALIZED_DATA] = "uninitialized data";
40}
41
42std::vector<DWORD> SectionHdrWrapper::splitCharacteristics(DWORD charact)
43{
44 if (s_secHdrCharact.size() == 0) {
45 initSecCharacter(s_secHdrCharact);
46 }
47 std::vector<DWORD> chSet;
48 std::map<DWORD, QString>::iterator iter;
49 for (iter = s_secHdrCharact.begin(); iter != s_secHdrCharact.end(); ++iter) {
50 if (charact & iter->first) {
51 chSet.push_back(iter->first);
52 }
53 }
54 return chSet;
55}
56
58{
59 if (s_secHdrCharact.size() == 0) {
60 initSecCharacter(s_secHdrCharact);
61 }
62
63 if (s_secHdrCharact.find(charact) == s_secHdrCharact.end()) return "";
64 return s_secHdrCharact[charact];
65}
66
67//----
68
70{
71 this->clear();
72
73 this->header = NULL;
74 getPtr();
75 reloadName();
76 return true;
77}
78
80{
81 if (m_PE == NULL) return NULL;
82
83 if (header != NULL) {
84 return (void*) this->header;
85 }
86
87 offset_t firstSecOffset = m_PE->secHdrsOffset();
88 offset_t secOffset = firstSecOffset + (this->sectNum * sizeof(IMAGE_SECTION_HEADER));
89
90 //cache the header:
91 this->header = (IMAGE_SECTION_HEADER*) m_PE->getContentAt(secOffset, sizeof(IMAGE_SECTION_HEADER));
92 return (void*) this->header;
93}
94
96{
97 IMAGE_SECTION_HEADER* header = (IMAGE_SECTION_HEADER*) getPtr();
98 if (!header) return false;
99
100 if (this->name) {
101 if (memcmp(this->name, header->Name, SECNAME_LEN) == 0) {
102 return true; //no need to reload
103 }
104 }
105 const size_t BUF_LEN = SECNAME_LEN + 2;
106 if (!this->name) {
107 this->name = (char*)::calloc(BUF_LEN, 1);
108 }
109 ::memset(this->name, 0, BUF_LEN);
110 ::memcpy(this->name, header->Name, SECNAME_LEN);
111 this->mappedName = this->name;
112 if (this->mappedName.length() == 0) {
113 this->mappedName = "#" + QString::number(this->sectNum, 10);
114 }
115 return true;
116}
117
119{
120 if (m_PE == NULL) return 0;
121 return sizeof(IMAGE_SECTION_HEADER);
122}
123
125{
126 //reloadName();
127 if (!this->name) return ""; //cannot load
128 return this->name;
129}
130
131void* SectionHdrWrapper::getFieldPtr(size_t fieldId, size_t subField)
132{
133 IMAGE_SECTION_HEADER* sec = (IMAGE_SECTION_HEADER*) getPtr();
134 if (!sec) return NULL;
135 if (!this->name) return NULL;
136 switch (fieldId)
137 {
138 case NAME: return (void*) &sec->Name;
139 case VSIZE: return (void*) &sec->Misc.VirtualSize;
140 case VPTR: return (void*) &sec->VirtualAddress;
141 case RSIZE: return (void*) &sec->SizeOfRawData;
142 case RPTR: return(void*) &sec->PointerToRawData;
143
144 case RELOC_PTR: return (void*) &sec->PointerToRelocations;
145 case RELOC_NUM: return (void*) &sec->NumberOfRelocations;
146 case LINENUM_PTR: return (void*) &sec->PointerToLinenumbers;
147 case LINENUM_NUM: return (void*) &sec->NumberOfLinenumbers;
148
149 case CHARACT: return (void*) &sec->Characteristics;
150 }
151 return this->getPtr();
152}
153
154QString SectionHdrWrapper::getFieldName(size_t fieldId)
155{
156 switch (fieldId)
157 {
158 case NAME: return "Name";
159 case VSIZE: return "Virtual Size";
160 case VPTR: return "Virtual Addr.";
161 case RSIZE: return "Raw size";
162 case RPTR: return "Raw Addr.";
163 case CHARACT: return "Characteristics";
164 case RELOC_PTR: return "Ptr to Reloc.";
165 case RELOC_NUM: return "Num. of Reloc.";
166 case LINENUM_PTR: return "Ptr to Linenum.";
167 case LINENUM_NUM: return "Num. of Linenum.";
168 }
169 return "";
170}
171
173{
174 switch (fieldId)
175 {
176 case VPTR: return Executable::RVA;
177 case RPTR: return Executable::RAW;
178 //case RELOC_PTR: return Executable::RAW;
179 }
181}
182
184{
185 if (fieldId == NAME) {
187 }
188 return WrappedValue::INT;
189}
190
191
192// offset that is declared in header
194{
195 if (this->header == NULL) return INVALID_ADDR;
196 offset_t offset = INVALID_ADDR;
197
198 if (aType == Executable::RAW) {
199 offset = static_cast<offset_t>(this->header->PointerToRawData);//(this->getNumValue(RPTR, &isOk));
200 } else if (aType == Executable::VA || aType == Executable::RVA) {
201 offset = static_cast<offset_t>(this->header->VirtualAddress);//this->getNumValue(VPTR, &isOk));
202 }
203 return offset;
204}
205
207{
208 offset_t offset = getContentDeclaredOffset(aType);
209 if (!useMapped) {
210 return offset; //returning as is
211 }
212 if (aType == Executable::RAW) {
214 const size_t units = pe_util::unitsCount(offset, align, false);
215 const offset_t rounded = units * align; //round down to section alignment
216 if (rounded != 0) {
217 offset = rounded;
218 }
219 const size_t peSize = m_PE->getMappedSize(aType);
220 if (offset > peSize) {
221 offset = INVALID_ADDR;
222 }
223 }
224 return offset;
225}
226
228{
229 const bool useMapped = true;
230 offset_t startOffset = getContentOffset(addrType, useMapped);
231 if (startOffset == INVALID_ADDR) return INVALID_ADDR;
232
233 offset_t endOffset = static_cast<offset_t>(getContentSize(addrType, recalculate)) + startOffset;
234 return endOffset;
235}
236
237// size that is declared in header
239{
240 if (this->header == NULL) return 0;
241 bufsize_t size = 0;
242
243 if (aType == Executable::RAW) {
244 size = static_cast<bufsize_t>(this->header->SizeOfRawData);//this->getNumValue(RSIZE, &isOk));
245 } else if (aType == Executable::VA || aType == Executable::RVA) {
246 size = static_cast<bufsize_t>(this->header->Misc.VirtualSize);//this->getNumValue(VSIZE, &isOk));
247 }
248 return size;
249}
250
251//RAW size that is really mapped
253{
255
256 const offset_t secOffset = getContentOffset(aType);
257 if (secOffset == INVALID_ADDR) {
258 return 0; //invalid addr, nothing is mapped
259 }
260 const bufsize_t peSize = m_PE->getRawSize();
261 if (secOffset > peSize) {
262 return 0; //out of scope
263 }
264 bufsize_t rawSize = getContentDeclaredSize(aType);
265 if (rawSize == 0) {
266 return 0; // no changes
267 }
269 if (virtualSize == 0) { // if virtual size is not filled, use the raw size as virtual
271 }
272 if (virtualSize < rawSize) {
273 // if Virtual Size is smaller than the raw size, it means not full raw size will be mapped
274 rawSize = virtualSize;
275 }
276 // round up to the file alignment unit:
277 bufsize_t unit = m_PE->getAlignment(aType);
278 if (unit != 0) {
279 rawSize = roundupToUnit(rawSize, unit);
280 }
281 const bufsize_t secEnd = secOffset + rawSize;
282 //trim to the file size:
283 if (secEnd > peSize) {
284 const bufsize_t trimmedSize = peSize - secOffset; // trim to the file size
285 if (virtualSize) {
287 if (unit != 0) {
288 virtualSize = roundupToUnit(virtualSize, unit);
289 }
290 }
291 if ((virtualSize != 0) && (trimmedSize > virtualSize)) {
292 return virtualSize;
293 }
294 return trimmedSize;
295 }
296 return rawSize;
297}
298
299//VirtualSize that is really mapped
301{
302 if (!m_PE) return 0;
303
305
306 const offset_t startOffset = getContentOffset(aType);
307 if (startOffset == INVALID_ADDR) {
308 return 0; //invalid addr, nothing is mapped
309 }
310
311 bufsize_t dVirtualSize = getContentDeclaredSize(aType);
312 if (dVirtualSize == 0) {
314 }
315 bufsize_t mRawSize = getMappedRawSize();
316
317 bufsize_t mVirtualSize = (dVirtualSize > mRawSize) ? dVirtualSize : mRawSize;
318 bufsize_t unit = m_PE->getAlignment(aType);
319 if (unit) {
320 mVirtualSize = roundupToUnit(mVirtualSize, unit);
321 }
322 // trim to Image Size:
323 bufsize_t secEnd = startOffset + mVirtualSize;
324 const bufsize_t imgSize = m_PE->getImageSize();
325 if (imgSize < startOffset) {
326 return 0;
327 }
328
329 // trim to next section
330 int secCounter = m_PE->_getSectionsCount(true);
331 for (size_t i = 0; i < secCounter; i++) {
333 if (!sec) continue;
334
335 offset_t currOffset = sec->getContentOffset(aType, true);
336 if (currOffset == INVALID_ADDR) continue;
337 if (currOffset > startOffset && currOffset < secEnd) {
338 secEnd = currOffset;
339 }
340 }
341 //trim to image size:
342 if (secEnd > imgSize) {
343 const bufsize_t trimmedSize = imgSize - startOffset;
344 return trimmedSize;
345 }
346 return (secEnd - startOffset);
347}
348
350{
351 if (!this->header || !m_PE) return 0;
352
353 bufsize_t size = 0;
354 if (!recalculate) {
355 size = getContentDeclaredSize(aType);
356 //printf("Declared size = %llx\n---\n", size);
357 return size;
358 }
359 //---
360 if (aType == Executable::RAW) {
361 //printf ("R: ");
362 size = getMappedRawSize();
363 }
364 if (aType == Executable::RVA || aType == Executable::VA) {
365 size = getMappedVirtualSize();
366 //printf ("V: ");
367 }
368 //printf("Mapped size = %llx\n", size);
369 return size;
370}
371
372//-----------------------------------------------------------------------------------
373
374bool SectHdrsWrapper::isMyEntryType(ExeNodeWrapper *entry)
375{
376 SectionHdrWrapper* sEntry = dynamic_cast<SectionHdrWrapper*> (entry);
377 if (sEntry == NULL) {
378 return false;
379 }
380 return true;
381}
382
384{
385 offset_t nextOffset = getNextEntryOffset();
386 bufsize_t entrySize = geEntrySize();
387 if (entrySize == 0) return false;
388
389 bufsize_t paddedSize = entrySize;
390 bool haveSpace = this->m_Exe->isAreaEmpty(nextOffset, paddedSize);
391 return haveSpace;
392}
393
395{
396 if (m_PE == NULL) return NULL;
397
398 size_t secCount = m_PE->hdrSectionsNum();
399 if (secCount == SECT_COUNT_MAX) return NULL; //limit exceeded
400
401 if (ExeNodeWrapper::addEntry(entry) == NULL) return NULL;
402
403 size_t count = secCount + 1;
404 if (m_PE->setHdrSectionsNum(count) == false) {
405 return NULL;
406 }
407 return getLastEntry();
408}
409
410void SectHdrsWrapper::clear()
411{
413 this->rSec.clear();
414 this->vSec.clear();
415}
416
417bool SectHdrsWrapper::loadNextEntry(size_t entryNum)
418{
419 SectionHdrWrapper *sec = new SectionHdrWrapper(this->m_PE, entryNum);
420 if (sec == NULL) return false;
421 if (sec->getPtr() == NULL) {
422 Logger::append(Logger::D_WARNING, "Deleting invalid section...");
423 delete sec;
424 sec = NULL;
425 return false;
426 }
427 this->entries.push_back(sec);
428 addMapping(sec);
429 return true;
430}
431
432void SectHdrsWrapper::addMapping(SectionHdrWrapper *sec)
433{
434 if (sec == NULL) return;
435 bool recalculate = true;
436 if (sec->getContentSize(Executable::RAW, true) == 0) {
437 //printf("skipping empty section..\n");
438 return;
439 }
440 const offset_t endRVA = sec->getContentEndOffset(Executable::RVA, recalculate);
441 const offset_t endRaw = sec->getContentEndOffset(Executable::RAW, recalculate);
442 if (rSec.find(endRaw) != rSec.end()) { //already exist
443 SectionHdrWrapper* prevSec = rSec[endRaw];
444 if (prevSec == NULL) return;
445 // keep the bigger one (with lower start address) in the mapping
447 return; //skip
448 }
449 }
450 if (vSec.find(endRVA) != vSec.end()) { //already exist
451 SectionHdrWrapper* prevSec = vSec[endRaw];
452 if (prevSec == NULL) return;
453 // keep the bigger one (with lower start address) in the mapping
455 return; //skip
456 }
457 }
458 vSec[endRVA] = sec;
459 rSec[endRaw] = sec;
460 return;
461}
462
464{
465 WatchedLocker lock(&m_secMutex, SEC_SHOW_LOCK, __FUNCTION__);
466 this->rSec.clear();
467 this->vSec.clear();
468
469 size_t count = this->getEntriesCount();
470 for (size_t i = 0; i < count; i++) {
471 SectionHdrWrapper* sec = dynamic_cast<SectionHdrWrapper*>(this->getEntryAt(i));
472 if (sec == NULL) continue;
473 addMapping(sec);
474 }
475}
476
478{
479 WatchedLocker lock(&m_secMutex, SEC_SHOW_LOCK, __FUNCTION__);
480
481 this->clear();
482 if (this->m_PE == NULL) return false;
483 size_t count = this->m_PE->hdrSectionsNum();
484 for (size_t i = 0; i < count && i < SECT_COUNT_MAX; i++) {
485 if (this->loadNextEntry(i) == false) break;
486 }
487 return true;
488}
489
491{
492 WatchedLocker lock(&m_secMutex, SEC_SHOW_LOCK, __FUNCTION__);
493 return this->entries.size();
494}
495
497{
498 WatchedLocker lock(&m_secMutex, SEC_SHOW_LOCK, __FUNCTION__);
499
500 if (entries.size() == 0) return NULL;
501 return entries[0]->getPtr();
502}
503
505{
506 WatchedLocker lock(&m_secMutex, SEC_SHOW_LOCK, __FUNCTION__);
507
508 if (this->m_PE == NULL) return 0;
509
510 size_t secCount = this->entries.size();
511 if (!secCount) return 0;
512
513 offset_t hdrOffset = m_PE->secHdrsOffset();
514 offset_t fileSize = m_PE->getRawSize();
515 offset_t endOffset = hdrOffset + (secCount * sizeof(IMAGE_SECTION_HEADER));
516
517 if (endOffset > fileSize) {
518 return bufsize_t (fileSize - hdrOffset);
519 }
520 return bufsize_t (endOffset - hdrOffset);
521}
522/*
523void* SectHdrsWrapper::getFieldPtr(size_t fieldId, size_t subField)
524{
525 if (fieldId >= entries.size()) return NULL;
526 return entries[fieldId]->getFieldPtr(subField);
527}
528*/
529QString SectHdrsWrapper::getFieldName(size_t fieldId)
530{
531 if (fieldId >= entries.size()) return NULL;
532 return entries[fieldId]->getName();
533}
534
536{
537 std::map<offset_t, SectionHdrWrapper*> *secMap = NULL;
538
539 if (addrType == Executable::RAW) {
540 secMap = &this->rSec;
541 } else if (addrType == Executable::RVA || addrType == Executable::VA) {
542 secMap = &this->vSec;
543 }
544 if (!secMap) return NULL;
545
546 std::map<offset_t, SectionHdrWrapper*>::iterator found = secMap->lower_bound(offset);
547 std::map<offset_t, SectionHdrWrapper*>::iterator itr;
548 for (itr = found; itr != secMap->end(); ++itr) {
549 SectionHdrWrapper* sec = itr->second;
550 if (sec == NULL) continue; //TODO: check it
551 if (verbose) {
552 printf("found [%llX] key: %llX sec: %llX %llX\n",
553 static_cast<unsigned long long>(offset),
554 static_cast<unsigned long long>(itr->first),
555 static_cast<unsigned long long>(sec->getContentOffset(addrType)),
556 static_cast<unsigned long long>(sec->getContentEndOffset(addrType, false))
557 );
558 }
559
560 offset_t startOffset = sec->getContentOffset(addrType);
561 if (startOffset == INVALID_ADDR) continue;
562
563 offset_t endOffset = sec->getContentEndOffset(addrType, recalculate);
564
565 if (offset >= startOffset && offset < endOffset) {
566 return sec;
567 }
568 if (offset < startOffset) break;
569 }
570 return NULL;
571}
572
574{
575 std::map<offset_t, SectionHdrWrapper*> *secMap = NULL;
576
577 if (aType == Executable::RAW) {
578 secMap = &this->rSec;
579 } else if (aType == Executable::RVA || aType == Executable::VA) {
580 secMap = &this->vSec;
581 }
582 if (secMap == NULL) return;
583
584 std::map<offset_t, SectionHdrWrapper*>::iterator itr;
585 for (itr = secMap->begin(); itr != secMap->end(); ++itr) {
586 SectionHdrWrapper* sec = itr->second;
587 offset_t secEnd = itr->first;
588
589 printf("[%llX] %s %llX %llX\n",
590 static_cast<unsigned long long>(secEnd),
591 sec->getName().toStdString().c_str(),
592 static_cast<unsigned long long>(sec->getContentOffset(aType)),
593 static_cast<unsigned long long>(sec->getContentEndOffset(aType, true))
594 );
595 }
596 printf("---\n\n");
597}
598
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
#define SEC_SHOW_LOCK
virtual bufsize_t getContentSize()=0
bool isAreaEmpty(offset_t rawOffset, bufsize_t size)
virtual bufsize_t getContentSize()
ExeNodeWrapper * getLastEntry()
virtual ExeNodeWrapper * getEntryAt(size_t fieldId)
virtual bufsize_t geEntrySize()
std::vector< ExeNodeWrapper * > entries
virtual offset_t getNextEntryOffset()
virtual size_t getEntriesCount()
virtual void clear()
virtual ExeNodeWrapper * addEntry(ExeNodeWrapper *entry)
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 bufsize_t getImageSize()
Definition Executable.h:74
virtual bufsize_t getMappedSize(Executable::addr_type aType)
Definition PEFile.cpp:298
SectionHdrWrapper * _getSecHdr(size_t index) const
Definition PEFile.h:371
offset_t secHdrsOffset() const
Definition PEFile.h:81
bool setHdrSectionsNum(size_t newNum)
Definition PEFile.cpp:349
size_t hdrSectionsNum() const
Definition PEFile.cpp:340
virtual bufsize_t getAlignment(Executable::addr_type aType) const
Definition PEFile.h:69
size_t _getSectionsCount(bool useMapped=true) const
Definition PEFile.cpp:371
void printSectionsMapping(Executable::addr_type aType)
ExeNodeWrapper * addEntry(ExeNodeWrapper *entry)
virtual bufsize_t getSize()
virtual QString getFieldName(size_t fieldId)
SectionHdrWrapper * getSecHdrAtOffset(offset_t offset, Executable::addr_type addrType, bool roundup, bool verbose=false)
virtual void reloadMapping()
virtual void * getPtr()
static size_t SECT_COUNT_MAX
static size_t SECT_INVALID_INDEX
virtual size_t getFieldsCount()
static std::vector< DWORD > splitCharacteristics(DWORD characteristics)
bufsize_t getMappedVirtualSize()
virtual QString getName()
virtual QString getFieldName(size_t fieldId)
offset_t getContentDeclaredOffset(Executable::addr_type aType)
static void initSecCharacter(std::map< DWORD, QString > &secHdrCharact)
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
bufsize_t getContentDeclaredSize(Executable::addr_type aType)
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField=FIELD_NONE)
static QString translateCharacteristics(DWORD charact)
bufsize_t getContentSize(Executable::addr_type aType, bool recalculate)
offset_t getContentEndOffset(Executable::addr_type aType, bool roundup)
offset_t getContentOffset(Executable::addr_type aType, bool useMapped=true)
static QString getSecHdrAccessRightsDesc(DWORD characteristics)
virtual void * getPtr()
bufsize_t getMappedRawSize()
static const size_t SECNAME_LEN
virtual WrappedValue::data_type containsDataType(size_t fieldId, size_t subField=FIELD_NONE)
virtual bufsize_t getSize()
bool append(dbg_level lvl, const char *format,...)
Definition Util.cpp:8
@ D_WARNING
Definition Util.h:26
bufsize_t roundupToUnit(bufsize_t size, bufsize_t unit)
size_t unitsCount(uint64_t value, uint64_t unit, bool roundup=true)
Definition Util.h:47