BearParser
Portable Executable parsing library (from PE-bear)
SectHdrsWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4using namespace buf_util;
5
6const size_t SECNAME_LEN = 8;
8
10{
11 this->clear();
12
13 this->header = NULL;
14 getPtr();
15 reloadName();
16 return true;
17}
18
20{
21 if (m_PE == NULL) return NULL;
22
23 if (header != NULL) {
24 return (void*) this->header;
25 }
26 //validate it above, not here...
27 //if (this->sectNum >= m_PE->hdrSectionsNum()) return NULL;
28
29 offset_t firstSecOffset = m_PE->secHdrsOffset();
30 offset_t secOffset = firstSecOffset + (this->sectNum * sizeof(IMAGE_SECTION_HEADER));
31
32 //cache the header:
33 this->header = (IMAGE_SECTION_HEADER*) m_PE->getContentAt(secOffset, sizeof(IMAGE_SECTION_HEADER));
34 return (void*) this->header;
35}
36
38{
39 IMAGE_SECTION_HEADER* header = (IMAGE_SECTION_HEADER*) getPtr();
40 if (!header) return false;
41
42 if (this->name) {
43 if (memcmp(this->name, header->Name, SECNAME_LEN) == 0) {
44 return true; //no need to reload
45 }
46 }
47 const size_t BUF_LEN = SECNAME_LEN + 2;
48
49 char *buf = new char[BUF_LEN];
50 memset(buf, 0, BUF_LEN);
51 snprintf(buf, BUF_LEN, "%.8s", (char*) header->Name);
52
53 //delete the previous pointer...
54 delete []this->name;
55 //...and set the new:
56 this->name = buf;
57 return true;
58}
59
61{
62 if (m_PE == NULL) return 0;
63 return sizeof(IMAGE_SECTION_HEADER);
64}
65
67{
68 //reloadName();
69 if (!this->name) return ""; //cannot load
70 return this->name;
71}
72
73void* SectionHdrWrapper::getFieldPtr(size_t fieldId, size_t subField)
74{
75 IMAGE_SECTION_HEADER* sec = (IMAGE_SECTION_HEADER*) getPtr();
76 if (!sec) return NULL;
77 if (!this->name) return NULL;
78 switch (fieldId)
79 {
80 case NAME: return (void*) &sec->Name;
81 case VSIZE: return (void*) &sec->Misc.VirtualSize;
82 case VPTR: return (void*) &sec->VirtualAddress;
83 case RSIZE: return (void*) &sec->SizeOfRawData;
84 case RPTR: return(void*) &sec->PointerToRawData;
85
86 case RELOC_PTR: return (void*) &sec->PointerToRelocations;
87 case RELOC_NUM: return (void*) &sec->NumberOfRelocations;
88 case LINENUM_PTR: return (void*) &sec->PointerToLinenumbers;
89 case LINENUM_NUM: return (void*) &sec->NumberOfLinenumbers;
90
91 case CHARACT: return (void*) &sec->Characteristics;
92 }
93 return this->getPtr();
94}
95
96QString SectionHdrWrapper::getFieldName(size_t fieldId)
97{
98 switch (fieldId)
99 {
100 case NAME: return "Name";
101 case VSIZE: return "Virtual Size";
102 case VPTR: return "Virtual Addr.";
103 case RSIZE: return "Raw size";
104 case RPTR: return "Raw Addr.";
105 case CHARACT: return "Characteristics";
106 case RELOC_PTR: return "Ptr to Reloc.";
107 case RELOC_NUM: return "Num. of Reloc.";
108 case LINENUM_PTR: return "Ptr to Linenum.";
109 case LINENUM_NUM: return "Num. of Linenum.";
110 }
111 return "";
112}
113
115{
116 switch (fieldId)
117 {
118 case VPTR: return Executable::RVA;
119 case RPTR: return Executable::RAW;
120 //case RELOC_PTR: return Executable::RAW;
121 }
123}
124
126{
127 if (fieldId == NAME) {
129 }
130 return WrappedValue::INT;
131}
132
133
134// offset that is declared in header
136{
137 if (this->header == NULL) return INVALID_ADDR;
138 offset_t offset = INVALID_ADDR;
139
140 if (aType == Executable::RAW) {
141 offset = static_cast<offset_t>(this->header->PointerToRawData);//(this->getNumValue(RPTR, &isOk));
142 } else if (aType == Executable::VA || aType == Executable::RVA) {
143 offset = static_cast<offset_t>(this->header->VirtualAddress);//this->getNumValue(VPTR, &isOk));
144 }
145 return offset;
146}
147
149{
150 offset_t offset = getContentDeclaredOffset(aType);
151 if (!useMapped) {
152 return offset; //returning as is
153 }
154 if (aType == Executable::RAW) {
155 const size_t peSize = m_PE->getMappedSize(aType);
156 const offset_t minAlign = m_PE->getAlignment(aType);
157 if (offset < minAlign || offset > peSize) {
158 offset = INVALID_ADDR;
159 }
160 }
161 return offset;
162}
163
165{
166 const bool useMapped = true;
167 offset_t startOffset = getContentOffset(addrType, useMapped);
168 if (startOffset == INVALID_ADDR) return INVALID_ADDR;
169
170 offset_t endOffset = static_cast<offset_t>(getContentSize(addrType, roundup)) + startOffset;
171 return endOffset;
172}
173
174// size that is declared in header
176{
177 if (this->header == NULL) return 0;
178 bufsize_t size = 0;
179
180 if (aType == Executable::RAW) {
181 size = static_cast<bufsize_t>(this->header->SizeOfRawData);//this->getNumValue(RSIZE, &isOk));
182 } else if (aType == Executable::VA || aType == Executable::RVA) {
183 size = static_cast<bufsize_t>(this->header->Misc.VirtualSize);//this->getNumValue(VSIZE, &isOk));
184 }
185 return size;
186}
187
188//RAW size that is really mapped
190{
192
193 const offset_t secOffset = getContentOffset(aType);
194 if (secOffset == INVALID_ADDR) {
195 return 0; //invalid addr, nothing is mapped
196 }
197 const bufsize_t dRawSize = getContentDeclaredSize(aType);
198 if (dRawSize == 0) {
199 return 0; // no changes
200 }
201
202 const bufsize_t peSize = m_PE->getRawSize();
203 if (secOffset > peSize) {
204 return 0; //out of scope
205 }
206 bufsize_t roundedUpSize = dRawSize;
207 bufsize_t unit = m_PE->getAlignment(aType);
208 if (unit != 0) {
209 roundedUpSize = roundupToUnit(dRawSize, unit);
210 }
211 const bufsize_t secEnd = secOffset + roundedUpSize;
212
213 //trim to the file size:
214 if (secEnd > peSize) {
215
216 const bufsize_t trimmedSize = peSize - secOffset; // trim to the file size
218
219 if (trimmedSize > virtualSize) {
220 return virtualSize;
221 }
222 return trimmedSize;
223 }
224 return roundedUpSize;
225}
226
227//VirtualSize that is really mapped
229{
231
232 const offset_t startOffset = getContentOffset(aType);
233 if (startOffset == INVALID_ADDR) {
234 return 0; //invalid addr, nothing is mapped
235 }
236
237 bufsize_t dVirtualSize = getContentDeclaredSize(aType);
238 bufsize_t mRawSize = getMappedRawSize();
239 bufsize_t mVirtualSize = (dVirtualSize > mRawSize) ? dVirtualSize : mRawSize;
240
241 bufsize_t unit = m_PE->getAlignment(aType);
242 if (unit == 0) {
243 return mRawSize; // do not roundup
244 }
245 bufsize_t size = roundupToUnit(mVirtualSize, unit);
246 return size;
247}
248
250{
251 if (this->header == NULL) return 0;
252 if (m_PE == NULL) return 0;
253
254 bufsize_t size = 0;
255 if (roundup == false) {
256 size = getContentDeclaredSize(aType);
257 //printf("Declared size = %llx\n---\n", size);
258 return size;
259 }
260 //---
261 if (aType == Executable::RAW) {
262 //printf ("R: ");
263 size = getMappedRawSize();
264 }
265 if (aType == Executable::RVA || aType == Executable::VA) {
266 size = getMappedVirtualSize();
267 //printf ("V: ");
268 }
269 //printf("Mapped size = %llx\n", size);
270 return size;
271}
272
273//-----------------------------------------------------------------------------------
274
276{
277 SectionHdrWrapper* sEntry = dynamic_cast<SectionHdrWrapper*> (entry);
278 if (sEntry == NULL) {
279 return false;
280 }
281 return true;
282}
283
285{
286 offset_t nextOffset = getNextEntryOffset();
287 bufsize_t entrySize = geEntrySize();
288 if (entrySize == 0) return false;
289
290 bufsize_t paddedSize = entrySize;
291 bool haveSpace = this->m_Exe->isAreaEmpty(nextOffset, paddedSize);
292 return haveSpace;
293}
294
296{
297 if (m_PE == NULL) return NULL;
298
299 size_t secCount = m_PE->hdrSectionsNum();
300 if (secCount == SECT_COUNT_MAX) return NULL; //limit exceeded
301
302 if (ExeNodeWrapper::addEntry(entry) == NULL) return NULL;
303
304 size_t count = secCount + 1;
305 if (m_PE->setHdrSectionsNum(count) == false) {
306 return NULL;
307 }
308 return getLastEntry();
309}
310
312{
314 this->rSec.clear();
315 this->vSec.clear();
316}
317
319{
320 SectionHdrWrapper *sec = new SectionHdrWrapper(this->m_PE, entryNum);
321 if (sec == NULL) return false;
322 if (sec->getPtr() == NULL) {
323 Logger::append(Logger::D_WARNING, "Deleting invalid section...");
324 delete sec;
325 sec = NULL;
326 return false;
327 }
328 this->entries.push_back(sec);
329 addMapping(sec);
330 return true;
331}
332
334{
335 if (sec == NULL) return;
336
337 bool roundup = true;
338 if (sec->getContentSize(Executable::RAW, true) == 0) {
339 //printf("skipping empty section..\n");
340 return;
341 }
344
347 vSec[endRVA] = sec;
348
349 if (rSec.find(endRaw) != rSec.end()) { //already exist
350 SectionHdrWrapper* prevSec = rSec[endRaw];
351 if (prevSec == NULL) return;
353 //printf("endRaw = %llX - SKIP\n", endRaw);
354 return; //skip
355 }
356 }
357 rSec[endRaw] = sec;
358 return;
359}
360
362{
363 this->rSec.clear();
364 this->vSec.clear();
365
366 size_t count = this->getEntriesCount();
367 for (size_t i = 0; i < count; i++) {
368 SectionHdrWrapper* sec = dynamic_cast<SectionHdrWrapper*>(this->getEntryAt(i));
369 if (sec == NULL) continue;
370 addMapping(sec);
371 }
372}
373
375{
376 this->clear();
377 if (this->m_PE == NULL) return false;
378
379 size_t count = this->m_PE->hdrSectionsNum();
380
381 for (size_t i = 0; i < count; i++) {
382 if (this->loadNextEntry(i) == false) break;
383 }
384 return true;
385}
386
388{
389 return this->entries.size();
390}
391
393{
394 if (entries.size() == 0) return NULL;
395 return entries[0]->getPtr();
396}
397
399{
400 if (this->m_PE == NULL) return 0;
401
402 size_t secCount = getFieldsCount();
403
404 offset_t hdrOffset = m_PE->secHdrsOffset();
405 offset_t fileSize = m_PE->getRawSize();
406 offset_t endOffset = hdrOffset + (secCount * sizeof(IMAGE_SECTION_HEADER));
407
408 if (endOffset > fileSize) {
409 return bufsize_t (fileSize - hdrOffset);
410 }
411 return bufsize_t (endOffset - hdrOffset);
412}
413/*
414void* SectHdrsWrapper::getFieldPtr(size_t fieldId, size_t subField)
415{
416 if (fieldId >= entries.size()) return NULL;
417 return entries[fieldId]->getFieldPtr(subField);
418}
419*/
420QString SectHdrsWrapper::getFieldName(size_t fieldId)
421{
422 if (fieldId >= entries.size()) return NULL;
423 return entries[fieldId]->getName();
424}
425
427{
428 size_t size = this->entries.size();
429 std::map<offset_t, SectionHdrWrapper*> *secMap = NULL;
430
431 if (addrType == Executable::RAW) {
432 secMap = &this->rSec;
433 } else if (addrType == Executable::RVA || addrType == Executable::VA) {
434 secMap = &this->vSec;
435 }
436 if (secMap == NULL) return NULL;
437
438 std::map<offset_t, SectionHdrWrapper*>::iterator found = secMap->lower_bound(offset);
439 std::map<offset_t, SectionHdrWrapper*>::iterator itr;
440 for (itr = found; itr != secMap->end(); itr++) {
441 SectionHdrWrapper* sec = itr->second;
442 if (sec == NULL) continue; //TODO: check it
443 if (verbose) {
444 printf("found [%llX] key: %llX sec: %llX %llX\n",
445 static_cast<unsigned long long>(offset),
446 static_cast<unsigned long long>(itr->first),
447 static_cast<unsigned long long>(sec->getContentOffset(addrType)),
448 static_cast<unsigned long long>(sec->getContentEndOffset(addrType, false))
449 );
450 }
451
452 offset_t startOffset = sec->getContentOffset(addrType);
453 if (startOffset == INVALID_ADDR) continue;
454
455 offset_t endOffset = sec->getContentEndOffset(addrType, roundup);
456
457 if (offset >= startOffset && offset < endOffset) {
458 return sec;
459 }
460 if (offset < startOffset) break;
461 }
462 return NULL;
463}
464
466{
467 std::map<offset_t, SectionHdrWrapper*> *secMap = NULL;
468
469 if (aType == Executable::RAW) {
470 secMap = &this->rSec;
471 } else if (aType == Executable::RVA || aType == Executable::VA) {
472 secMap = &this->vSec;
473 }
474 if (secMap == NULL) return;
475
476 std::map<offset_t, SectionHdrWrapper*>::iterator itr;
477 for (itr = secMap->begin(); itr != secMap->end(); itr++) {
478 SectionHdrWrapper* sec = itr->second;
479 offset_t secEnd = itr->first;
480
481 printf("[%llX] %s %llX %llX\n",
482 static_cast<unsigned long long>(secEnd),
483 sec->getName().toStdString().c_str(),
484 static_cast<unsigned long long>(sec->getContentOffset(aType)),
485 static_cast<unsigned long long>(sec->getContentEndOffset(aType, true))
486 );
487 }
488 printf("---\n\n");
489}
490
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
const size_t SECNAME_LEN
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:57
virtual offset_t getRawSize() const
Definition: Executable.h:54
virtual bufsize_t getMappedSize(Executable::addr_type aType)
Definition: PEFile.cpp:201
size_t hdrSectionsNum()
Definition: PEFile.cpp:241
bool setHdrSectionsNum(size_t newNum)
Definition: PEFile.cpp:250
virtual bufsize_t getAlignment(Executable::addr_type aType)
Definition: PEFile.h:68
offset_t secHdrsOffset()
Definition: PEFile.h:78
PEFile * m_PE
Definition: PENodeWrapper.h:36
std::map< offset_t, SectionHdrWrapper * > rSec
void printSectionsMapping(Executable::addr_type aType)
ExeNodeWrapper * addEntry(ExeNodeWrapper *entry)
virtual bufsize_t getSize()
virtual bool loadNextEntry(size_t entryNum)
virtual QString getFieldName(size_t fieldId)
SectionHdrWrapper * getSecHdrAtOffset(offset_t offset, Executable::addr_type addrType, bool roundup, bool verbose=false)
bool isMyEntryType(ExeNodeWrapper *entry)
virtual void reloadMapping()
virtual void * getPtr()
static size_t SECT_COUNT_MAX
std::map< offset_t, SectionHdrWrapper * > vSec
void addMapping(SectionHdrWrapper *sec)
virtual size_t getFieldsCount()
bufsize_t getMappedVirtualSize()
virtual QString getName()
virtual QString getFieldName(size_t fieldId)
bufsize_t getContentSize(Executable::addr_type aType, bool roundup)
offset_t getContentDeclaredOffset(Executable::addr_type aType)
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)
offset_t getContentEndOffset(Executable::addr_type aType, bool roundup)
offset_t getContentOffset(Executable::addr_type aType, bool useMapped=true)
virtual void * getPtr()
bufsize_t getMappedRawSize()
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)
uint64_t roundup(uint64_t value, uint64_t unit)
Definition: Util.h:45