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(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(str(self))
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 1, 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 RVA in the file, tries to determine the section this RVA belongs to.
394
395 @type rva: int
396 @param rva: RVA value.
397
398 @rtype: int
399 @return: An index, starting at 1, that represents the section the given RVA belongs to.
400 """
401
402 index = -1
403 if rva < self.sectionHeaders[0].virtualAddress.value:
404 return index
405
406 for i in range(len(self.sectionHeaders)):
407 fa = self.ntHeaders.optionalHeader.fileAlignment.value
408 prd = self.sectionHeaders[i].pointerToRawData.value
409 srd = self.sectionHeaders[i].sizeOfRawData.value
410 if len(str(self)) - self._adjustFileAlignment(prd, fa) < srd:
411 size = self.sectionHeaders[i].misc.value
412 else:
413 size = max(srd, self.sectionHeaders[i].misc.value)
414 if (self.sectionHeaders[i].virtualAddress.value <= rva) and rva < (self.sectionHeaders[i].virtualAddress.value + size):
415 index = i
416 break
417
418 return index
419
420 @staticmethod
422 """
423 Returns a default DOS stub.
424
425 @rtype: str
426 @return: A defaul DOS stub.
427 """
428 return "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A240000000000000037E338C97382569A7382569A7382569A6DD0D29A6982569A6DD0C39A6382569A6DD0D59A3A82569A54442D9A7482569A7382579A2582569A6DD0DC9A7282569A6DD0C29A7282569A6DD0C79A7282569A526963687382569A000000000000000000000000000000000000000000000000".decode("hex")
429
431 """
432 Returns the offset to last section header present in the PE file.
433
434 @rtype: int
435 @return: The offset where the end of the last section header resides in the PE file.
436 """
437 return len(str(self.dosHeader) + str(self.dosStub) + str(self.ntHeaders) + str(self.sectionHeaders))
438
440 """Parse all the directories in the PE file."""
441 self._parseDirectories(self.ntHeaders.optionalHeader.dataDirectory, self.PE_TYPE)
442
444 """
445 Populates the attributes of the L{PE} object.
446
447 @type readDataInstance: L{ReadData}
448 @param readDataInstance: A L{ReadData} instance with the data of a PE file.
449 """
450 self.dosHeader = DosHeader.parse(readDataInstance)
451
452 self.dosStub = readDataInstance.read(self.dosHeader.e_lfanew.value - readDataInstance.offset)
453 self.ntHeaders = NtHeaders.parse(readDataInstance)
454
455 if self.ntHeaders.optionalHeader.magic.value == consts.PE32:
456 self.PE_TYPE = consts.PE32
457 elif self.ntHeaders.optionalHeader.magic.value == consts.PE64:
458 self.PE_TYPE = consts.PE64
459 readDataInstance.setOffset(readDataInstance.tell() - OptionalHeader().sizeof())
460 self.ntHeaders.optionalHeader = OptionalHeader64.parse(readDataInstance)
461
462 self.sectionHeaders = SectionHeaders.parse(readDataInstance, self.ntHeaders.fileHeader.numberOfSections.value)
463
464
465
466 readDataInstance.setOffset(self.sectionHeaders[0].pointerToRawData.value)
467
468 self.sections = Sections.parse(readDataInstance, self.sectionHeaders)
469
470 self.overlay = self._getOverlay(readDataInstance, self.sectionHeaders)
471 self.signature = self._getSignature(readDataInstance, self.ntHeaders.optionalHeader.dataDirectory)
472
473 if not self._fastLoad:
474 self._parseDirectories(self.ntHeaders.optionalHeader.dataDirectory, self.PE_TYPE)
475
476 - def addSection(self, data, name =".pype32\x00", flags = 0x60000000):
477 """
478 Adds a new section to the existing L{PE} instance.
479
480 @type data: str
481 @param data: The data to be added in the new section.
482
483 @type name: str
484 @param name: (Optional) The name for the new section.
485
486 @type flags: int
487 @param flags: (Optional) The attributes for the new section.
488 """
489 fa = self.ntHeaders.optionalHeader.fileAlignment.value
490 sa = self.ntHeaders.optionalHeader.sectionAlignment.value
491
492 padding = "\xcc" * (fa - len(data))
493 sh = SectionHeader()
494
495 if len(self.sectionHeaders):
496
497 vaLastSection = self.sectionHeaders[-1].virtualAddress.value
498 sizeLastSection = self.sectionHeaders[-1].misc.value
499 pointerToRawDataLastSection = self.sectionHeaders[-1].pointerToRawData.value
500 sizeOfRawDataLastSection = self.sectionHeaders[-1].sizeOfRawData.value
501
502 sh.virtualAddress.value = self._adjustSectionAlignment(vaLastSection + sizeLastSection, fa, sa)
503 sh.pointerToRawData.value = self._adjustFileAlignment(pointerToRawDataLastSection + sizeOfRawDataLastSection, fa)
504
505 sh.misc.value = self._adjustSectionAlignment(len(data), fa, sa) or consts.DEFAULT_PAGE_SIZE
506 sh.sizeOfRawData.value = self._adjustFileAlignment(len(data), fa) or consts.DEFAULT_FILE_ALIGNMENT
507 sh.characteristics.value = flags
508 sh.name.value = name
509
510 self.sectionHeaders.append(sh)
511 self.sections.append(data + padding)
512
513 self.ntHeaders.fileHeader.numberOfSections.value += 1
514
516 """
517 Extends an existing section in the L{PE} instance.
518
519 @type sectionIndex: int
520 @param sectionIndex: The index for the section to be extended.
521
522 @type data: str
523 @param data: The data to include in the section.
524
525 @raise IndexError: If an invalid C{sectionIndex} was specified.
526 @raise SectionHeadersException: If there is not section to extend.
527 """
528
529 fa = self.ntHeaders.optionalHeader.fileAlignment.value
530 sa = self.ntHeaders.optionalHeader.sectionAlignment.value
531
532 if len(self.sectionHeaders):
533 if len(self.sectionHeaders) == sectionIndex:
534 try:
535
536 vzLastSection = self.sectionHeaders[-1].misc.value
537 rzLastSection = self.sectionHeaders[-1].sizeOfRawData.value
538
539 self.sectionHeaders[-1].misc.value = self._adjustSectionAlignment(vzLastSection + len(data), fa, sa)
540 self.sectionHeaders[-1].sizeOfRawData.value = self._adjustFileAlignment(rzLastSection + len(data), fa)
541
542 vz = self.sectionHeaders[-1].misc.value
543 rz = self.sectionHeaders[-1].sizeOfRawData.value
544
545 except IndexError:
546 raise IndexError("list index out of range.")
547
548 if vz < rz:
549 print "WARNING: VirtualSize (%x) is less than SizeOfRawData (%x)" % (vz, rz)
550
551 if len(data) % fa == 0:
552 self.sections[-1] += data
553 else:
554 self.sections[-1] += data + "\xcc" * (fa - len(data) % fa)
555
556 else:
557
558 try:
559
560 counter = sectionIndex - 1
561
562 vzCurrentSection = self.sectionHeaders[counter].misc.value
563 rzCurrentSection = self.sectionHeaders[counter].sizeOfRawData.value
564
565 self.sectionHeaders[counter].misc.value = self._adjustSectionAlignment(vzCurrentSection + len(data), fa, sa)
566 self.sectionHeaders[counter].sizeOfRawData.value = self._adjustFileAlignment(rzCurrentSection + len(data), fa)
567
568 if len(data) % fa == 0:
569 self.sections[counter] += data
570 else:
571 self.sections[counter] += data + "\xcc" * (fa - len(data) % fa)
572
573 counter += 1
574
575 while(counter != len(self.sectionHeaders)):
576 vzPreviousSection = self.sectionHeaders[counter - 1].misc.value
577 vaPreviousSection = self.sectionHeaders[counter - 1].virtualAddress.value
578 rzPreviousSection = self.sectionHeaders[counter - 1].sizeOfRawData.value
579 roPreviousSection = self.sectionHeaders[counter - 1].pointerToRawData.value
580
581
582 self.sectionHeaders[counter].virtualAddress.value = self._adjustSectionAlignment(vzPreviousSection + vaPreviousSection, fa, sa)
583 self.sectionHeaders[counter].pointerToRawData.value = self._adjustFileAlignment(rzPreviousSection + roPreviousSection, fa)
584
585 vz = self.sectionHeaders[counter].virtualAddress.value
586 rz = self.sectionHeaders[counter].pointerToRawData.value
587
588 if vz < rz:
589 print "WARNING: VirtualSize (%x) is less than SizeOfRawData (%x)" % (vz, rz)
590
591 counter += 1
592
593 except IndexError:
594 raise IndexError("list index out of range.")
595
596 else:
597 raise excep.SectionHeadersException("There is no section to extend.")
598
600 """
601 Fixes the necessary fields in the PE file instance in order to create a valid PE32. i.e. SizeOfImage.
602 """
603 sizeOfImage = 0
604 for sh in self.sectionHeaders:
605 sizeOfImage += sh.misc
606 self.ntHeaders.optionaHeader.sizeoOfImage.value = self._sectionAlignment(sizeOfImage + 0x1000)
607
609 """
610 Align a value to C{FileAligment}.
611
612 @type value: int
613 @param value: The value to align.
614
615 @type fileAlignment: int
616 @param fileAlignment: The value to be used to align the C{value} parameter.
617
618 @rtype: int
619 @return: The aligned value.
620 """
621 if fileAlignment > consts.DEFAULT_FILE_ALIGNMENT:
622 if not utils.powerOfTwo(fileAlignment):
623 print "Warning: FileAlignment is greater than DEFAULT_FILE_ALIGNMENT (0x200) and is not power of two."
624
625 if fileAlignment < consts.DEFAULT_FILE_ALIGNMENT:
626 return value
627
628 if fileAlignment and value % fileAlignment:
629 return ((value / fileAlignment) + 1) * fileAlignment
630
631 return value
632
634 """
635 Align a value to C{SectionAligment}.
636
637 @type value: int
638 @param value: The value to be aligned.
639
640 @type fileAlignment: int
641 @param fileAlignment: The value to be used as C{FileAlignment}.
642
643 @type sectionAlignment: int
644 @param sectionAlignment: The value to be used as C{SectionAlignment}.
645
646 @rtype: int
647 @return: The aligned value.
648 """
649 if fileAlignment < consts.DEFAULT_FILE_ALIGNMENT:
650 if fileAligment != sectionAlignment:
651 print "FileAlignment does not match SectionAlignment."
652
653 if sectionAlignment < consts.DEFAULT_PAGE_SIZE:
654 sectionAlignment = fileAlignment
655
656 if sectionAlignment and value % sectionAlignment:
657 return sectionAlignment * ((value / sectionAlignment) + 1)
658 return value
659
661 """
662 Returns a C{DWORD} from a given RVA.
663
664 @type rva: int
665 @param rva: The RVA to get the C{DWORD} from.
666
667 @rtype: L{DWORD}
668 @return: The L{DWORD} obtained at the given RVA.
669 """
670 return datatypes.DWORD.parse(utils.ReadData(self.getDataAtRva(rva, 4)))
671
673 """
674 Returns a C{WORD} from a given RVA.
675
676 @type rva: int
677 @param rva: The RVA to get the C{WORD} from.
678
679 @rtype: L{WORD}
680 @return: The L{WORD} obtained at the given RVA.
681 """
682 return datatypes.WORD.parse(utils.ReadData(self.getDataAtRva(rva, 2)))
683
685 """
686 Returns a C{DWORD} from a given offset.
687
688 @type offset: int
689 @param offset: The offset to get the C{DWORD} from.
690
691 @rtype: L{DWORD}
692 @return: The L{DWORD} obtained at the given offset.
693 """
694 return datatypes.DWORD.parse(utils.ReadData(self.getDataAtOffset(offset, 4)))
695
697 """
698 Returns a C{WORD} from a given offset.
699
700 @type offset: int
701 @param offset: The offset to get the C{WORD} from.
702
703 @rtype: L{WORD}
704 @return: The L{WORD} obtained at the given offset.
705 """
706 return datatypes.WORD.parse(utils.ReadData(self.getDataAtOffset(offset, 2)))
707
709 """
710 Returns a C{QWORD} from a given RVA.
711
712 @type rva: int
713 @param rva: The RVA to get the C{QWORD} from.
714
715 @rtype: L{QWORD}
716 @return: The L{QWORD} obtained at the given RVA.
717 """
718 return datatypes.QWORD.parse(utils.ReadData(self.getDataAtRva(rva, 8)))
719
721 """
722 Returns a C{QWORD} from a given offset.
723
724 @type offset: int
725 @param offset: The offset to get the C{QWORD} from.
726
727 @rtype: L{QWORD}
728 @return: The L{QWORD} obtained at the given offset.
729 """
730 return datatypes.QWORD.parse(utils.ReadData(self.getDataAtOffset(offset, 8)))
731
733 """
734 Gets binary data at a given RVA.
735
736 @type rva: int
737 @param rva: The RVA to get the data from.
738
739 @type size: int
740 @param size: The size of the data to be obtained.
741
742 @rtype: str
743 @return: The data obtained at the given RVA.
744 """
745 return self.getDataAtOffset(self.getOffsetFromRva(rva), size)
746
748 """
749 Gets binary data at a given offset.
750
751 @type offset: int
752 @param offset: The offset to get the data from.
753
754 @type size: int
755 @param size: The size of the data to be obtained.
756
757 @rtype: str
758 @return: The data obtained at the given offset.
759 """
760 data = str(self)
761 return data[offset:offset+size]
762
764 """
765 Returns a L{String} object from a given RVA.
766
767 @type rva: int
768 @param rva: The RVA to get the string from.
769
770 @rtype: L{String}
771 @return: A new L{String} object from the given RVA.
772 """
773 d = self.getDataAtRva(rva, 1)
774 resultStr = datatypes.String("")
775 while d != "\x00":
776 resultStr.value += d
777 rva += 1
778 d = self.getDataAtRva(rva, 1)
779 return resultStr
780
782 """
783 Determines if the current L{PE} instance is an Executable file.
784
785 @rtype: bool
786 @return: C{True} if the current L{PE} instance is an Executable file. Otherwise, returns C{False}.
787 """
788 if not self.isDll() and not self.isDriver() and self.fileHeader.characteristics == consts.IMAGE_FILE_EXECUTABLE_IMAGE:
789 return True
790 return False
791
793 """
794 Determines if the current L{PE} instance is a Dynamic Link Library file.
795
796 @rtype: bool
797 @return: C{True} if the current L{PE} instance is a DLL. Otherwise, returns C{False}.
798 """
799 if self.ntHeaders.fileHeader.characteristics == consts.IMAGE_FILE_DLL:
800 return True
801 return False
802
804 """
805 Determines if the current L{PE} instance is a driver (.sys) file.
806
807 @rtype: bool
808 @return: C{True} if the current L{PE} instance is a driver. Otherwise, returns C{False}.
809 """
810 modules = []
811 imports = self.ntHeaders.optionalHeader.dataDirectory[consts.IMPORT_DIRECTORY].info
812 for module in imports:
813 modules.append(module.metaData.moduleName.value.lower())
814
815 if set(["ntoskrnl.exe", "hal.dll", "ndis.sys", "bootvid.dll", "kdcom.dll"]).intersection(modules):
816 return True
817 return False
818
820 """
821 Determines if the current L{PE} instance is a PE32 file.
822
823 @rtype: bool
824 @return: C{True} if the current L{PE} instance is a PE32 file. Otherwise, returns C{False}.
825 """
826 if self.ntHeaders.optionalHeader.magic.value == consts.PE32:
827 return True
828 return False
829
831 """
832 Determines if the current L{PE} instance is a PE64 file.
833
834 @rtype: bool
835 @return: C{True} if the current L{PE} instance is a PE64 file. Otherwise, returns C{False}.
836 """
837 if self.ntHeaders.optionalHeader.magic.value == consts.PE64:
838 return True
839 return False
840
842 """
843 Determines if the current L{PE} instance is bounded, i.e. has a C{BOUND_IMPORT_DIRECTORY}.
844
845 @rtype: bool
846 @return: Returns C{True} if the current L{PE} instance is bounded. Otherwise, returns C{False}.
847 """
848 boundImportsDir = self.ntHeaders.optionalHeader.dataDirectory[consts.BOUND_IMPORT_DIRECTORY]
849 if boundImportsDir.rva.value and boundImportsDir.size.value:
850 return True
851 return False
852
854 """
855 Parses all the directories in the L{PE} instance.
856
857 @type dataDirectoryInstance: L{DataDirectory}
858 @param dataDirectoryInstance: A L{DataDirectory} object with the directories data.
859
860 @type magic: int
861 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
862 """
863 directories = [(consts.EXPORT_DIRECTORY, self._parseExportDirectory),\
864 (consts.IMPORT_DIRECTORY, self._parseImportDirectory),\
865 (consts.RESOURCE_DIRECTORY, self._parseResourceDirectory),\
866 (consts.EXCEPTION_DIRECTORY, self._parseExceptionDirectory),\
867 (consts.RELOCATION_DIRECTORY, self._parseRelocsDirectory),\
868 (consts.TLS_DIRECTORY, self._parseTlsDirectory),\
869 (consts.DEBUG_DIRECTORY, self._parseDebugDirectory),\
870 (consts.BOUND_IMPORT_DIRECTORY, self._parseBoundImportDirectory),\
871 (consts.DELAY_IMPORT_DIRECTORY, self._parseDelayImportDirectory),\
872 (consts.NET_METADATA_DIRECTORY, self._parseNetDirectory)]
873
874 for directory in directories:
875 dir = dataDirectoryInstance[directory[0]]
876 if dir.rva.value and dir.size.value:
877 dataDirectoryInstance[directory[0]].info = directory[1](dir.rva.value, dir.size.value, magic)
878
880 """
881 Parses the C{IMAGE_RESOURCE_DIRECTORY} directory.
882
883 @type rva: int
884 @param rva: The RVA where the C{IMAGE_RESOURCE_DIRECTORY} starts.
885
886 @type size: int
887 @param size: The size of the C{IMAGE_RESOURCE_DIRECTORY} directory.
888
889 @type magic: int
890 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
891
892 @rtype: str
893 @return: The C{IMAGE_RESOURCE_DIRECTORY} data.
894 """
895 return self.getDataAtRva(rva, size)
896
898 """
899 Parses the C{IMAGE_EXCEPTION_DIRECTORY} directory.
900
901 @type rva: int
902 @param rva: The RVA where the C{IMAGE_EXCEPTION_DIRECTORY} starts.
903
904 @type size: int
905 @param size: The size of the C{IMAGE_EXCEPTION_DIRECTORY} directory.
906
907 @type magic: int
908 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
909
910 @rtype: str
911 @return: The C{IMAGE_EXCEPTION_DIRECTORY} data.
912 """
913 return self.getDataAtRva(rva, size)
914
916 """
917 Parses the delay imports directory.
918
919 @type rva: int
920 @param rva: The RVA where the delay imports directory starts.
921
922 @type size: int
923 @param size: The size of the delay imports directory.
924
925 @type magic: int
926 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
927
928 @rtype: str
929 @return: The delay imports directory data.
930 """
931 return self.getDataAtRva(rva, size)
932
934 """
935 Parses the bound import directory.
936
937 @type rva: int
938 @param rva: The RVA where the bound import directory starts.
939
940 @type size: int
941 @param size: The size of the bound import directory.
942
943 @type magic: int
944 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
945
946 @rtype: L{ImageBoundImportDescriptor}
947 @return: A new L{ImageBoundImportDescriptor} object.
948 """
949 data = self.getDataAtRva(rva, size)
950 rd = utils.ReadData(data)
951 boundImportDirectory = directories.ImageBoundImportDescriptor.parse(rd)
952
953
954 for i in range(len(boundImportDirectory) - 1):
955 if hasattr(boundImportDirectory[i], "forwarderRefsList"):
956 if boundImportDirectory[i].forwarderRefsList:
957 for forwarderRefEntry in boundImportDirectory[i].forwarderRefsList:
958 offset = forwarderRefEntry.offsetModuleName.value
959 forwarderRefEntry.moduleName = self.readStringAtRva(offset + rva)
960
961 offset = boundImportDirectory[i].offsetModuleName.value
962 boundImportDirectory[i].moduleName = self.readStringAtRva(offset + rva)
963 return boundImportDirectory
964
966 """
967 Parses the TLS directory.
968
969 @type rva: int
970 @param rva: The RVA where the TLS directory starts.
971
972 @type size: int
973 @param size: The size of the TLS directory.
974
975 @type magic: int
976 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
977
978 @rtype: L{TLSDirectory}
979 @return: A new L{TLSDirectory}.
980 @note: if the L{PE} instance is a PE64 file then a new L{TLSDirectory64} is returned.
981 """
982 data = self.getDataAtRva(rva, size)
983 rd = utils.ReadData(data)
984
985 if magic == consts.PE32:
986 return directories.TLSDirectory.parse(rd)
987 elif magic == consts.PE64:
988 return directories.TLSDirectory64.parse(rd)
989 else:
990 raise excep.InvalidParameterException("Wrong magic")
991
993 """
994 Parses the relocation directory.
995
996 @type rva: int
997 @param rva: The RVA where the relocation directory starts.
998
999 @type size: int
1000 @param size: The size of the relocation directory.
1001
1002 @type magic: int
1003 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1004
1005 @rtype: L{ImageBaseRelocation}
1006 @return: A new L{ImageBaseRelocation} object.
1007 """
1008 data = self.getDataAtRva(rva, size)
1009
1010 rd = utils.ReadData(data)
1011
1012 relocsArray = directories.ImageBaseRelocation()
1013 while rd.offset < size:
1014 relocEntry = directories.ImageBaseRelocationEntry.parse(rd)
1015 relocsArray.append(relocEntry)
1016 return relocsArray
1017
1019 """
1020 Parses the C{IMAGE_EXPORT_DIRECTORY} directory.
1021
1022 @type rva: int
1023 @param rva: The RVA where the C{IMAGE_EXPORT_DIRECTORY} directory starts.
1024
1025 @type size: int
1026 @param size: The size of the C{IMAGE_EXPORT_DIRECTORY} directory.
1027
1028 @type magic: int
1029 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1030
1031 @rtype: L{ImageExportTable}
1032 @return: A new L{ImageExportTable} object.
1033 """
1034 data = self.getDataAtRva(rva, size)
1035 rd = utils.ReadData(data)
1036
1037 iet = directories.ImageExportTable.parse(rd)
1038
1039 auxFunctionRvaArray = list()
1040
1041 numberOfNames = iet.numberOfNames.value
1042 addressOfNames = iet.addressOfNames.value
1043 addressOfNameOrdinals = iet.addressOfNameOrdinals.value
1044 addressOfFunctions = iet.addressOfFunctions.value
1045
1046
1047 for i in range(iet.numberOfFunctions.value):
1048 auxFunctionRvaArray.append(self.getDwordAtRva(addressOfFunctions).value)
1049 addressOfFunctions += datatypes.DWORD().sizeof()
1050
1051 for i in range(numberOfNames):
1052
1053 nameRva = self.getDwordAtRva(addressOfNames).value
1054 nameOrdinal = self.getWordAtRva(addressOfNameOrdinals).value
1055 exportName = self.readStringAtRva(nameRva).value
1056
1057 entry = directories.ExportTableEntry()
1058
1059 ordinal = nameOrdinal + iet.base.value
1060
1061 entry.ordinal.value = ordinal
1062
1063 entry.nameOrdinal.vaue = nameOrdinal
1064 entry.nameRva.value = nameRva
1065 entry.name.value = exportName
1066 entry.functionRva.value = auxFunctionRvaArray[nameOrdinal]
1067
1068 iet.exportTable.append(entry)
1069
1070 addressOfNames += datatypes.DWORD().sizeof()
1071 addressOfNameOrdinals += datatypes.WORD().sizeof()
1072
1073
1074
1075
1076 for i in range(iet.numberOfFunctions.value):
1077
1078 if auxFunctionRvaArray[i] != iet.exportTable[i].functionRva.value:
1079 entry = directories.ExportTableEntry()
1080
1081 entry.functionRva.value = auxFunctionRvaArray[i]
1082 entry.ordinal.value = iet.base.value + i
1083
1084 iet.exportTable.append(entry)
1085
1086
1087 sorted(iet.exportTable, key=lambda entry:entry.ordinal)
1088 return iet
1089
1091 """
1092 Parses the C{IMAGE_DEBUG_DIRECTORY} directory.
1093 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680307(v=vs.85).aspx}
1094
1095 @type rva: int
1096 @param rva: The RVA where the C{IMAGE_DEBUG_DIRECTORY} directory starts.
1097
1098 @type size: int
1099 @param size: The size of the C{IMAGE_DEBUG_DIRECTORY} directory.
1100
1101 @type magic: int
1102 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1103
1104 @rtype: L{ImageDebugDirectory}
1105 @return: A new L{ImageDebugDirectory} object.
1106 """
1107 debugDirData = self.getDataAtRva(rva, size)
1108 numberOfEntries = size / consts.SIZEOF_IMAGE_DEBUG_ENTRY32
1109 rd = utils.ReadData(debugDirData)
1110 return directories.ImageDebugDirectories.parse(rd, numberOfEntries)
1111
1113 """
1114 Parses the C{IMAGE_IMPORT_DIRECTORY} directory.
1115
1116 @type rva: int
1117 @param rva: The RVA where the C{IMAGE_IMPORT_DIRECTORY} directory starts.
1118
1119 @type size: int
1120 @param size: The size of the C{IMAGE_IMPORT_DIRECTORY} directory.
1121
1122 @type magic: int
1123 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1124
1125 @rtype: L{ImageImportDescriptor}
1126 @return: A new L{ImageImportDescriptor} object.
1127
1128 @raise InvalidParameterException: If wrong magic was specified.
1129 """
1130
1131 importsDirData = self.getDataAtRva(rva, size)
1132
1133 numberOfEntries = size / consts.SIZEOF_IMAGE_IMPORT_ENTRY32
1134 rd = utils.ReadData(importsDirData)
1135
1136
1137
1138
1139 rdAux = utils.ReadData(importsDirData)
1140 count = 0
1141 entry = rdAux.read(consts.SIZEOF_IMAGE_IMPORT_ENTRY32)
1142 while rdAux.offset < len(rdAux.data) and not utils.allZero(entry):
1143 try:
1144 entry = rdAux.read(consts.SIZEOF_IMAGE_IMPORT_ENTRY32)
1145 count += 1
1146 except excep.DataLengthException:
1147 if self._verbose:
1148 print "[!] Warning: DataLengthException detected!."
1149
1150 if numberOfEntries - 1 > count:
1151 numberOfEntries = count + 1
1152
1153 iid = directories.ImageImportDescriptor.parse(rd, numberOfEntries)
1154 iidLength = len(iid)
1155
1156 peIsBounded = self.isPeBounded()
1157
1158 if magic == consts.PE64:
1159 ORDINAL_FLAG = consts.IMAGE_ORDINAL_FLAG64
1160 ADDRESS_MASK = consts.ADDRESS_MASK64
1161 elif magic == consts.PE32:
1162 ORDINAL_FLAG = consts.IMAGE_ORDINAL_FLAG
1163 ADDRESS_MASK = consts.ADDRESS_MASK32
1164 else:
1165 raise InvalidParameterException("magic value %d is not PE64 nor PE32." % magic)
1166
1167 for i in range(iidLength -1):
1168 if iid[i].originalFirstThunk.value != 0:
1169 iltRva = iid[i].originalFirstThunk.value
1170 iatRva = iid[i].firstThunk.value
1171
1172 if magic == consts.PE64:
1173 entry = self.getQwordAtRva(iltRva).value
1174 elif magic == consts.PE32:
1175 entry = self.getDwordAtRva(iltRva).value
1176
1177 while entry != 0:
1178
1179 if magic == consts.PE64:
1180 iatEntry = directories.ImportAddressTableEntry64()
1181 elif magic == consts.PE32:
1182 iatEntry = directories.ImportAddressTableEntry()
1183
1184 iatEntry.originalFirstThunk.value = entry
1185
1186 if iatEntry.originalFirstThunk.value & ORDINAL_FLAG:
1187 iatEntry.hint.value = None
1188 iatEntry.name.value = iatEntry.originalFirstThunk.value & ADDRESS_MASK
1189 else:
1190 iatEntry.hint.value = self.getWordAtRva(iatEntry.originalFirstThunk.value).value
1191 iatEntry.name.value = self.readStringAtRva(iatEntry.originalFirstThunk.value + 2).value
1192
1193 if magic == consts.PE64:
1194 iatEntry.firstThunk.value = self.getQwordAtRva(iatRva).value
1195 iltRva += 8
1196 iatRva += 8
1197 entry = self.getQwordAtRva(iltRva).value
1198 elif magic == consts.PE32:
1199 iatEntry.firstThunk.value = self.getDwordAtRva(iatRva).value
1200 iltRva += 4
1201 iatRva += 4
1202 entry = self.getDwordAtRva(iltRva).value
1203
1204 iid[i].iat.append(iatEntry)
1205
1206 else:
1207 iatRva = iid[i].firstThunk.value
1208
1209 if magic == consts.PE64:
1210 entry = self.getQwordAtRva(iatRva).value
1211 elif magic == consts.PE32:
1212 entry = self.getDwordAtRva(iatRva).value
1213
1214 while entry != 0:
1215
1216 if magic == consts.PE64:
1217 iatEntry = directories.ImportAddressTableEntry64()
1218 elif magic == consts.PE32:
1219 iatEntry = directories.ImportAddressTableEntry()
1220
1221 iatEntry.firstThunk.value = entry
1222 iatEntry.originalFirstThunk.value = 0
1223
1224 if not peIsBounded:
1225 ft = iatEntry.firstThunk.value
1226
1227 if ft & ORDINAL_FLAG:
1228 iatEntry.hint.value = None
1229 iatEntry.name.value = ft & ADDRESS_MASK
1230 else:
1231 iatEntry.hint.value = self.getWordAtRva(ft).value
1232 iatEntry.name.value = self.readStringAtRva(ft + 2).value
1233 else:
1234 iatEntry.hint.value = None
1235 iatEntry.name.value = None
1236
1237 if magic == consts.PE64:
1238 iatRva += 8
1239 entry = self.getQwordAtRva(iatRva).value
1240 elif magic == consts.PE32:
1241 iatRva += 4
1242 entry = self.getDwordAtRva(iatRva).value
1243
1244 iid[i].iat.append(iatEntry)
1245
1246 iid[i].metaData.moduleName.value = self.readStringAtRva(iid[i].name.value).value
1247 iid[i].metaData.numberOfImports.value = len(iid[i].iat)
1248 return iid
1249
1251 """
1252 Parses the NET directory.
1253 @see: U{http://www.ntcore.com/files/dotnetformat.htm}
1254
1255 @type rva: int
1256 @param rva: The RVA where the NET directory starts.
1257
1258 @type size: int
1259 @param size: The size of the NET directory.
1260
1261 @type magic: int
1262 @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
1263
1264 @rtype: L{NETDirectory}
1265 @return: A new L{NETDirectory} object.
1266 """
1267 if rva and size:
1268
1269 netDirectoryClass = directories.NETDirectory()
1270
1271
1272 netDir = directories.NetDirectory.parse(utils.ReadData(self.getDataAtRva(rva, size)))
1273
1274 netDirectoryClass.directory = netDir
1275
1276
1277 mdhRva = netDir.metaData.rva.value
1278 mdhSize = netDir.metaData.size.value
1279
1280
1281 rd = utils.ReadData(self.getDataAtRva(mdhRva, mdhSize))
1282
1283
1284 netDirectoryClass.netMetaDataHeader = directories.NetMetaDataHeader.parse(rd)
1285
1286
1287 numberOfStreams = netDirectoryClass.netMetaDataHeader.numberOfStreams.value
1288 netDirectoryClass.netMetaDataStreams = directories.NetMetaDataStreams.parse(rd, numberOfStreams)
1289
1290 for i in range(numberOfStreams):
1291 name = netDirectoryClass.netMetaDataStreams[i].name.value
1292 if name.find("#~") >= 0:
1293 netDirectoryClass.netMetaDataStreams[i].info = directories.NetMetaDataTables.parse(utils.ReadData(rd.read(netDirectoryClass.netMetaDataStreams[i].size.value)))
1294 else:
1295 netDirectoryClass.netMetaDataStreams[i].info = rd.read(netDirectoryClass.netMetaDataStreams[i].size.value)
1296
1297 return netDirectoryClass
1298
1300 """
1301 Get MD5 hash from PE file.
1302
1303 @rtype: str
1304 @return: The MD5 hash from the L{PE} instance.
1305 """
1306 return hashlib.md5(str(self)).hexdigest()
1307
1309 """
1310 Get SHA1 hash from PE file.
1311
1312 @rtype: str
1313 @return: The SHA1 hash from the L{PE} instance.
1314 """
1315 return hashlib.sha1(str(self)).hexdigest()
1316
1318 """
1319 Get SHA256 hash from PE file.
1320
1321 @rtype: str
1322 @return: The SHA256 hash from the L{PE} instance.
1323 """
1324 return hashlib.sha256(str(self)).hexdigest()
1325
1327 """
1328 Get SHA512 hash from PE file.
1329
1330 @rtype: str
1331 @return: The SHA512 hash from the L{PE} instance.
1332 """
1333 return hashlib.sha512(str(self)).hexdigest()
1334
1336 """
1337 Get CRC32 checksum from PE file.
1338
1339 @rtype: int
1340 @return: The CRD32 checksum from the L{PE} instance.
1341 """
1342 return binascii.crc32(str(self)) & 0xffffffff
1343
1345 """DosHeader object."""
1347 """
1348 Class representation of the C{IMAGE_DOS_HEADER} structure.
1349 @see: U{http://msdn.microsoft.com/en-us/magazine/cc301805.aspx}
1350
1351 @type shouldPack: bool
1352 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1353 """
1354 baseclasses.BaseStructClass.__init__(self, shouldPack)
1355
1356 self.e_magic = datatypes.WORD(consts.MZ_SIGNATURE)
1357 self.e_cblp = datatypes.WORD(0)
1358 self.e_cp = datatypes.WORD(0)
1359 self.e_crlc = datatypes.WORD(0)
1360 self.e_cparhdr = datatypes.WORD(0)
1361 self.e_minalloc = datatypes.WORD(0)
1362 self.e_maxalloc = datatypes.WORD(0)
1363 self.e_ss = datatypes.WORD(0)
1364 self.e_sp = datatypes.WORD(0)
1365 self.e_csum = datatypes.WORD(0)
1366 self.e_ip = datatypes.WORD(0)
1367 self.e_cs = datatypes.WORD(0)
1368 self.e_lfarlc = datatypes.WORD(0)
1369 self.e_ovno = datatypes.WORD(0)
1370
1371 self.e_res = datatypes.Array(datatypes.TYPE_WORD)
1372 self.e_res.extend([datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0)])
1373
1374 self.e_oemid = datatypes.WORD(0)
1375 self.e_oeminfo = datatypes.WORD(0)
1376
1377 self.e_res2 = datatypes.Array(datatypes.TYPE_WORD)
1378 self.e_res2.extend([datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0),\
1379 datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0), datatypes.WORD(0),\
1380 datatypes.WORD(0), datatypes.WORD(0)])
1381
1382 self.e_lfanew = datatypes.DWORD(0xf0)
1383
1384 self._attrsList = ["e_magic","e_cblp","e_cp","e_crlc","e_cparhdr","e_minalloc","e_maxalloc","e_ss","e_sp","e_csum",\
1385 "e_ip","e_cs","e_lfarlc","e_ovno","e_res","e_oemid","e_oeminfo","e_res2","e_lfanew"]
1386
1387 @staticmethod
1389 """
1390 Returns a new L{DosHeader} object.
1391
1392 @type readDataInstance: L{ReadData}
1393 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{DosHeader} object.
1394
1395 @rtype: L{DosHeader}
1396 @return: A new L{DosHeader} object.
1397 """
1398 dosHdr = DosHeader()
1399
1400 dosHdr.e_magic.value = readDataInstance.readWord()
1401 dosHdr.e_cblp.value = readDataInstance.readWord()
1402 dosHdr.e_cp.value = readDataInstance.readWord()
1403 dosHdr.e_crlc.value = readDataInstance.readWord()
1404 dosHdr.e_cparhdr.value = readDataInstance.readWord()
1405 dosHdr.e_minalloc.value = readDataInstance.readWord()
1406 dosHdr.e_maxalloc.value = readDataInstance.readWord()
1407 dosHdr.e_ss.value = readDataInstance.readWord()
1408 dosHdr.e_sp.value = readDataInstance.readWord()
1409 dosHdr.e_csum.value = readDataInstance.readWord()
1410 dosHdr.e_ip.value = readDataInstance.readWord()
1411 dosHdr.e_cs.value = readDataInstance.readWord()
1412 dosHdr.e_lfarlc.value = readDataInstance.readWord()
1413 dosHdr.e_ovno.value = readDataInstance.readWord()
1414
1415 dosHdr.e_res = datatypes.Array(datatypes.TYPE_WORD)
1416 for i in range(4):
1417 dosHdr.e_res.append(datatypes.WORD(readDataInstance.readWord()))
1418
1419 dosHdr.e_oemid.value = readDataInstance.readWord()
1420 dosHdr.e_oeminfo.value = readDataInstance.readWord()
1421
1422 dosHdr.e_res2 = datatypes.Array(datatypes.TYPE_WORD)
1423 for i in range (10):
1424 dosHdr.e_res2.append(datatypes.WORD(readDataInstance.readWord()))
1425
1426 dosHdr.e_lfanew.value = readDataInstance.readDword()
1427 return dosHdr
1428
1432
1434 """NtHeaders object."""
1436 """
1437 Class representation of the C{IMAGE_NT_HEADERS} structure.
1438 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680336%28v=vs.85%29.aspx}
1439
1440 @type shouldPack: bool
1441 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1442 """
1443 baseclasses.BaseStructClass.__init__(self, shouldPack)
1444
1445 self.signature = datatypes.DWORD(consts.PE_SIGNATURE)
1446 self.fileHeader = FileHeader()
1447 self.optionalHeader = OptionalHeader()
1448
1450 return str(self.signature) + str(self.fileHeader) + str(self.optionalHeader)
1451
1452 @staticmethod
1454 """
1455 Returns a new L{NtHeaders} object.
1456
1457 @type readDataInstance: L{ReadData}
1458 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{NtHeaders} object.
1459
1460 @rtype: L{NtHeaders}
1461 @return: A new L{NtHeaders} object.
1462 """
1463 nt = NtHeaders()
1464 nt.signature.value = readDataInstance.readDword()
1465 nt.fileHeader = FileHeader.parse(readDataInstance)
1466 nt.optionalHeader = OptionalHeader.parse(readDataInstance)
1467 return nt
1468
1472
1474 """FileHeader object."""
1476 """
1477 Class representation of the C{IMAGE_FILE_HEADER} structure.
1478 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680313%28v=vs.85%29.aspx}
1479
1480 @type shouldPack: bool
1481 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1482 """
1483 baseclasses.BaseStructClass.__init__(self, shouldPack = True)
1484
1485 self.machine = datatypes.WORD(consts.INTEL386)
1486 self.numberOfSections = datatypes.WORD(1)
1487 self.timeDateStamp = datatypes.DWORD(0)
1488 self.pointerToSymbolTable = datatypes.DWORD(0)
1489 self.numberOfSymbols = datatypes.DWORD(0)
1490 self.sizeOfOptionalHeader = datatypes.WORD(0xe0)
1491 self.characteristics = datatypes.WORD(consts.COMMON_CHARACTERISTICS)
1492
1493 self._attrsList = ["machine","numberOfSections","timeDateStamp","pointerToSymbolTable","numberOfSymbols",\
1494 "sizeOfOptionalHeader","characteristics"]
1495
1496 @staticmethod
1498 """
1499 Returns a new L{FileHeader} object.
1500
1501 @type readDataInstance: L{ReadData}
1502 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{FileHeader} object.
1503
1504 @rtype: L{FileHeader}
1505 @return: A new L{ReadData} object.
1506 """
1507 fh = FileHeader()
1508 fh.machine.value = readDataInstance.readWord()
1509 fh.numberOfSections.value = readDataInstance.readWord()
1510 fh.timeDateStamp.value = readDataInstance.readDword()
1511 fh.pointerToSymbolTable.value = readDataInstance.readDword()
1512 fh.numberOfSymbols.value = readDataInstance.readDword()
1513 fh.sizeOfOptionalHeader.value = readDataInstance.readWord()
1514 fh.characteristics.value = readDataInstance.readWord()
1515 return fh
1516
1520
1522 """OptionalHeader object."""
1524 """
1525 Class representation of the C{IMAGE_OPTIONAL_HEADER} structure.
1526 @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680339%28v=vs.85%29.aspx}
1527
1528 @type shouldPack: bool
1529 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1530 """
1531 baseclasses.BaseStructClass.__init__(self, shouldPack)
1532
1533 self.magic = datatypes.WORD(consts.PE32)
1534 self.majorLinkerVersion = datatypes.BYTE(2)
1535 self.minorLinkerVersion = datatypes.BYTE(0x19)
1536 self.sizeOfCode = datatypes.DWORD(0x1000)
1537 self.sizeOfInitializedData = datatypes.DWORD(0)
1538 self.sizeOfUninitializedData = datatypes.DWORD(0)
1539 self.addressOfEntryPoint = datatypes.DWORD(0x1000)
1540 self.baseOfCode = datatypes.DWORD(0x1000)
1541 self.baseOfData = datatypes.DWORD(0x1000)
1542 self.imageBase = datatypes.DWORD(0x400000)
1543 self.sectionAlignment = datatypes.DWORD(0x1000)
1544 self.fileAlignment = datatypes.DWORD(0x200)
1545 self.majorOperatingSystemVersion = datatypes.WORD(5)
1546 self.minorOperatingSystemVersion = datatypes.WORD(0)
1547 self.majorImageVersion = datatypes.WORD(6)
1548 self.minorImageVersion = datatypes.WORD(0)
1549 self.majorSubsystemVersion = datatypes.WORD(5)
1550 self.minorSubsystemVersion = datatypes.WORD(0)
1551 self.win32VersionValue = datatypes.DWORD(0)
1552 self.sizeOfImage = datatypes.DWORD(0x2000)
1553 self.sizeOfHeaders = datatypes.DWORD(0x400)
1554 self.checksum = datatypes.DWORD(0)
1555 self.subsystem = datatypes.WORD(consts.WINDOWSGUI)
1556 self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE)
1557 self.sizeOfStackReserve = datatypes.DWORD(0x00100000)
1558 self.sizeOfStackCommit = datatypes.DWORD(0x00004000)
1559 self.sizeOfHeapReserve = datatypes.DWORD(00100000)
1560 self.sizeOfHeapCommit = datatypes.DWORD(0x1000)
1561 self.loaderFlags = datatypes.DWORD(0)
1562 self.numberOfRvaAndSizes = datatypes.DWORD(0x10)
1563 self.dataDirectory = datadirs.DataDirectory()
1564
1565 self._attrsList = ["magic","majorLinkerVersion","minorLinkerVersion","sizeOfCode","sizeOfInitializedData",\
1566 "sizeOfUninitializedData","addressOfEntryPoint","baseOfCode","baseOfData","imageBase","sectionAlignment",\
1567 "fileAlignment","majorOperatingSystemVersion","minorOperatingSystemVersion","majorImageVersion",\
1568 "minorImageVersion","majorSubsystemVersion","minorSubsystemVersion","win32VersionValue","sizeOfImage",\
1569 "sizeOfHeaders","checksum","subsystem","dllCharacteristics","sizeOfStackReserve","sizeOfStackCommit",\
1570 "sizeOfHeapReserve","sizeOfHeapCommit","loaderFlags","numberOfRvaAndSizes","dataDirectory"]
1571
1572 @staticmethod
1574 """
1575 Returns a new L{OptionalHeader} object.
1576
1577 @type readDataInstance: L{ReadData}
1578 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{OptionalHeader} object.
1579
1580 @rtype: L{OptionalHeader}
1581 @return: A new L{OptionalHeader} object.
1582 """
1583 oh = OptionalHeader()
1584
1585 oh.magic.value = readDataInstance.readWord()
1586 oh.majorLinkerVersion.value = readDataInstance.readByte()
1587 oh.minorLinkerVersion.value = readDataInstance.readByte()
1588 oh.sizeOfCode.value = readDataInstance.readDword()
1589 oh.sizeOfInitializedData.value = readDataInstance.readDword()
1590 oh.sizeOfUninitializedData.value = readDataInstance.readDword()
1591 oh.addressOfEntryPoint.value = readDataInstance.readDword()
1592 oh.baseOfCode.value = readDataInstance.readDword()
1593 oh.baseOfData.value = readDataInstance.readDword()
1594 oh.imageBase.value = readDataInstance.readDword()
1595 oh.sectionAlignment.value = readDataInstance.readDword()
1596 oh.fileAlignment.value = readDataInstance.readDword()
1597 oh.majorOperatingSystemVersion.value = readDataInstance.readWord()
1598 oh.minorOperatingSystemVersion.value = readDataInstance.readWord()
1599 oh.majorImageVersion.value = readDataInstance.readWord()
1600 oh.minorImageVersion.value = readDataInstance.readWord()
1601 oh.majorSubsystemVersion.value = readDataInstance.readWord()
1602 oh.minorSubsystemVersion.value = readDataInstance.readWord()
1603 oh.win32VersionValue.value = readDataInstance.readDword()
1604 oh.sizeOfImage.value = readDataInstance.readDword()
1605 oh.sizeOfHeaders.value = readDataInstance.readDword()
1606 oh.checksum.value = readDataInstance.readDword()
1607 oh.subsystem.value = readDataInstance.readWord()
1608 oh.dllCharacteristics.value = readDataInstance.readWord()
1609 oh.sizeOfStackReserve.value = readDataInstance.readDword()
1610 oh.sizeOfStackCommit.value = readDataInstance.readDword()
1611 oh.sizeOfHeapReserve.value = readDataInstance.readDword()
1612 oh.sizeOfHeapCommit.value = readDataInstance.readDword()
1613 oh.loaderFlags.value = readDataInstance.readDword()
1614 oh.numberOfRvaAndSizes.value = readDataInstance.readDword()
1615
1616 dirs = readDataInstance.read(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 8)
1617
1618 oh.dataDirectory = datadirs.DataDirectory.parse(utils.ReadData(dirs))
1619
1620 return oh
1621
1625
1659 """OptionalHeader64 object."""
1661 """
1662 Class representation of the C{IMAGE_OPTIONAL_HEADER64} structure.
1663 @see: Remarks in U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms680339%28v=vs.85%29.aspx}
1664
1665 @type shouldPack: bool
1666 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1667 """
1668 baseclasses.BaseStructClass.__init__(self, shouldPack)
1669
1670 self.magic = datatypes.WORD(consts.PE32)
1671 self.majorLinkerVersion = datatypes.BYTE(2)
1672 self.minorLinkerVersion = datatypes.BYTE(0x19)
1673 self.sizeOfCode = datatypes.DWORD(0x1000)
1674 self.sizeOfInitializedData = datatypes.DWORD(0)
1675 self.sizeOfUninitializedData = datatypes.DWORD(0)
1676 self.addressOfEntryPoint = datatypes.DWORD(0x1000)
1677 self.baseOfCode = datatypes.DWORD(0x1000)
1678 self.imageBase = datatypes.QWORD(0x400000)
1679 self.sectionAlignment = datatypes.DWORD(0x1000)
1680 self.fileAlignment = datatypes.DWORD(0x200)
1681 self.majorOperatingSystemVersion = datatypes.WORD(5)
1682 self.minorOperatingSystemVersion = datatypes.WORD(0)
1683 self.majorImageVersion = datatypes.WORD(6)
1684 self.minorImageVersion = datatypes.WORD(0)
1685 self.majorSubsystemVersion = datatypes.WORD(5)
1686 self.minorSubsystemVersion = datatypes.WORD(0)
1687 self.win32VersionValue = datatypes.DWORD(0)
1688 self.sizeOfImage = datatypes.DWORD(0x2000)
1689 self.sizeOfHeaders = datatypes.DWORD(0x400)
1690 self.checksum = datatypes.DWORD(0)
1691 self.subsystem = datatypes.WORD(consts.WINDOWSGUI)
1692 self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE)
1693 self.sizeOfStackReserve = datatypes.QWORD(0x00100000)
1694 self.sizeOfStackCommit = datatypes.QWORD(0x00004000)
1695 self.sizeOfHeapReserve = datatypes.QWORD(00100000)
1696 self.sizeOfHeapCommit = datatypes.QWORD(0x1000)
1697 self.loaderFlags = datatypes.DWORD(0)
1698 self.numberOfRvaAndSizes = datatypes.DWORD(0x10)
1699 self.dataDirectory = datadirs.DataDirectory()
1700
1701 self._attrsList = ["magic","majorLinkerVersion","minorLinkerVersion","sizeOfCode","sizeOfInitializedData",\
1702 "sizeOfUninitializedData","addressOfEntryPoint","baseOfCode", "imageBase","sectionAlignment",\
1703 "fileAlignment","majorOperatingSystemVersion","minorOperatingSystemVersion","majorImageVersion",\
1704 "minorImageVersion","majorSubsystemVersion","minorSubsystemVersion","win32VersionValue","sizeOfImage",\
1705 "sizeOfHeaders","checksum","subsystem","dllCharacteristics","sizeOfStackReserve","sizeOfStackCommit",\
1706 "sizeOfHeapReserve","sizeOfHeapCommit","loaderFlags","numberOfRvaAndSizes","dataDirectory"]
1707
1708 @staticmethod
1710 """
1711 Returns a new L{OptionalHeader64} object.
1712
1713 @type readDataInstance: L{ReadData}
1714 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{OptionalHeader64} object.
1715
1716 @rtype: L{OptionalHeader64}
1717 @return: A new L{OptionalHeader64} object.
1718 """
1719 oh = OptionalHeader64()
1720
1721 oh.magic.value = readDataInstance.readWord()
1722 oh.majorLinkerVersion.value = readDataInstance.readByte()
1723 oh.minorLinkerVersion.value = readDataInstance.readByte()
1724 oh.sizeOfCode.value = readDataInstance.readDword()
1725 oh.sizeOfInitializedData.value = readDataInstance.readDword()
1726 oh.sizeOfUninitializedData.value = readDataInstance.readDword()
1727 oh.addressOfEntryPoint.value = readDataInstance.readDword()
1728 oh.baseOfCode.value = readDataInstance.readDword()
1729 oh.imageBase.value = readDataInstance.readQword()
1730 oh.sectionAlignment.value = readDataInstance.readDword()
1731 oh.fileAlignment.value = readDataInstance.readDword()
1732 oh.majorOperatingSystemVersion.value = readDataInstance.readWord()
1733 oh.minorOperatingSystemVersion.value = readDataInstance.readWord()
1734 oh.majorImageVersion.value = readDataInstance.readWord()
1735 oh.minorImageVersion.value = readDataInstance.readWord()
1736 oh.majorSubsystemVersion.value = readDataInstance.readWord()
1737 oh.minorSubsystemVersion.value = readDataInstance.readWord()
1738 oh.win32VersionValue.value = readDataInstance.readDword()
1739 oh.sizeOfImage.value = readDataInstance.readDword()
1740 oh.sizeOfHeaders.value = readDataInstance.readDword()
1741 oh.checksum.value = readDataInstance.readDword()
1742 oh.subsystem.value = readDataInstance.readWord()
1743 oh.dllCharacteristics.value = readDataInstance.readWord()
1744 oh.sizeOfStackReserve.value = readDataInstance.readQword()
1745 oh.sizeOfStackCommit.value = readDataInstance.readQword()
1746 oh.sizeOfHeapReserve.value = readDataInstance.readQword()
1747 oh.sizeOfHeapCommit.value = readDataInstance.readQword()
1748 oh.loaderFlags.value = readDataInstance.readDword()
1749 oh.numberOfRvaAndSizes.value = readDataInstance.readDword()
1750
1751 dirs = readDataInstance.read(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 8)
1752
1753 oh.dataDirectory = datadirs.DataDirectory.parse(utils.ReadData(dirs))
1754
1755 return oh
1756
1760
1762 """SectionHeader object."""
1764 """
1765 Class representation of the C{IMAGE_SECTION_HEADER} structure.
1766 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms680341%28v=vs.85%29.aspx}
1767
1768 @type shouldPack: bool
1769 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1770 """
1771 baseclasses.BaseStructClass.__init__(self, shouldPack)
1772
1773 self.name = datatypes.String('.travest')
1774 self.misc = datatypes.DWORD(0x1000)
1775 self.virtualAddress = datatypes.DWORD(0x1000)
1776 self.sizeOfRawData = datatypes.DWORD(0x200)
1777 self.pointerToRawData = datatypes.DWORD(0x400)
1778 self.pointerToRelocations = datatypes.DWORD(0)
1779 self.pointerToLineNumbers = datatypes.DWORD(0)
1780 self.numberOfRelocations = datatypes.WORD(0)
1781 self.numberOfLinesNumbers = datatypes.WORD(0)
1782 self.characteristics = datatypes.DWORD(0x60000000)
1783
1784 self._attrsList = ["name","misc","virtualAddress","sizeOfRawData","pointerToRawData","pointerToRelocations",\
1785 "pointerToLineNumbers","numberOfRelocations","numberOfLinesNumbers","characteristics"]
1786
1787 @staticmethod
1789 """
1790 Returns a new L{SectionHeader} object.
1791
1792 @type readDataInstance: L{ReadData}
1793 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{SectionHeader} object.
1794
1795 @rtype: L{SectionHeader}
1796 @return: A new L{SectionHeader} object.
1797 """
1798 sh = SectionHeader()
1799 sh.name.value = readDataInstance.read(8)
1800 sh.misc.value = readDataInstance.readDword()
1801 sh.virtualAddress.value = readDataInstance.readDword()
1802 sh.sizeOfRawData.value = readDataInstance.readDword()
1803 sh.pointerToRawData.value = readDataInstance.readDword()
1804 sh.pointerToRelocations.value = readDataInstance.readDword()
1805 sh.pointerToLineNumbers.value = readDataInstance.readDword()
1806 sh.numberOfRelocations.value = readDataInstance.readWord()
1807 sh.numberOfLinesNumbers.value = readDataInstance.readWord()
1808 sh.characteristics.value = readDataInstance.readDword()
1809 return sh
1810
1814
1816 """SectionHeaders object."""
1818 """
1819 Array of L{SectionHeader} objects.
1820
1821 @type shouldPack: bool
1822 @param shouldPack: (Optional) If set to C{True}, the object will be packed. If set to C{False}, the object won't be packed.
1823
1824 @type numberOfSectionHeaders: int
1825 @param numberOfSectionHeaders: (Optional) The number of desired section headers. By default, this parameter is set to 1.
1826 """
1827 list.__init__(self)
1828
1829 self.shouldPack = shouldPack
1830
1831 if numberOfSectionHeaders:
1832 for i in range(numberOfSectionHeaders):
1833 sh = SectionHeader()
1834 self.append(sh)
1835
1837 return "".join([str(x) for x in self if x.shouldPack])
1838
1839 @staticmethod
1841 """
1842 Returns a new L{SectionHeaders} object.
1843
1844 @type readDataInstance: L{ReadData}
1845 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{SectionHeaders} object.
1846
1847 @type numberOfSectionHeaders: int
1848 @param numberOfSectionHeaders: The number of L{SectionHeader} objects in the L{SectionHeaders} instance.
1849 """
1850 sHdrs = SectionHeaders(numberOfSectionHeaders = 0)
1851
1852 for i in range(numberOfSectionHeaders):
1853 sh = SectionHeader()
1854
1855 sh.name.value = readDataInstance.read(8)
1856 sh.misc.value = readDataInstance.readDword()
1857 sh.virtualAddress.value = readDataInstance.readDword()
1858 sh.sizeOfRawData.value = readDataInstance.readDword()
1859 sh.pointerToRawData.value = readDataInstance.readDword()
1860 sh.pointerToRelocations.value = readDataInstance.readDword()
1861 sh.pointerToLineNumbers.value = readDataInstance.readDword()
1862 sh.numberOfRelocations.value = readDataInstance.readWord()
1863 sh.numberOfLinesNumbers.value = readDataInstance.readWord()
1864 sh.characteristics.value = readDataInstance.readDword()
1865
1866 sHdrs.append(sh)
1867
1868 return sHdrs
1869
1871 """Sections object."""
1872 - def __init__(self, sectionHeadersInstance = None):
1873 """
1874 Array with the data of each section present in the file.
1875
1876 @type sectionHeadersInstance: instance
1877 @param sectionHeadersInstance: (Optional) A L{SectionHeaders} instance to be parsed.
1878 """
1879 list.__init__(self)
1880
1881 if sectionHeadersInstance:
1882 for sh in sectionHeadersInstance:
1883 self.append("\xcc" * sh.sizeOfRawData.value)
1884
1886 return "".join([str(data) for data in self])
1887
1888 @staticmethod
1889 - def parse(readDataInstance, sectionHeadersInstance):
1890 """
1891 Returns a new L{Sections} object.
1892
1893 @type readDataInstance: L{ReadData}
1894 @param readDataInstance: A L{ReadData} object with data to be parsed as a L{Sections} object.
1895
1896 @type sectionHeadersInstance: instance
1897 @param sectionHeadersInstance: The L{SectionHeaders} instance with the necessary to parse every section data.
1898
1899 @rtype: L{Sections}
1900 @return: A new L{Sections} object.
1901 """
1902 sData = Sections()
1903
1904 for sectionHdr in sectionHeadersInstance:
1905
1906 if sectionHdr.sizeOfRawData.value > len(readDataInstance.data):
1907 print "Warning: SizeOfRawData is larger than file."
1908
1909 if sectionHdr.pointerToRawData.value > len(readDataInstance.data):
1910 print "Warning: PointerToRawData points beyond the end of the file."
1911
1912 if sectionHdr.misc.value > 0x10000000:
1913 print "Warning: VirtualSize is extremely large > 256MiB."
1914
1915 if sectionHdr.virtualAddress.value > 0x10000000:
1916 print "Warning: VirtualAddress is beyond 0x10000000"
1917
1918
1919 if sectionHdr.pointerToRawData.value:
1920 sData.append(readDataInstance.read(sectionHdr.sizeOfRawData.value))
1921
1922 return sData
1923