1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """
32 Common PE structures.
33
34 @group Main class:
35 PE
36
37 @group PE fields:
38 FileHeader, DosHeader, NtHeaders, OptionalHeader, OptionalHeader64,
39 SectionHeader, SectionHeaders, Sections
40 """
41
42 __revision__ = "$Id$"
43
44 __all__ = [
45 "PE",
46 "FileHeader",
47 "DosHeader",
48 "NtHeaders",
49 "OptionalHeader",
50 "OptionalHeader64",
51 "SectionHeader",
52 "SectionHeaders",
53 "Sections",
54 ]
55
56 import os
57 import hashlib
58 import binascii
59
60 import datadirs
61 import datatypes
62 import consts
63 import excep
64 import utils
65 import directories
66 import baseclasses
67
68 from struct import pack, unpack
71 """PE object."""
72 - def __init__(self, pathToFile = None, data = None, fastLoad = False, verbose = False):
73 """
74 A class representation of the Portable Executable format.
75 @see: PE format U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms680547%28v=vs.85%29.aspx}
76
77 @type pathToFile: str
78 @param pathToFile: Path to the file to load.
79
80 @type data: str
81 @param data: PE data to process.
82
83 @type fastLoad: bool
84 @param fastLoad: If set to C{False}, the PE class won't parse the directory data, just headers.
85 The L{fullLoad} method is available to load the directories in case the C{fastLoad} parameter was set to C{False}.
86 If set to C{True}, the entire PE will be parsed.
87
88 @type verbose: bool
89 @param verbose: Verbose output.
90
91 @todo: Parse the Resource directory.
92 @todo: Parse the Delay Imports directory.
93 @todo: Parse the Exception directory.
94 @todo: Add dump() method to show nicely all the structure of the PE file.
95 """
96 self.dosHeader = DosHeader()
97 self.dosStub = PE.getDosStub()
98 self.ntHeaders = NtHeaders()
99 self.sectionHeaders = SectionHeaders()
100 self.sections = Sections(self.sectionHeaders)
101 self.overlay = ""
102 self.signature = ""
103
104 self._data = data
105 self._pathToFile = pathToFile
106
107 self._verbose = verbose
108 self._fastLoad = fastLoad
109 self.PE_TYPE = None
110
111 if self._data and not isinstance(data, utils.ReadData):
112 rd = utils.ReadData(data)
113 self._internalParse(rd)
114 elif self._pathToFile:
115 if os.path.exists(self._pathToFile):
116
117 stat = os.stat(self._pathToFile)
118 if stat.st_size == 0:
119 raise PEException("File is empty.")
120
121 self._data = self.readFile(self._pathToFile)
122 rd = utils.ReadData(self._data)
123
124 if self.hasMZSignature(rd) and self.hasPESignature(rd):
125 rd.setOffset(0)
126 self._internalParse(rd)
127 else:
128 raise excep.PyPe32Exception("MZ/PE signature not present. Maybe not a PE file?")
129 else:
130 raise excep.NotValidPathException("The specified path does not exists.")
131
132 self.validate()
133
135 """
136 Check for MZ signature.
137
138 @type rd: L{ReadData}
139 @param rd: A L{ReadData} object.
140
141 @rtype: bool
142 @return: True is the given L{ReadData} stream has the MZ signature. Otherwise, False.
143 """
144 rd.setOffset(0)
145 sign = rd.read(2)
146 if sign == "MZ":
147 return True
148 return False
149
151 """
152 Check for PE signature.
153
154 @type rd: L{ReadData}
155 @param rd: A L{ReadData} object.
156
157 @rtype: bool
158 @return: True is the given L{ReadData} stream has the PE signature. Otherwise, False.
159 """
160 rd.setOffset(0)
161 e_lfanew_offset = unpack("<L", rd.readAt(0x3c, 4))[0]
162 sign = rd.readAt(e_lfanew_offset, 2)
163 if sign == "PE":
164 return True
165 return False
166
168 """
169 Performs validations over some fields of the PE structure to determine if the loaded file has a valid PE format.
170
171 @raise PEException: If an invalid value is found into the PE instance.
172 """
173
174 if self.dosHeader.e_magic.value != consts.MZ_SIGNATURE:
175 raise excep.PEException("Invalid MZ signature. Found %d instead of %d." % (self.dosHeader.magic.value, consts.MZ_SIGNATURE))
176
177 if self.dosHeader.e_lfanew.value > len(self):
178 raise excep.PEException("Invalid e_lfanew value. Probably not a PE file.")
179
180 if self.ntHeaders.signature.value != consts.PE_SIGNATURE:
181 raise excep.PEException("Invalid PE signature. Found %d instead of %d." % (self.ntHeaders.optionaHeader.signature.value, consts.PE_SIGNATURE))
182
183 if self.ntHeaders.optionalHeader.numberOfRvaAndSizes.value > 0x10:
184 print excep.PEWarning("Suspicious value for NumberOfRvaAndSizes: %d." % self.ntHeaders.optionaHeader.numberOfRvaAndSizes.value)
185
187 """
188 Returns data from a file.
189
190 @type pathToFile: str
191 @param pathToFile: Path to the file.
192
193 @rtype: str
194 @return: The data from file.
195 """
196 fd = open(pathToFile, "rb")
197 data = fd.read()
198 fd.close()
199 return data
200
201 - def write(self, filename = ""):
202 """
203 Writes data from L{PE} object to a file.
204
205 @rtype: str
206 @return: The L{PE} stream data.
207
208 @raise IOError: If the file could not be opened for write operations.
209 """
210 file_data = str(self)
211 if filename:
212 try:
213 self.__write(filename, file_data)
214 except IOError:
215 raise IOError("File could not be opened for write operations.")
216 else:
217 return file_data
218
219 - def __write(self, thePath, theData):
220 """
221 Write data to a file.
222
223 @type thePath: str
224 @param thePath: The file path.
225
226 @type theData: str
227 @param theData: The data to write.
228 """
229 fd = open(thePath, "wb")
230 fd.write(theData)
231 fd.close()
232
234 return len(str(self))
235
237 if self._data is None and self._pathToFile is None:
238 padding = "\x00" * (self.sectionHeaders[0].pointerToRawData.value - self._getPaddingToSectionOffset())
239 else:
240 padding = self._getPaddingDataToSectionOffset()
241
242 pe = str(self.dosHeader) + str(self.dosStub) + str(self.ntHeaders) + str(self.sectionHeaders) + str(padding) + str(self.sections) + str(self.overlay)
243
244
245 return pe
246
248 """
249 Updates the data in every L{Directory} object.
250
251 @type peStr: str
252 @param peStr: C{str} representation of the L{PE} object.
253
254 @rtype: str
255 @return: A C{str} representation of the L{PE} object.
256 """
257 dataDirs = self.ntHeaders.optionalHeader.dataDirectory
258 wr = utils.WriteData(data)
259
260 for dir in dataDirs:
261 dataToWrite = str(dir.info)
262 if len(dataToWrite) != dir.size.value and self._verbose:
263 print excep.DataLengthException("Warning: current size of %s directory does not match with dataToWrite length %d." % (dir.size.value, len(dataToWrite)))
264 wr.setOffset(self.getOffsetFromRva(dir.rva.value))
265 wr.write(dataToWrite)
266 return str(wr)
267
269 """
270 Returns the data between the last section header and the begenning of data from the first section.
271
272 @rtype: str
273 @return: Data between last section header and the begenning of the first section.
274 """
275 start = self._getPaddingToSectionOffset()
276 end = self.sectionHeaders[0].pointerToRawData.value - start
277 return self._data[start:start+end]
278
279 - def _getSignature(self, readDataInstance, dataDirectoryInstance):
280 """
281 Returns the digital signature within a digital signed PE file.
282
283 @type readDataInstance: L{ReadData}
284 @param readDataInstance: A L{ReadData} instance containing a PE file data.
285
286 @type dataDirectoryInstance: L{DataDirectory}
287 @param dataDirectoryInstance: A L{DataDirectory} object containing the information about directories.
288
289 @rtype: str
290 @return: A string with the digital signature.
291
292 @raise InstanceErrorException: If the C{readDataInstance} or the C{dataDirectoryInstance} were not specified.
293 """
294 signature = ""
295
296 if readDataInstance is not None and dataDirectoryInstance is not None:
297 securityDirectory = dataDirectoryInstance[consts.SECURITY_DIRECTORY]
298
299 if(securityDirectory.rva.value and securityDirectory.size.value):
300 readDataInstance.setOffset(self.getOffsetFromRva(securityDirectory.rva.value))
301
302 signature = readDataInstance.read(securityDirectory.size.value)
303 else:
304 raise excep.InstanceErrorException("ReadData instance or DataDirectory instance not specified.")
305
306 return signature
307
308 - def _getOverlay(self, readDataInstance, sectionHdrsInstance):
309 """
310 Returns the overlay data from the PE file.
311
312 @type readDataInstance: L{ReadData}
313 @param readDataInstance: A L{ReadData} instance containing the PE file data.
314
315 @type sectionHdrsInstance: L{SectionHeaders}
316 @param sectionHdrsInstance: A L{SectionHeaders} instance containing the information about the sections present in the PE file.
317
318 @rtype: str
319 @return: A string with the overlay data from the PE file.
320
321 @raise InstanceErrorException: If the C{readDataInstance} or the C{sectionHdrsInstance} were not specified.
322 """
323 if readDataInstance is not None and sectionHdrsInstance is not None:
324
325 try:
326 offset = sectionHdrsInstance[-1].pointerToRawData.value + sectionHdrsInstance[-1].sizeOfRawData.value
327 readDataInstance.setOffset(offset)
328 except excep.WrongOffsetValueException:
329 if self._verbose:
330 print "It seems that the file has no overlay data."
331 else:
332 raise excep.InstanceErrorException("ReadData instance or SectionHeaders instance not specified.")
333
334 return readDataInstance.data[readDataInstance.offset:]
335
337 """
338 Converts an offset to an RVA.
339
340 @type rva: int
341 @param rva: The RVA to be converted.
342
343 @rtype: int
344 @return: An integer value representing an offset in the PE file.
345 """
346 offset = -1
347 s = self.getSectionByRva(rva)
348
349 if s != offset:
350 offset = (rva - self.sectionHeaders[s].virtualAddress.value) + self.sectionHeaders[s].pointerToRawData.value
351 else:
352 offset = rva
353
354 return offset
355
357 """
358 Converts a RVA to an offset.
359
360 @type offset: int
361 @param offset: The offset value to be converted to RVA.
362
363 @rtype: int
364 @return: The RVA obtained from the given offset.
365 """
366 rva = -1
367 s = self.getSectionByOffset(offset)
368
369 if s:
370 rva = (offset - self.sectionHeaders[s].pointerToRawData.value) + self.sectionHeaders[s].virtualAddress.value
371
372 return rva
373
375 """
376 Given an offset in the file, tries to determine the section this offset belong to.
377
378 @type offset: int
379 @param offset: Offset value.
380
381 @rtype: int
382 @return: An index, starting at 0, that represents the section the given offset belongs to.
383 """
384 index = -1
385 for i in range(len(self.sectionHeaders)):
386 if (offset < self.sectionHeaders[i].pointerToRawData.value + self.sectionHeaders[i].sizeOfRawData.value):
387 index = i
388 break
389 return index
390
392 """
393 Given a string representing a section name, tries to find the section index.
394
395 @type name: str
396 @param name: A section name.
397
398 @rtype: int
399 @return: The index, starting at 0, of the section.
400 """
401 index = -1
402
403 if name:
404 for i in range(len(self.sectionHeaders)):
405 if self.sectionHeaders[i].name.value.find(name) >= 0:
406 index = i
407 break
408 return index
409
411 """
412 Given a RVA in the file, tries to determine the section this RVA belongs to.
413
414 @type rva: int
415 @param rva: RVA value.
416
417 @rtype: int
418 @return: An index, starting at 1, that represents the section the given RVA belongs to.
419 """
420
421 index = -1
422 if rva < self.sectionHeaders[0].virtualAddress.value:
423 return index
424
425 for i in range(len(self.sectionHeaders)):
426 fa = self.ntHeaders.optionalHeader.fileAlignment.value
427 prd = self.sectionHeaders[i].pointerToRawData.value
428 srd = self.sectionHeaders[i].sizeOfRawData.value
429 if len(str(self)) - self._adjustFileAlignment(prd, fa) < srd:
430 size = self.sectionHeaders[i].misc.value
431 else:
432 size = max(srd, self.sectionHeaders[i].misc.value)
433 if (self.sectionHeaders[i].virtualAddress.value <= rva) and rva < (self.sectionHeaders[i].virtualAddress.value + size):
434 index = i
435 break
436
437 return index
438
439 @staticmethod
441 """
442 Returns a default DOS stub.
443
444 @rtype: str
445 @return: A defaul DOS stub.
446 """
447 return "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A240000000000000037E338C97382569A7382569A7382569A6DD0D29A6982569A6DD0C39A6382569A6DD0D59A3A82569A54442D9A7482569A7382579A2582569A6DD0DC9A7282569A6DD0C29A7282569A6DD0C79A7282569A526963687382569A000000000000000000000000000000000000000000000000".decode("hex")
448
450 """
451 Returns the offset to last section header present in the PE file.
452
453 @rtype: int
454 @return: The offset where the end of the last section header resides in the PE file.
455 """
456 return len(str(self.dosHeader) + str(self.dosStub) + str(self.ntHeaders) + str(self.sectionHeaders))
457
459 """Parse all the directories in the PE file."""
460 self._parseDirectories(self.ntHeaders.optionalHeader.dataDirectory, self.PE_TYPE)
461
463 """
464 Populates the attributes of the L{PE} object.
465
466 @type readDataInstance: L{ReadData}
467 @param readDataInstance: A L{ReadData} instance with the data of a PE file.
468 """
469 self.dosHeader = DosHeader.parse(readDataInstance)
470
471 self.dosStub = readDataInstance.read(self.dosHeader.e_lfanew.value - readDataInstance.offset)
472 self.ntHeaders = NtHeaders.parse(readDataInstance)
473
474 if self.ntHeaders.optionalHeader.magic.value == consts.PE32:
475 self.PE_TYPE = consts.PE32
476 elif self.ntHeaders.optionalHeader.magic.value == consts.PE64:
477 self.PE_TYPE = consts.PE64
478 readDataInstance.setOffset(readDataInstance.tell() - OptionalHeader().sizeof())
479 self.ntHeaders.optionalHeader = OptionalHeader64.parse(readDataInstance)
480
481 self.sectionHeaders = SectionHeaders.parse(readDataInstance, self.ntHeaders.fileHeader.numberOfSections.value)
482
483
484
485 readDataInstance.setOffset(self.sectionHeaders[0].pointerToRawData.value)
486
487 self.sections = Sections.parse(readDataInstance, self.sectionHeaders)
488
489 self.overlay = self._getOverlay(readDataInstance, self.sectionHeaders)
490 self.signature = self._getSignature(readDataInstance, self.ntHeaders.optionalHeader.dataDirectory)
491
492 if not self._fastLoad:
493 self._parseDirectories(self.ntHeaders.optionalHeader.dataDirectory, self.PE_TYPE)
494
495 - def addSection(self, data, name =".pype32\x00", flags = 0x60000000):
496 """
497 Adds a new section to the existing L{PE} instance.
498
499 @type data: str
500 @param data: The data to be added in the new section.
501
502 @type name: str
503 @param name: (Optional) The name for the new section.
504
505 @type flags: int
506 @param flags: (Optional) The attributes for the new section.
507 """
508 fa = self.ntHeaders.optionalHeader.fileAlignment.value
509 sa = self.ntHeaders.optionalHeader.sectionAlignment.value
510
511 padding = "\xcc" * (fa - len(data))
512 sh = SectionHeader()
513
514 if len(self.sectionHeaders):
515
516 vaLastSection = self.sectionHeaders[-1].virtualAddress.value
517 sizeLastSection = self.sectionHeaders[-1].misc.value
518 pointerToRawDataLastSection = self.sectionHeaders[-1].pointerToRawData.value
519 sizeOfRawDataLastSection = self.sectionHeaders[-1].sizeOfRawData.value
520
521 sh.virtualAddress.value = self._adjustSectionAlignment(vaLastSection + sizeLastSection, fa, sa)
522 sh.pointerToRawData.value = self._adjustFileAlignment(pointerToRawDataLastSection + sizeOfRawDataLastSection, fa)
523
524 sh.misc.value = self._adjustSectionAlignment(len(data), fa, sa) or consts.DEFAULT_PAGE_SIZE
525 sh.sizeOfRawData.value = self._adjustFileAlignment(len(data), fa) or consts.DEFAULT_FILE_ALIGNMENT
526 sh.characteristics.value = flags
527 sh.name.value = name
528
529 self.sectionHeaders.append(sh)
530 self.sections.append(data + padding)
531
532 self.ntHeaders.fileHeader.numberOfSections.value += 1
533
535 """
536 Extends an existing section in the L{PE} instance.
537
538 @type sectionIndex: int
539 @param sectionIndex: The index for the section to be extended.
540
541 @type data: str
542 @param data: The data to include in the section.
543
544 @raise IndexError: If an invalid C{sectionIndex} was specified.
545 @raise SectionHeadersException: If there is not section to extend.
546 """
547
548 fa = self.ntHeaders.optionalHeader.fileAlignment.value
549 sa = self.ntHeaders.optionalHeader.sectionAlignment.value
550
551 if len(self.sectionHeaders):
552 if len(self.sectionHeaders) == sectionIndex:
553 try:
554
555 vzLastSection = self.sectionHeaders[-1].misc.value
556 rzLastSection = self.sectionHeaders[-1].sizeOfRawData.value
557
558 self.sectionHeaders[-1].misc.value = self._adjustSectionAlignment(vzLastSection + len(data), fa, sa)
559 self.sectionHeaders[-1].sizeOfRawData.value = self._adjustFileAlignment(rzLastSection + len(data), fa)
560
561 vz = self.sectionHeaders[-1].misc.value
562 rz = self.sectionHeaders[-1].sizeOfRawData.value
563
564 except IndexError:
565 raise IndexError("list index out of range.")
566
567 if vz < rz:
568 print "WARNING: VirtualSize (%x) is less than SizeOfRawData (%x)" % (vz, rz)
569
570 if len(data) % fa == 0:
571 self.sections[-1] += data
572 else:
573 self.sections[-1] += data + "\xcc" * (fa - len(data) % fa)
574
575 else:
576
577 try:
578
579 counter = sectionIndex - 1
580
581 vzCurrentSection = self.sectionHeaders[counter].misc.value
582 rzCurrentSection = self.sectionHeaders[counter].sizeOfRawData.value
583
584 self.sectionHeaders[counter].misc.value = self._adjustSectionAlignment(vzCurrentSection + len(data), fa, sa)
585 self.sectionHeaders[counter].sizeOfRawData.value = self._adjustFileAlignment(rzCurrentSection + len(data), fa)
586
587 if len(data) % fa == 0:
588 self.sections[counter] += data
589 else:
590 self.sections[counter] += data + "\xcc" * (fa - len(data) % fa)
591
592 counter += 1
593
594 while(counter != len(self.sectionHeaders)):
595 vzPreviousSection = self.sectionHeaders[counter - 1].misc.value
596 vaPreviousSection = self.sectionHeaders[counter - 1].virtualAddress.value
597 rzPreviousSection = self.sectionHeaders[counter - 1].sizeOfRawData.value
598 roPreviousSection = self.sectionHeaders[counter - 1].pointerToRawData.value
599
600
601 self.sectionHeaders[counter].virtualAddress.value = self._adjustSectionAlignment(vzPreviousSection + vaPreviousSection, fa, sa)
602 self.sectionHeaders[counter].pointerToRawData.value = self._adjustFileAlignment(rzPreviousSection + roPreviousSection, fa)
603
604 vz = self.sectionHeaders[counter].virtualAddress.value
605 rz = self.sectionHeaders[counter].pointerToRawData.value
606
607 if vz < rz:
608 print "WARNING: VirtualSize (%x) is less than SizeOfRawData (%x)" % (vz, rz)
609
610 counter += 1
611
612 except IndexError:
613 raise IndexError("list index out of range.")
614
615 else:
616 raise excep.SectionHeadersException("There is no section to extend.")
617
619 """
620 Fixes the necessary fields in the PE file instance in order to create a valid PE32. i.e. SizeOfImage.
621 """
622 sizeOfImage = 0
623 for sh in self.sectionHeaders:
624 sizeOfImage += sh.misc
625 self.ntHeaders.optionaHeader.sizeoOfImage.value = self._sectionAlignment(sizeOfImage + 0x1000)
626
628 """
629 Align a value to C{FileAligment}.
630
631 @type value: int
632 @param value: The value to align.
633
634 @type fileAlignment: int
635 @param fileAlignment: The value to be used to align the C{value} parameter.
636
637 @rtype: int
638 @return: The aligned value.
639 """
640 if fileAlignment > consts.DEFAULT_FILE_ALIGNMENT:
641 if not utils.powerOfTwo(fileAlignment):
642 print "Warning: FileAlignment is greater than DEFAULT_FILE_ALIGNMENT (0x200) and is not power of two."
643
644 if fileAlignment < consts.DEFAULT_FILE_ALIGNMENT:
645 return value
646
647 if fileAlignment and value % fileAlignment:
648 return ((value / fileAlignment) + 1) * fileAlignment
649
650 return value
651
653 """
654 Align a value to C{SectionAligment}.
655
656 @type value: int
657 @param value: The value to be aligned.
658
659 @type fileAlignment: int
660 @param fileAlignment: The value to be used as C{FileAlignment}.
661
662 @type sectionAlignment: int
663 @param sectionAlignment: The value to be used as C{SectionAlignment}.
664
665 @rtype: int
666 @return: The aligned value.
667 """
668 if fileAlignment < consts.DEFAULT_FILE_ALIGNMENT:
669 if fileAligment != sectionAlignment:
670 print "FileAlignment does not match SectionAlignment."
671
672 if sectionAlignment < consts.DEFAULT_PAGE_SIZE:
673 sectionAlignment = fileAlignment
674
675 if sectionAlignment and value % sectionAlignment:
676 return sectionAlignment * ((value / sectionAlignment) + 1)
677 return value
678
680 """
681 Returns a C{DWORD} from a given RVA.
682
683 @type rva: int
684 @param rva: The RVA to get the C{DWORD} from.
685
686 @rtype: L{DWORD}
687 @return: The L{DWORD} obtained at the given RVA.
688 """
689 return datatypes.DWORD.parse(utils.ReadData(self.getDataAtRva(rva, 4)))
690
692 """
693 Returns a C{WORD} from a given RVA.
694
695 @type rva: int
696 @param rva: The RVA to get the C{WORD} from.
697
698 @rtype: L{WORD}
699 @return: The L{WORD} obtained at the given RVA.
700 """
701 return datatypes.WORD.parse(utils.ReadData(self.getDataAtRva(rva, 2)))
702
704 """
705 Returns a C{DWORD} from a given offset.
706
707 @type offset: int
708 @param offset: The offset to get the C{DWORD} from.
709
710 @rtype: L{DWORD}
711 @return: The L{DWORD} obtained at the given offset.
712 """
713 return datatypes.DWORD.parse(utils.ReadData(self.getDataAtOffset(offset, 4)))
714
716 """
717 Returns a C{WORD} from a given offset.
718
719 @type offset: int
720 @param offset: The offset to get the C{WORD} from.
721
722 @rtype: L{WORD}
723 @return: The L{WORD} obtained at the given offset.
724 """
725 return datatypes.WORD.parse(utils.ReadData(self.getDataAtOffset(offset, 2)))
726
728 """
729 Returns a C{QWORD} from a given RVA.
730
731 @type rva: int
732 @param rva: The RVA to get the C{QWORD} from.
733
734 @rtype: L{QWORD}
735 @return: The L{QWORD} obtained at the given RVA.
736 """
737 return datatypes.QWORD.parse(utils.ReadData(self.getDataAtRva(rva, 8)))
738
740 """
741 Returns a C{QWORD} from a given offset.
742
743 @type offset: int
744 @param offset: The offset to get the C{QWORD} from.
745
746 @rtype: L{QWORD}
747 @return: The L{QWORD} obtained at the given offset.
748 """
749 return datatypes.QWORD.parse(utils.ReadData(self.getDataAtOffset(offset, 8)))
750
752 """
753 Gets binary data at a given RVA.
754
755 @type rva: int
756 @param rva: The RVA to get the data from.
757
758 @type size: int
759 @param size: The size of the data to be obtained.
760
761 @rtype: str
762 @return: The data obtained at the given RVA.
763 """
764 return self.getDataAtOffset(self.getOffsetFromRva(rva), size)
765
767 """
768 Gets binary data at a given offset.
769
770 @type offset: int
771 @param offset: The offset to get the data from.
772
773 @type size: int
774 @param size: The size of the data to be obtained.
775
776 @rtype: str
777 @return: The data obtained at the given offset.
778 """
779 data = str(self)
780 return data[offset:offset+size]
781
783 """
784 Returns a L{String} object from a given RVA.
785
786 @type rva: int
787 @param rva: The RVA to get the string from.
788
789 @rtype: L{String}
790 @return: A new L{String} object from the given RVA.
791 """
792 d = self.getDataAtRva(rva, 1)
793 resultStr = datatypes.String("")
794 while d != "\x00":
795 resultStr.value += d
796 rva += 1
797 d = self.getDataAtRva(rva, 1)
798 return resultStr
799
801 """
802 Determines if the current L{PE} instance is an Executable file.
803
804 @rtype: bool
805 @return: C{True} if the current L{PE} instance is an Executable file. Otherwise, returns C{False}.
806 """
807 if not self.isDll() and not self.isDriver() and ( consts.IMAGE_FILE_EXECUTABLE_IMAGE & self.ntHeaders.fileHeader.characteristics.value) == consts.IMAGE_FILE_EXECUTABLE_IMAGE:
808 return True
809 return False
810
812 """
813 Determines if the current L{PE} instance is a Dynamic Link Library file.
814
815 @rtype: bool
816 @return: C{True} if the current L{PE} instance is a DLL. Otherwise, returns C{False}.
817 """
818 if (consts.IMAGE_FILE_DLL & self.ntHeaders.fileHeader.characteristics.value) == consts.IMAGE_FILE_DLL:
819 return True
820 return False
821
823 """
824 Determines if the current L{PE} instance is a driver (.sys) file.
825
826 @rtype: bool
827 @return: C{True} if the current L{PE} instance is a driver. Otherwise, returns C{False}.
828 """
829 modules = []
830 imports = self.ntHeaders.optionalHeader.dataDirectory[consts.IMPORT_DIRECTORY].info
831 for module in imports:
832 modules.append(module.metaData.moduleName.value.lower())
833
834 if set(["ntoskrnl.exe", "hal.dll", "ndis.sys", "bootvid.dll", "kdcom.dll"]).intersection(modules):
835 return True
836 return False
837
839 """
840 Determines if the current L{PE} instance is a PE32 file.
841
842 @rtype: bool
843 @return: C{True} if the current L{PE} instance is a PE32 file. Otherwise, returns C{False}.
844 """
845 if self.ntHeaders.optionalHeader.magic.value == consts.PE32:
846 return True
847 return False
848
850 """
851 Determines if the current L{PE} instance is a PE64 file.
852
853 @rtype: bool
854 @return: C{True} if the current L{PE} instance is a PE64 file. Otherwise, returns C{False}.
855 """
856 if self.ntHeaders.optionalHeader.magic.value == consts.PE64:
857 return True
858 return False
859
861 """
862 Determines if the current L{PE} instance is bounded, i.e. has a C{BOUND_IMPORT_DIRECTORY}.
863
864 @rtype: bool
865 @return: Returns C{True} if the current L{PE} instance is bounded. Otherwise, returns C{False}.
866 """
867 boundImportsDir = self.ntHeaders.optionalHeader.dataDirectory[consts.BOUND_IMPORT_DIRECTORY]
868 if boundImportsDir.rva.value and boundImportsDir.size.value:
869 return True
870 return False
871
873 """
874 Determines if the current L{PE} instance has the NXCOMPAT (Compatible with Data Execution Prevention) flag enabled.
875 @see: U{http://msdn.microsoft.com/en-us/library/ms235442.aspx}
876
877 @rtype: bool
878 @return: Returns C{True} if the current L{PE} instance has the NXCOMPAT flag enabled. Otherwise, returns C{False}.
879 """
880 return self.ntHeaders.optionalHeader.dllCharacteristics.value & consts.IMAGE_DLL_CHARACTERISTICS_NX_COMPAT == consts.IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
881
882
883
884
885
887 """
888 Determines if the current L{PE} instance has CFG (Control Flow Guard) flag enabled.
889 @see: U{http://blogs.msdn.com/b/vcblog/archive/2014/12/08/visual-studio-2015-preview-work-in-progress-security-feature.aspx}
890 @see: U{https://msdn.microsoft.com/en-us/library/dn919635%%28v=vs.140%%29.aspx}
891
892 @rtype: bool
893 @return: Returns C{True} if the current L{PE} instance has the CFG flag enabled. Otherwise, return C{False}.
894 """
895 return self.ntHeaders.optionalHeader.dllCharacteristics.value & consts.IMAGE_DLL_CHARACTERISTICS_GUARD_CF == consts.IMAGE_DLL_CHARACTERISTICS_GUARD_CF
896
898 """
899 Determines if the current L{PE} instance has the DYNAMICBASE (Use address space layout randomization) flag enabled.
900 @see: U{http://msdn.microsoft.com/en-us/library/bb384887.aspx}
901
902 @rtype: bool
903 @return: Returns C{True} if the current L{PE} instance has the DYNAMICBASE flag enabled. Otherwise, returns C{False}.
904 """
905 return self.ntHeaders.optionalHeader.dllCharacteristics.value & consts.IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE == consts.IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
906
908 """
909 Determines if the current L{PE} instance has the SAFESEH (Image has Safe Exception Handlers) flag enabled.
910 @see: U{http://msdn.microsoft.com/en-us/library/9a89h429.aspx}
911
912 @rtype: bool
913 @return: Returns C{True} if the current L{PE} instance has the SAFESEH flag enabled. Returns C{False} if SAFESEH is off or -1 if SAFESEH is set to NO.
914 """
915 NOSEH = -1
916 SAFESEH_OFF = 0
917 SAFESEH_ON = 1
918
919 if self.ntHeaders.optionalHeader.dllCharacteristics.value & consts.IMAGE_DLL_CHARACTERISTICS_NO_SEH:
920 return NOSEH
921
922 loadConfigDir = self.ntHeaders.optionalHeader.dataDirectory[consts.CONFIGURATION_DIRECTORY]
923 if loadConfigDir.info:
924 if loadConfigDir.info.SEHandlerTable.value:
925 return SAFESEH_ON
926 return SAFESEH_OFF
927
929 """
930 Parses all the directories in the L{PE} instance.
931
932 @type dataDirectoryInstance: L{DataDirectory}
933 @param dataDirectoryInstance: A L{DataDirectory} object with the directories data.
934
935 @type magic: int
936 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
937 """
938 directories = [(consts.EXPORT_DIRECTORY, self._parseExportDirectory),\
939 (consts.IMPORT_DIRECTORY, self._parseImportDirectory),\
940 (consts.RESOURCE_DIRECTORY, self._parseResourceDirectory),\
941 (consts.EXCEPTION_DIRECTORY, self._parseExceptionDirectory),\
942 (consts.RELOCATION_DIRECTORY, self._parseRelocsDirectory),\
943 (consts.TLS_DIRECTORY, self._parseTlsDirectory),\
944 (consts.DEBUG_DIRECTORY, self._parseDebugDirectory),\
945 (consts.BOUND_IMPORT_DIRECTORY, self._parseBoundImportDirectory),\
946 (consts.DELAY_IMPORT_DIRECTORY, self._parseDelayImportDirectory),\
947 (consts.CONFIGURATION_DIRECTORY, self._parseLoadConfigDirectory),\
948 (consts.NET_METADATA_DIRECTORY, self._parseNetDirectory)]
949
950 for directory in directories:
951 dir = dataDirectoryInstance[directory[0]]
952 if dir.rva.value and dir.size.value:
953 try:
954 dataDirectoryInstance[directory[0]].info = directory[1](dir.rva.value, dir.size.value, magic)
955 except Exception as e:
956 print excep.PEWarning("Error parsing PE directory: %s." % directory[1].__name__.replace("_parse", ""))
957
959 """
960 Parses the C{IMAGE_RESOURCE_DIRECTORY} directory.
961
962 @type rva: int
963 @param rva: The RVA where the C{IMAGE_RESOURCE_DIRECTORY} starts.
964
965 @type size: int
966 @param size: The size of the C{IMAGE_RESOURCE_DIRECTORY} directory.
967
968 @type magic: int
969 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
970
971 @rtype: str
972 @return: The C{IMAGE_RESOURCE_DIRECTORY} data.
973 """
974 return self.getDataAtRva(rva, size)
975
977 """
978 Parses the C{IMAGE_EXCEPTION_DIRECTORY} directory.
979
980 @type rva: int
981 @param rva: The RVA where the C{IMAGE_EXCEPTION_DIRECTORY} starts.
982
983 @type size: int
984 @param size: The size of the C{IMAGE_EXCEPTION_DIRECTORY} directory.
985
986 @type magic: int
987 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
988
989 @rtype: str
990 @return: The C{IMAGE_EXCEPTION_DIRECTORY} data.
991 """
992 return self.getDataAtRva(rva, size)
993
995 """
996 Parses the delay imports directory.
997
998 @type rva: int
999 @param rva: The RVA where the delay imports directory starts.
1000
1001 @type size: int
1002 @param size: The size of the delay imports directory.
1003
1004 @type magic: int
1005 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1006
1007 @rtype: str
1008 @return: The delay imports directory data.
1009 """
1010 return self.getDataAtRva(rva, size)
1011
1013 """
1014 Parses the bound import directory.
1015
1016 @type rva: int
1017 @param rva: The RVA where the bound import directory starts.
1018
1019 @type size: int
1020 @param size: The size of the bound import directory.
1021
1022 @type magic: int
1023 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1024
1025 @rtype: L{ImageBoundImportDescriptor}
1026 @return: A new L{ImageBoundImportDescriptor} object.
1027 """
1028 data = self.getDataAtRva(rva, size)
1029 rd = utils.ReadData(data)
1030 boundImportDirectory = directories.ImageBoundImportDescriptor.parse(rd)
1031
1032
1033 for i in range(len(boundImportDirectory) - 1):
1034 if hasattr(boundImportDirectory[i], "forwarderRefsList"):
1035 if boundImportDirectory[i].forwarderRefsList:
1036 for forwarderRefEntry in boundImportDirectory[i].forwarderRefsList:
1037 offset = forwarderRefEntry.offsetModuleName.value
1038 forwarderRefEntry.moduleName = self.readStringAtRva(offset + rva)
1039
1040 offset = boundImportDirectory[i].offsetModuleName.value
1041 boundImportDirectory[i].moduleName = self.readStringAtRva(offset + rva)
1042 return boundImportDirectory
1043
1078
1080 """
1081 Parses the TLS directory.
1082
1083 @type rva: int
1084 @param rva: The RVA where the TLS directory starts.
1085
1086 @type size: int
1087 @param size: The size of the TLS directory.
1088
1089 @type magic: int
1090 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1091
1092 @rtype: L{TLSDirectory}
1093 @return: A new L{TLSDirectory}.
1094 @note: if the L{PE} instance is a PE64 file then a new L{TLSDirectory64} is returned.
1095 """
1096 data = self.getDataAtRva(rva, size)
1097 rd = utils.ReadData(data)
1098
1099 if magic == consts.PE32:
1100 return directories.TLSDirectory.parse(rd)
1101 elif magic == consts.PE64:
1102 return directories.TLSDirectory64.parse(rd)
1103 else:
1104 raise excep.InvalidParameterException("Wrong magic")
1105
1107 """
1108 Parses the relocation directory.
1109
1110 @type rva: int
1111 @param rva: The RVA where the relocation directory starts.
1112
1113 @type size: int
1114 @param size: The size of the relocation directory.
1115
1116 @type magic: int
1117 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1118
1119 @rtype: L{ImageBaseRelocation}
1120 @return: A new L{ImageBaseRelocation} object.
1121 """
1122 data = self.getDataAtRva(rva, size)
1123
1124 rd = utils.ReadData(data)
1125
1126 relocsArray = directories.ImageBaseRelocation()
1127 while rd.offset < size:
1128 relocEntry = directories.ImageBaseRelocationEntry.parse(rd)
1129 relocsArray.append(relocEntry)
1130 return relocsArray
1131
1133 """
1134 Parses the C{IMAGE_EXPORT_DIRECTORY} directory.
1135
1136 @type rva: int
1137 @param rva: The RVA where the C{IMAGE_EXPORT_DIRECTORY} directory starts.
1138
1139 @type size: int
1140 @param size: The size of the C{IMAGE_EXPORT_DIRECTORY} directory.
1141
1142 @type magic: int
1143 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1144
1145 @rtype: L{ImageExportTable}
1146 @return: A new L{ImageExportTable} object.
1147 """
1148 data = self.getDataAtRva(rva, size)
1149 rd = utils.ReadData(data)
1150
1151 iet = directories.ImageExportTable.parse(rd)
1152
1153 auxFunctionRvaArray = list()
1154
1155 numberOfNames = iet.numberOfNames.value
1156 addressOfNames = iet.addressOfNames.value
1157 addressOfNameOrdinals = iet.addressOfNameOrdinals.value
1158 addressOfFunctions = iet.addressOfFunctions.value
1159
1160
1161 for i in xrange(iet.numberOfFunctions.value):
1162 auxFunctionRvaArray.append(self.getDwordAtRva(addressOfFunctions).value)
1163 addressOfFunctions += datatypes.DWORD().sizeof()
1164
1165 for i in xrange(numberOfNames):
1166
1167 nameRva = self.getDwordAtRva(addressOfNames).value
1168 nameOrdinal = self.getWordAtRva(addressOfNameOrdinals).value
1169 exportName = self.readStringAtRva(nameRva).value
1170
1171 entry = directories.ExportTableEntry()
1172
1173 ordinal = nameOrdinal + iet.base.value
1174
1175 entry.ordinal.value = ordinal
1176
1177 entry.nameOrdinal.vaue = nameOrdinal
1178 entry.nameRva.value = nameRva
1179 entry.name.value = exportName
1180 entry.functionRva.value = auxFunctionRvaArray[nameOrdinal]
1181
1182 iet.exportTable.append(entry)
1183
1184 addressOfNames += datatypes.DWORD().sizeof()
1185 addressOfNameOrdinals += datatypes.WORD().sizeof()
1186
1187
1188
1189
1190 for i in xrange(iet.numberOfFunctions.value):
1191
1192 if auxFunctionRvaArray[i] != iet.exportTable[i].functionRva.value:
1193 entry = directories.ExportTableEntry()
1194
1195 entry.functionRva.value = auxFunctionRvaArray[i]
1196 entry.ordinal.value = iet.base.value + i
1197
1198 iet.exportTable.append(entry)
1199
1200
1201 sorted(iet.exportTable, key=lambda entry:entry.ordinal)
1202 return iet
1203
1205 """
1206 Parses the C{IMAGE_DEBUG_DIRECTORY} directory.
1207 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680307(v=vs.85).aspx}
1208
1209 @type rva: int
1210 @param rva: The RVA where the C{IMAGE_DEBUG_DIRECTORY} directory starts.
1211
1212 @type size: int
1213 @param size: The size of the C{IMAGE_DEBUG_DIRECTORY} directory.
1214
1215 @type magic: int
1216 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1217
1218 @rtype: L{ImageDebugDirectory}
1219 @return: A new L{ImageDebugDirectory} object.
1220 """
1221 debugDirData = self.getDataAtRva(rva, size)
1222 numberOfEntries = size / consts.SIZEOF_IMAGE_DEBUG_ENTRY32
1223 rd = utils.ReadData(debugDirData)
1224 return directories.ImageDebugDirectories.parse(rd, numberOfEntries)
1225
1227 """
1228 Parses the C{IMAGE_IMPORT_DIRECTORY} directory.
1229
1230 @type rva: int
1231 @param rva: The RVA where the C{IMAGE_IMPORT_DIRECTORY} directory starts.
1232
1233 @type size: int
1234 @param size: The size of the C{IMAGE_IMPORT_DIRECTORY} directory.
1235
1236 @type magic: int
1237 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1238
1239 @rtype: L{ImageImportDescriptor}
1240 @return: A new L{ImageImportDescriptor} object.
1241
1242 @raise InvalidParameterException: If wrong magic was specified.
1243 """
1244
1245 importsDirData = self.getDataAtRva(rva, size)
1246
1247 numberOfEntries = size / consts.SIZEOF_IMAGE_IMPORT_ENTRY32
1248 rd = utils.ReadData(importsDirData)
1249
1250
1251
1252
1253 rdAux = utils.ReadData(importsDirData)
1254 count = 0
1255 entry = rdAux.read(consts.SIZEOF_IMAGE_IMPORT_ENTRY32)
1256 while rdAux.offset < len(rdAux.data) and not utils.allZero(entry):
1257 try:
1258 entry = rdAux.read(consts.SIZEOF_IMAGE_IMPORT_ENTRY32)
1259 count += 1
1260 except excep.DataLengthException:
1261 if self._verbose:
1262 print "[!] Warning: DataLengthException detected!."
1263
1264 if numberOfEntries - 1 > count:
1265 numberOfEntries = count + 1
1266
1267 iid = directories.ImageImportDescriptor.parse(rd, numberOfEntries)
1268 iidLength = len(iid)
1269
1270 peIsBounded = self.isPeBounded()
1271
1272 if magic == consts.PE64:
1273 ORDINAL_FLAG = consts.IMAGE_ORDINAL_FLAG64
1274 ADDRESS_MASK = consts.ADDRESS_MASK64
1275 elif magic == consts.PE32:
1276 ORDINAL_FLAG = consts.IMAGE_ORDINAL_FLAG
1277 ADDRESS_MASK = consts.ADDRESS_MASK32
1278 else:
1279 raise InvalidParameterException("magic value %d is not PE64 nor PE32." % magic)
1280
1281 for i in range(iidLength -1):
1282 if iid[i].originalFirstThunk.value != 0:
1283 iltRva = iid[i].originalFirstThunk.value
1284 iatRva = iid[i].firstThunk.value
1285
1286 if magic == consts.PE64:
1287 entry = self.getQwordAtRva(iltRva).value
1288 elif magic == consts.PE32:
1289 entry = self.getDwordAtRva(iltRva).value
1290
1291 while entry != 0:
1292
1293 if magic == consts.PE64:
1294 iatEntry = directories.ImportAddressTableEntry64()
1295 elif magic == consts.PE32:
1296 iatEntry = directories.ImportAddressTableEntry()
1297
1298 iatEntry.originalFirstThunk.value = entry
1299
1300 if iatEntry.originalFirstThunk.value & ORDINAL_FLAG:
1301 iatEntry.hint.value = None
1302 iatEntry.name.value = iatEntry.originalFirstThunk.value & ADDRESS_MASK
1303 else:
1304 iatEntry.hint.value = self.getWordAtRva(iatEntry.originalFirstThunk.value).value
1305 iatEntry.name.value = self.readStringAtRva(iatEntry.originalFirstThunk.value + 2).value
1306
1307 if magic == consts.PE64:
1308 iatEntry.firstThunk.value = self.getQwordAtRva(iatRva).value
1309 iltRva += 8
1310 iatRva += 8
1311 entry = self.getQwordAtRva(iltRva).value
1312 elif magic == consts.PE32:
1313 iatEntry.firstThunk.value = self.getDwordAtRva(iatRva).value
1314 iltRva += 4
1315 iatRva += 4
1316 entry = self.getDwordAtRva(iltRva).value
1317
1318 iid[i].iat.append(iatEntry)
1319
1320 else:
1321 iatRva = iid[i].firstThunk.value
1322
1323 if magic == consts.PE64:
1324 entry = self.getQwordAtRva(iatRva).value
1325 elif magic == consts.PE32:
1326 entry = self.getDwordAtRva(iatRva).value
1327
1328 while entry != 0:
1329
1330 if magic == consts.PE64:
1331 iatEntry = directories.ImportAddressTableEntry64()
1332 elif magic == consts.PE32:
1333 iatEntry = directories.ImportAddressTableEntry()
1334
1335 iatEntry.firstThunk.value = entry
1336 iatEntry.originalFirstThunk.value = 0
1337
1338 if not peIsBounded:
1339 ft = iatEntry.firstThunk.value
1340
1341 if ft & ORDINAL_FLAG:
1342 iatEntry.hint.value = None
1343 iatEntry.name.value = ft & ADDRESS_MASK
1344 else:
1345 iatEntry.hint.value = self.getWordAtRva(ft).value
1346 iatEntry.name.value = self.readStringAtRva(ft + 2).value
1347 else:
1348 iatEntry.hint.value = None
1349 iatEntry.name.value = None
1350
1351 if magic == consts.PE64:
1352 iatRva += 8
1353 entry = self.getQwordAtRva(iatRva).value
1354 elif magic == consts.PE32:
1355 iatRva += 4
1356 entry = self.getDwordAtRva(iatRva).value
1357
1358 iid[i].iat.append(iatEntry)
1359
1360 iid[i].metaData.moduleName.value = self.readStringAtRva(iid[i].name.value).value
1361 iid[i].metaData.numberOfImports.value = len(iid[i].iat)
1362 return iid
1363
1365 """
1366 Parses the NET directory.
1367 @see: U{http://www.ntcore.com/files/dotnetformat.htm}
1368
1369 @type rva: int
1370 @param rva: The RVA where the NET directory starts.
1371
1372 @type size: int
1373 @param size: The size of the NET directory.
1374
1375 @type magic: int
1376 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1377
1378 @rtype: L{NETDirectory}
1379 @return: A new L{NETDirectory} object.
1380 """
1381 if not rva or not size:
1382 return None
1383
1384
1385 netDirectoryClass = directories.NETDirectory()
1386
1387
1388 netDir = directories.NetDirectory.parse(utils.ReadData(self.getDataAtRva(rva, size)))
1389
1390 netDirectoryClass.directory = netDir
1391
1392
1393 mdhRva = netDir.metaData.rva.value
1394 mdhSize = netDir.metaData.size.value
1395
1396
1397 rd = utils.ReadData(self.getDataAtRva(mdhRva, mdhSize))
1398
1399
1400 netDirectoryClass.netMetaDataHeader = directories.NetMetaDataHeader.parse(rd)
1401
1402
1403 numberOfStreams = netDirectoryClass.netMetaDataHeader.numberOfStreams.value
1404 netDirectoryClass.netMetaDataStreams = directories.NetMetaDataStreams.parse(rd, numberOfStreams)
1405
1406 for i in range(numberOfStreams):
1407 stream = netDirectoryClass.netMetaDataStreams[i]
1408 name = stream.name.value
1409 rd.setOffset(stream.offset.value)
1410 rd2 = utils.ReadData(rd.read(stream.size.value))
1411 stream.info = []
1412 if name == "#~" or i == 0:
1413 stream.info = rd2
1414 elif name == "#Strings" or i == 1:
1415 while len(rd2) > 0:
1416 offset = rd2.tell()
1417 stream.info.append({ offset: rd2.readDotNetString() })
1418 elif name == "#US" or i == 2:
1419 while len(rd2) > 0:
1420 offset = rd2.tell()
1421 stream.info.append({ offset: rd2.readDotNetUnicodeString() })
1422 elif name == "#GUID" or i == 3:
1423 while len(rd2) > 0:
1424 offset = rd2.tell()
1425 stream.info.append({ offset: rd2.readDotNetGuid() })
1426 elif name == "#Blob" or i == 4:
1427 while len(rd2) > 0:
1428 offset = rd2.tell()
1429 stream.info.append({ offset: rd2.readDotNetBlob() })
1430
1431 for i in range(numberOfStreams):
1432 stream = netDirectoryClass.netMetaDataStreams[i]
1433 name = stream.name.value
1434 if name == "#~" or i == 0:
1435 stream.info = directories.NetMetaDataTables.parse(stream.info, netDirectoryClass.netMetaDataStreams)
1436
1437
1438
1439 resRva = netDir.resources.rva.value
1440 resSize = netDir.resources.size.value
1441
1442
1443 rd = utils.ReadData(self.getDataAtRva(resRva, resSize))
1444
1445 resources = []
1446
1447 for i in netDirectoryClass.netMetaDataStreams[0].info.tables["ManifestResource"]:
1448 offset = i["offset"]
1449 rd.setOffset(offset)
1450 size = rd.readDword()
1451 data = rd.read(size)
1452 if data[:4] == "\xce\xca\xef\xbe":
1453 data = directories.NetResources.parse(utils.ReadData(data))
1454 resources.append({ "name": i["name"], "offset": offset + 4, "size": size, "data": data })
1455
1456 netDirectoryClass.directory.resources.info = resources
1457
1458 return netDirectoryClass
1459
1461 """
1462 Get MD5 hash from PE file.
1463
1464 @rtype: str
1465 @return: The MD5 hash from the L{PE} instance.
1466 """
1467 return hashlib.md5(str(self)).hexdigest()
1468
1470 """
1471 Get SHA1 hash from PE file.
1472
1473 @rtype: str
1474 @return: The SHA1 hash from the L{PE} instance.
1475 """
1476 return hashlib.sha1(str(self)).hexdigest()
1477
1479 """
1480 Get SHA256 hash from PE file.
1481
1482 @rtype: str
1483 @return: The SHA256 hash from the L{PE} instance.
1484 """
1485 return hashlib.sha256(str(self)).hexdigest()
1486
1488 """
1489 Get SHA512 hash from PE file.
1490
1491 @rtype: str
1492 @return: The SHA512 hash from the L{PE} instance.
1493 """
1494 return hashlib.sha512(str(self)).hexdigest()
1495
1497 """
1498 Get CRC32 checksum from PE file.
1499
1500 @rtype: int
1501 @return: The CRD32 checksum from the L{PE} instance.
1502 """
1503 return binascii.crc32(str(self)) & 0xffffffff
1504
1506 retval = False
1507 if not self._fastLoad:
1508 import_directory = self.ntHeaders.optionalHeader.dataDirectory[consts.IMPORT_DIRECTORY]
1509 if import_directory:
1510 for iid_entry in import_directory.info:
1511 for entry in iid_entry.iat:
1512 if entry.name.value == funcName:
1513 retval = True
1514 break
1515 else:
1516 print "WARNING: IMPORT_DIRECTORY not found on PE!"
1517 else:
1518 print "WARNING: fastLoad parameter was used to load the PE. Data directories are not parsed when using this options. Please, use fastLoad = False."
1519 return retval
1520
1536
1538 dnh = self.ntHeaders.optionalHeader.dataDirectory[14].info
1539 if not dnh: return None
1540 dnh = dnh.directory
1541
1542 token = self.getNetMetadataToken(dnh.entryPointToken.value)
1543
1544 if dnh.flags.value & consts.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT:
1545
1546 offset = self.getOffsetFromRva(token)
1547 else:
1548
1549 offset = self.getOffsetFromRva(token["rva"])
1550 rd = utils.ReadData(self.getDataAtOffset(offset, 12))
1551 flags = rd.readByte()
1552 if flags & 0x3 == consts.CORILMETHOD_TINYFORMAT:
1553
1554 codeSize = flags >> 2 & 0x3f
1555 flags = flags & 0x3
1556 headerSize = 1
1557 maxStack = 8
1558 localVarSigTok = 0
1559 elif flags & 0x3 == consts.CORILMETHOD_FATFORMAT:
1560
1561 flags |= rd.readByte() << 8
1562 headerSize = 4 * (flags >> 12 & 0xf)
1563 flags = flags & 0xfff
1564 maxStack = rd.readWord()
1565 codeSize = rd.readDword()
1566 localVarSigTok = rd.readDword()
1567 else:
1568 raise Exception("Unknown CLR method header.")
1569 offset += headerSize
1570
1571 return offset
1572
1574 """DosHeader object."""
1576 """
1577 Class representation of the C{IMAGE_DOS_HEADER} structure.
1578 @see: U{http://msdn.microsoft.com/en-us/magazine/cc301805.aspx}
1579
1580 @type shouldPack: bool
1581 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1582 """
1583 baseclasses.BaseStructClass.__init__(self, shouldPack)
1584
1585 self.e_magic = datatypes.WORD(consts.MZ_SIGNATURE)
1586 self.e_cblp = datatypes.WORD(0)
1587 self.e_cp = datatypes.WORD(0)
1588 self.e_crlc = datatypes.WORD(0)
1589 self.e_cparhdr = datatypes.WORD(0)
1590 self.e_minalloc = datatypes.WORD(0)
1591 self.e_maxalloc = datatypes.WORD(0)
1592 self.e_ss = datatypes.WORD(0)
1593 self.e_sp = datatypes.WORD(0)
1594 self.e_csum = datatypes.WORD(0)
1595 self.e_ip = datatypes.WORD(0)
1596 self.e_cs = datatypes.WORD(0)
1597 self.e_lfarlc = datatypes.WORD(0)
1598 self.e_ovno = datatypes.WORD(0)
1599
1600 self.e_res = datatypes.Array(datatypes.TYPE_WORD)
1601 self.e_res.extend([datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0)])
1602
1603 self.e_oemid = datatypes.WORD(0)
1604 self.e_oeminfo = datatypes.WORD(0)
1605
1606 self.e_res2 = datatypes.Array(datatypes.TYPE_WORD)
1607 self.e_res2.extend([datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0),\
1608 datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0),\
1609 datatypes.WORD(0), datatypes.WORD(0)])
1610
1611 self.e_lfanew = datatypes.DWORD(0xf0)
1612
1613 self._attrsList = ["e_magic","e_cblp","e_cp","e_crlc","e_cparhdr","e_minalloc","e_maxalloc","e_ss","e_sp","e_csum",\
1614 "e_ip","e_cs","e_lfarlc","e_ovno","e_res","e_oemid","e_oeminfo","e_res2","e_lfanew"]
1615
1616 @staticmethod
1618 """
1619 Returns a new L{DosHeader} object.
1620
1621 @type readDataInstance: L{ReadData}
1622 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{DosHeader} object.
1623
1624 @rtype: L{DosHeader}
1625 @return: A new L{DosHeader} object.
1626 """
1627 dosHdr = DosHeader()
1628
1629 dosHdr.e_magic.value = readDataInstance.readWord()
1630 dosHdr.e_cblp.value = readDataInstance.readWord()
1631 dosHdr.e_cp.value = readDataInstance.readWord()
1632 dosHdr.e_crlc.value = readDataInstance.readWord()
1633 dosHdr.e_cparhdr.value = readDataInstance.readWord()
1634 dosHdr.e_minalloc.value = readDataInstance.readWord()
1635 dosHdr.e_maxalloc.value = readDataInstance.readWord()
1636 dosHdr.e_ss.value = readDataInstance.readWord()
1637 dosHdr.e_sp.value = readDataInstance.readWord()
1638 dosHdr.e_csum.value = readDataInstance.readWord()
1639 dosHdr.e_ip.value = readDataInstance.readWord()
1640 dosHdr.e_cs.value = readDataInstance.readWord()
1641 dosHdr.e_lfarlc.value = readDataInstance.readWord()
1642 dosHdr.e_ovno.value = readDataInstance.readWord()
1643
1644 dosHdr.e_res = datatypes.Array(datatypes.TYPE_WORD)
1645 for i in range(4):
1646 dosHdr.e_res.append(datatypes.WORD(readDataInstance.readWord()))
1647
1648 dosHdr.e_oemid.value = readDataInstance.readWord()
1649 dosHdr.e_oeminfo.value = readDataInstance.readWord()
1650
1651 dosHdr.e_res2 = datatypes.Array(datatypes.TYPE_WORD)
1652 for i in range (10):
1653 dosHdr.e_res2.append(datatypes.WORD(readDataInstance.readWord()))
1654
1655 dosHdr.e_lfanew.value = readDataInstance.readDword()
1656 return dosHdr
1657
1661
1663 """NtHeaders object."""
1665 """
1666 Class representation of the C{IMAGE_NT_HEADERS} structure.
1667 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680336%28v=vs.85%29.aspx}
1668
1669 @type shouldPack: bool
1670 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1671 """
1672 baseclasses.BaseStructClass.__init__(self, shouldPack)
1673
1674 self.signature = datatypes.DWORD(consts.PE_SIGNATURE)
1675 self.fileHeader = FileHeader()
1676 self.optionalHeader = OptionalHeader()
1677
1679 return str(self.signature) + str(self.fileHeader) + str(self.optionalHeader)
1680
1681 @staticmethod
1683 """
1684 Returns a new L{NtHeaders} object.
1685
1686 @type readDataInstance: L{ReadData}
1687 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{NtHeaders} object.
1688
1689 @rtype: L{NtHeaders}
1690 @return: A new L{NtHeaders} object.
1691 """
1692 nt = NtHeaders()
1693 nt.signature.value = readDataInstance.readDword()
1694 nt.fileHeader = FileHeader.parse(readDataInstance)
1695 nt.optionalHeader = OptionalHeader.parse(readDataInstance)
1696 return nt
1697
1701
1703 """FileHeader object."""
1705 """
1706 Class representation of the C{IMAGE_FILE_HEADER} structure.
1707 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680313%28v=vs.85%29.aspx}
1708
1709 @type shouldPack: bool
1710 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1711 """
1712 baseclasses.BaseStructClass.__init__(self, shouldPack = True)
1713
1714 self.machine = datatypes.WORD(consts.INTEL386)
1715 self.numberOfSections = datatypes.WORD(1)
1716 self.timeDateStamp = datatypes.DWORD(0)
1717 self.pointerToSymbolTable = datatypes.DWORD(0)
1718 self.numberOfSymbols = datatypes.DWORD(0)
1719 self.sizeOfOptionalHeader = datatypes.WORD(0xe0)
1720 self.characteristics = datatypes.WORD(consts.COMMON_CHARACTERISTICS)
1721
1722 self._attrsList = ["machine","numberOfSections","timeDateStamp","pointerToSymbolTable","numberOfSymbols",\
1723 "sizeOfOptionalHeader","characteristics"]
1724
1725 @staticmethod
1727 """
1728 Returns a new L{FileHeader} object.
1729
1730 @type readDataInstance: L{ReadData}
1731 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{FileHeader} object.
1732
1733 @rtype: L{FileHeader}
1734 @return: A new L{ReadData} object.
1735 """
1736 fh = FileHeader()
1737 fh.machine.value = readDataInstance.readWord()
1738 fh.numberOfSections.value = readDataInstance.readWord()
1739 fh.timeDateStamp.value = readDataInstance.readDword()
1740 fh.pointerToSymbolTable.value = readDataInstance.readDword()
1741 fh.numberOfSymbols.value = readDataInstance.readDword()
1742 fh.sizeOfOptionalHeader.value = readDataInstance.readWord()
1743 fh.characteristics.value = readDataInstance.readWord()
1744 return fh
1745
1749
1751 """OptionalHeader object."""
1753 """
1754 Class representation of the C{IMAGE_OPTIONAL_HEADER} structure.
1755 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680339%28v=vs.85%29.aspx}
1756
1757 @type shouldPack: bool
1758 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1759 """
1760 baseclasses.BaseStructClass.__init__(self, shouldPack)
1761
1762 self.magic = datatypes.WORD(consts.PE32)
1763 self.majorLinkerVersion = datatypes.BYTE(2)
1764 self.minorLinkerVersion = datatypes.BYTE(0x19)
1765 self.sizeOfCode = datatypes.DWORD(0x1000)
1766 self.sizeOfInitializedData = datatypes.DWORD(0)
1767 self.sizeOfUninitializedData = datatypes.DWORD(0)
1768 self.addressOfEntryPoint = datatypes.DWORD(0x1000)
1769 self.baseOfCode = datatypes.DWORD(0x1000)
1770 self.baseOfData = datatypes.DWORD(0x1000)
1771 self.imageBase = datatypes.DWORD(0x400000)
1772 self.sectionAlignment = datatypes.DWORD(0x1000)
1773 self.fileAlignment = datatypes.DWORD(0x200)
1774 self.majorOperatingSystemVersion = datatypes.WORD(5)
1775 self.minorOperatingSystemVersion = datatypes.WORD(0)
1776 self.majorImageVersion = datatypes.WORD(6)
1777 self.minorImageVersion = datatypes.WORD(0)
1778 self.majorSubsystemVersion = datatypes.WORD(5)
1779 self.minorSubsystemVersion = datatypes.WORD(0)
1780 self.win32VersionValue = datatypes.DWORD(0)
1781 self.sizeOfImage = datatypes.DWORD(0x2000)
1782 self.sizeOfHeaders = datatypes.DWORD(0x400)
1783 self.checksum = datatypes.DWORD(0)
1784 self.subsystem = datatypes.WORD(consts.WINDOWSGUI)
1785 self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE)
1786 self.sizeOfStackReserve = datatypes.DWORD(0x00100000)
1787 self.sizeOfStackCommit = datatypes.DWORD(0x00004000)
1788 self.sizeOfHeapReserve = datatypes.DWORD(00100000)
1789 self.sizeOfHeapCommit = datatypes.DWORD(0x1000)
1790 self.loaderFlags = datatypes.DWORD(0)
1791 self.numberOfRvaAndSizes = datatypes.DWORD(0x10)
1792 self.dataDirectory = datadirs.DataDirectory()
1793
1794 self._attrsList = ["magic","majorLinkerVersion","minorLinkerVersion","sizeOfCode","sizeOfInitializedData",\
1795 "sizeOfUninitializedData","addressOfEntryPoint","baseOfCode","baseOfData","imageBase","sectionAlignment",\
1796 "fileAlignment","majorOperatingSystemVersion","minorOperatingSystemVersion","majorImageVersion",\
1797 "minorImageVersion","majorSubsystemVersion","minorSubsystemVersion","win32VersionValue","sizeOfImage",\
1798 "sizeOfHeaders","checksum","subsystem","dllCharacteristics","sizeOfStackReserve","sizeOfStackCommit",\
1799 "sizeOfHeapReserve","sizeOfHeapCommit","loaderFlags","numberOfRvaAndSizes","dataDirectory"]
1800
1801 @staticmethod
1803 """
1804 Returns a new L{OptionalHeader} object.
1805
1806 @type readDataInstance: L{ReadData}
1807 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{OptionalHeader} object.
1808
1809 @rtype: L{OptionalHeader}
1810 @return: A new L{OptionalHeader} object.
1811 """
1812 oh = OptionalHeader()
1813
1814 oh.magic.value = readDataInstance.readWord()
1815 oh.majorLinkerVersion.value = readDataInstance.readByte()
1816 oh.minorLinkerVersion.value = readDataInstance.readByte()
1817 oh.sizeOfCode.value = readDataInstance.readDword()
1818 oh.sizeOfInitializedData.value = readDataInstance.readDword()
1819 oh.sizeOfUninitializedData.value = readDataInstance.readDword()
1820 oh.addressOfEntryPoint.value = readDataInstance.readDword()
1821 oh.baseOfCode.value = readDataInstance.readDword()
1822 oh.baseOfData.value = readDataInstance.readDword()
1823 oh.imageBase.value = readDataInstance.readDword()
1824 oh.sectionAlignment.value = readDataInstance.readDword()
1825 oh.fileAlignment.value = readDataInstance.readDword()
1826 oh.majorOperatingSystemVersion.value = readDataInstance.readWord()
1827 oh.minorOperatingSystemVersion.value = readDataInstance.readWord()
1828 oh.majorImageVersion.value = readDataInstance.readWord()
1829 oh.minorImageVersion.value = readDataInstance.readWord()
1830 oh.majorSubsystemVersion.value = readDataInstance.readWord()
1831 oh.minorSubsystemVersion.value = readDataInstance.readWord()
1832 oh.win32VersionValue.value = readDataInstance.readDword()
1833 oh.sizeOfImage.value = readDataInstance.readDword()
1834 oh.sizeOfHeaders.value = readDataInstance.readDword()
1835 oh.checksum.value = readDataInstance.readDword()
1836 oh.subsystem.value = readDataInstance.readWord()
1837 oh.dllCharacteristics.value = readDataInstance.readWord()
1838 oh.sizeOfStackReserve.value = readDataInstance.readDword()
1839 oh.sizeOfStackCommit.value = readDataInstance.readDword()
1840 oh.sizeOfHeapReserve.value = readDataInstance.readDword()
1841 oh.sizeOfHeapCommit.value = readDataInstance.readDword()
1842 oh.loaderFlags.value = readDataInstance.readDword()
1843 oh.numberOfRvaAndSizes.value = readDataInstance.readDword()
1844
1845 dirs = readDataInstance.read(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 8)
1846
1847 oh.dataDirectory = datadirs.DataDirectory.parse(utils.ReadData(dirs))
1848
1849 return oh
1850
1854
1888 """OptionalHeader64 object."""
1890 """
1891 Class representation of the C{IMAGE_OPTIONAL_HEADER64} structure.
1892 @see: Remarks in U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms680339%28v=vs.85%29.aspx}
1893
1894 @type shouldPack: bool
1895 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1896 """
1897 baseclasses.BaseStructClass.__init__(self, shouldPack)
1898
1899 self.magic = datatypes.WORD(consts.PE32)
1900 self.majorLinkerVersion = datatypes.BYTE(2)
1901 self.minorLinkerVersion = datatypes.BYTE(0x19)
1902 self.sizeOfCode = datatypes.DWORD(0x1000)
1903 self.sizeOfInitializedData = datatypes.DWORD(0)
1904 self.sizeOfUninitializedData = datatypes.DWORD(0)
1905 self.addressOfEntryPoint = datatypes.DWORD(0x1000)
1906 self.baseOfCode = datatypes.DWORD(0x1000)
1907 self.imageBase = datatypes.QWORD(0x400000)
1908 self.sectionAlignment = datatypes.DWORD(0x1000)
1909 self.fileAlignment = datatypes.DWORD(0x200)
1910 self.majorOperatingSystemVersion = datatypes.WORD(5)
1911 self.minorOperatingSystemVersion = datatypes.WORD(0)
1912 self.majorImageVersion = datatypes.WORD(6)
1913 self.minorImageVersion = datatypes.WORD(0)
1914 self.majorSubsystemVersion = datatypes.WORD(5)
1915 self.minorSubsystemVersion = datatypes.WORD(0)
1916 self.win32VersionValue = datatypes.DWORD(0)
1917 self.sizeOfImage = datatypes.DWORD(0x2000)
1918 self.sizeOfHeaders = datatypes.DWORD(0x400)
1919 self.checksum = datatypes.DWORD(0)
1920 self.subsystem = datatypes.WORD(consts.WINDOWSGUI)
1921 self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE)
1922 self.sizeOfStackReserve = datatypes.QWORD(0x00100000)
1923 self.sizeOfStackCommit = datatypes.QWORD(0x00004000)
1924 self.sizeOfHeapReserve = datatypes.QWORD(00100000)
1925 self.sizeOfHeapCommit = datatypes.QWORD(0x1000)
1926 self.loaderFlags = datatypes.DWORD(0)
1927 self.numberOfRvaAndSizes = datatypes.DWORD(0x10)
1928 self.dataDirectory = datadirs.DataDirectory()
1929
1930 self._attrsList = ["magic","majorLinkerVersion","minorLinkerVersion","sizeOfCode","sizeOfInitializedData",\
1931 "sizeOfUninitializedData","addressOfEntryPoint","baseOfCode", "imageBase","sectionAlignment",\
1932 "fileAlignment","majorOperatingSystemVersion","minorOperatingSystemVersion","majorImageVersion",\
1933 "minorImageVersion","majorSubsystemVersion","minorSubsystemVersion","win32VersionValue","sizeOfImage",\
1934 "sizeOfHeaders","checksum","subsystem","dllCharacteristics","sizeOfStackReserve","sizeOfStackCommit",\
1935 "sizeOfHeapReserve","sizeOfHeapCommit","loaderFlags","numberOfRvaAndSizes","dataDirectory"]
1936
1937 @staticmethod
1939 """
1940 Returns a new L{OptionalHeader64} object.
1941
1942 @type readDataInstance: L{ReadData}
1943 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{OptionalHeader64} object.
1944
1945 @rtype: L{OptionalHeader64}
1946 @return: A new L{OptionalHeader64} object.
1947 """
1948 oh = OptionalHeader64()
1949
1950 oh.magic.value = readDataInstance.readWord()
1951 oh.majorLinkerVersion.value = readDataInstance.readByte()
1952 oh.minorLinkerVersion.value = readDataInstance.readByte()
1953 oh.sizeOfCode.value = readDataInstance.readDword()
1954 oh.sizeOfInitializedData.value = readDataInstance.readDword()
1955 oh.sizeOfUninitializedData.value = readDataInstance.readDword()
1956 oh.addressOfEntryPoint.value = readDataInstance.readDword()
1957 oh.baseOfCode.value = readDataInstance.readDword()
1958 oh.imageBase.value = readDataInstance.readQword()
1959 oh.sectionAlignment.value = readDataInstance.readDword()
1960 oh.fileAlignment.value = readDataInstance.readDword()
1961 oh.majorOperatingSystemVersion.value = readDataInstance.readWord()
1962 oh.minorOperatingSystemVersion.value = readDataInstance.readWord()
1963 oh.majorImageVersion.value = readDataInstance.readWord()
1964 oh.minorImageVersion.value = readDataInstance.readWord()
1965 oh.majorSubsystemVersion.value = readDataInstance.readWord()
1966 oh.minorSubsystemVersion.value = readDataInstance.readWord()
1967 oh.win32VersionValue.value = readDataInstance.readDword()
1968 oh.sizeOfImage.value = readDataInstance.readDword()
1969 oh.sizeOfHeaders.value = readDataInstance.readDword()
1970 oh.checksum.value = readDataInstance.readDword()
1971 oh.subsystem.value = readDataInstance.readWord()
1972 oh.dllCharacteristics.value = readDataInstance.readWord()
1973 oh.sizeOfStackReserve.value = readDataInstance.readQword()
1974 oh.sizeOfStackCommit.value = readDataInstance.readQword()
1975 oh.sizeOfHeapReserve.value = readDataInstance.readQword()
1976 oh.sizeOfHeapCommit.value = readDataInstance.readQword()
1977 oh.loaderFlags.value = readDataInstance.readDword()
1978 oh.numberOfRvaAndSizes.value = readDataInstance.readDword()
1979
1980 dirs = readDataInstance.read(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 8)
1981
1982 oh.dataDirectory = datadirs.DataDirectory.parse(utils.ReadData(dirs))
1983
1984 return oh
1985
1989
1991 """SectionHeader object."""
1993 """
1994 Class representation of the C{IMAGE_SECTION_HEADER} structure.
1995 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms680341%28v=vs.85%29.aspx}
1996
1997 @type shouldPack: bool
1998 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1999 """
2000 baseclasses.BaseStructClass.__init__(self, shouldPack)
2001
2002 self.name = datatypes.String('.travest')
2003 self.misc = datatypes.DWORD(0x1000)
2004 self.virtualAddress = datatypes.DWORD(0x1000)
2005 self.sizeOfRawData = datatypes.DWORD(0x200)
2006 self.pointerToRawData = datatypes.DWORD(0x400)
2007 self.pointerToRelocations = datatypes.DWORD(0)
2008 self.pointerToLineNumbers = datatypes.DWORD(0)
2009 self.numberOfRelocations = datatypes.WORD(0)
2010 self.numberOfLinesNumbers = datatypes.WORD(0)
2011 self.characteristics = datatypes.DWORD(0x60000000)
2012
2013 self._attrsList = ["name","misc","virtualAddress","sizeOfRawData","pointerToRawData","pointerToRelocations",\
2014 "pointerToLineNumbers","numberOfRelocations","numberOfLinesNumbers","characteristics"]
2015
2016 @staticmethod
2018 """
2019 Returns a new L{SectionHeader} object.
2020
2021 @type readDataInstance: L{ReadData}
2022 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{SectionHeader} object.
2023
2024 @rtype: L{SectionHeader}
2025 @return: A new L{SectionHeader} object.
2026 """
2027 sh = SectionHeader()
2028 sh.name.value = readDataInstance.read(8)
2029 sh.misc.value = readDataInstance.readDword()
2030 sh.virtualAddress.value = readDataInstance.readDword()
2031 sh.sizeOfRawData.value = readDataInstance.readDword()
2032 sh.pointerToRawData.value = readDataInstance.readDword()
2033 sh.pointerToRelocations.value = readDataInstance.readDword()
2034 sh.pointerToLineNumbers.value = readDataInstance.readDword()
2035 sh.numberOfRelocations.value = readDataInstance.readWord()
2036 sh.numberOfLinesNumbers.value = readDataInstance.readWord()
2037 sh.characteristics.value = readDataInstance.readDword()
2038 return sh
2039
2043
2045 """SectionHeaders object."""
2047 """
2048 Array of L{SectionHeader} objects.
2049
2050 @type shouldPack: bool
2051 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
2052
2053 @type numberOfSectionHeaders: int
2054 @param numberOfSectionHeaders: (Optional) The number of desired section headers. By default, this parameter is set to 1.
2055 """
2056 list.__init__(self)
2057
2058 self.shouldPack = shouldPack
2059
2060 if numberOfSectionHeaders:
2061 for i in range(numberOfSectionHeaders):
2062 sh = SectionHeader()
2063 self.append(sh)
2064
2066 return "".join([str(x) for x in self if x.shouldPack])
2067
2068 @staticmethod
2070 """
2071 Returns a new L{SectionHeaders} object.
2072
2073 @type readDataInstance: L{ReadData}
2074 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{SectionHeaders} object.
2075
2076 @type numberOfSectionHeaders: int
2077 @param numberOfSectionHeaders: The number of L{SectionHeader} objects in the L{SectionHeaders} instance.
2078 """
2079 sHdrs = SectionHeaders(numberOfSectionHeaders = 0)
2080
2081 for i in range(numberOfSectionHeaders):
2082 sh = SectionHeader()
2083
2084 sh.name.value = readDataInstance.read(8)
2085 sh.misc.value = readDataInstance.readDword()
2086 sh.virtualAddress.value = readDataInstance.readDword()
2087 sh.sizeOfRawData.value = readDataInstance.readDword()
2088 sh.pointerToRawData.value = readDataInstance.readDword()
2089 sh.pointerToRelocations.value = readDataInstance.readDword()
2090 sh.pointerToLineNumbers.value = readDataInstance.readDword()
2091 sh.numberOfRelocations.value = readDataInstance.readWord()
2092 sh.numberOfLinesNumbers.value = readDataInstance.readWord()
2093 sh.characteristics.value = readDataInstance.readDword()
2094
2095 sHdrs.append(sh)
2096
2097 return sHdrs
2098
2100 """Sections object."""
2101 - def __init__(self, sectionHeadersInstance = None):
2102 """
2103 Array with the data of each section present in the file.
2104
2105 @type sectionHeadersInstance: instance
2106 @param sectionHeadersInstance: (Optional) A L{SectionHeaders} instance to be parsed.
2107 """
2108 list.__init__(self)
2109
2110 if sectionHeadersInstance:
2111 for sh in sectionHeadersInstance:
2112 self.append("\xcc" * sh.sizeOfRawData.value)
2113
2115 return "".join([str(data) for data in self])
2116
2117 @staticmethod
2118 - def parse(readDataInstance, sectionHeadersInstance):
2119 """
2120 Returns a new L{Sections} object.
2121
2122 @type readDataInstance: L{ReadData}
2123 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{Sections} object.
2124
2125 @type sectionHeadersInstance: instance
2126 @param sectionHeadersInstance: The L{SectionHeaders} instance with the necessary to parse every section data.
2127
2128 @rtype: L{Sections}
2129 @return: A new L{Sections} object.
2130 """
2131 sData = Sections()
2132
2133 for sectionHdr in sectionHeadersInstance:
2134
2135 if sectionHdr.sizeOfRawData.value > len(readDataInstance.data):
2136 print "Warning: SizeOfRawData is larger than file."
2137
2138 if sectionHdr.pointerToRawData.value > len(readDataInstance.data):
2139 print "Warning: PointerToRawData points beyond the end of the file."
2140
2141 if sectionHdr.misc.value > 0x10000000:
2142 print "Warning: VirtualSize is extremely large > 256MiB."
2143
2144 if sectionHdr.virtualAddress.value > 0x10000000:
2145 print "Warning: VirtualAddress is beyond 0x10000000"
2146
2147
2148 if sectionHdr.pointerToRawData.value:
2149 sData.append(readDataInstance.read(sectionHdr.sizeOfRawData.value))
2150
2151 return sData
2152