Package pype32 :: Module pype32 |
[hide private]
[frames] | no frames]

# Source Code for Module pype32.pype32

       1  #!/usr/bin/python
       2  # -*- coding: utf-8 -*-
       3
       4  # Copyright (c) 2013, Nahuel Riva
       5  # All rights reserved.
       6  #
       7  # Redistribution and use in source and binary forms, with or without
       8  # modification, are permitted provided that the following conditions are met:
       9  #
      10  #     * Redistributions of source code must retain the above copyright notice,
      11  #       this list of conditions and the following disclaimer.
      12  #     * Redistributions in binary form must reproduce the above copyright
      13  #       notice,this list of conditions and the following disclaimer in the
      14  #       documentation and/or other materials provided with the distribution.
      15  #     * Neither the name of the copyright holder nor the names of its
      16  #       contributors may be used to endorse or promote products derived from
      17  #       this software without specific prior written permission.
      18  #
      19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      23  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      24  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      25  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      27  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      28  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      29  # POSSIBILITY OF SUCH DAMAGE.
      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
      69
      70 -class PE(object):
      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() #: L{DosHeader} dosHeader.
      97          self.dosStub = PE.getDosStub() #: C{str} dosStub.
      98          self.ntHeaders = NtHeaders() #: L{NtHeaders} ntHeaders.
      99          self.sectionHeaders = SectionHeaders() #: L{SectionHeaders} sectionHeaders.
     100          self.sections = Sections(self.sectionHeaders) #: L{Sections} sections.
     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                  # nasty check to avoid loading a non-PE file
     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
     134 -    def hasMZSignature(self, rd):
     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
     150 -    def hasPESignature(self, rd):
     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
     167 -    def validate(self):
     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          # Ange Albertini (@angie4771) can kill me for this! :)
     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
     186 -    def readFile(self, pathToFile):
     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
     233 -    def __len__(self):
     234          return len(str(self))
     235
     236 -    def __str__(self):
     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          #if not self._fastLoad:
     244              #pe = self._updateDirectoriesData(pe)
     245          return pe
     246
     247 -    def _updateDirectoriesData(self, peStr):
     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
     268 -    def _getPaddingDataToSectionOffset(self):
     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              # adjust the offset in readDataInstance to the RawOffset + RawSize of the last section
     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
     336 -    def getOffsetFromRva(self, rva):
     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
     356 -    def getRvaFromOffset(self, offset):
     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
     374 -    def getSectionByOffset(self, offset):
     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
     391 -    def getSectionIndexByName(self, name):
     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
     410 -    def getSectionByRva(self, rva):
     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
     440 -    def getDosStub():
     441          """
     442          Returns a default DOS stub.
     443
     444          @rtype: str
     445          @return: A defaul DOS stub.
     446          """
     447          return "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A240000000000000037E338C97382569A7382569A7382569A6DD0D29A6982569A6DD0C39A6382569A6DD0D59A3A82569A54442D9A7482569A7382579A2582569A6DD0DC9A7282569A6DD0C29A7282569A6DD0C79A7282569A526963687382569A000000000000000000000000000000000000000000000000".decode("hex")
     448
     449 -    def _getPaddingToSectionOffset(self):
     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
     458 -    def fullLoad(self):
     459          """Parse all the directories in the PE file."""
     460          self._parseDirectories(self.ntHeaders.optionalHeader.dataDirectory, self.PE_TYPE)
     461
     462 -    def _internalParse(self, readDataInstance):
     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          # as padding is possible between the last section header and the beginning of the first section
     484          # we must adjust the offset in readDataInstance to point to the first byte of the first section.
     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              # get the va, vz, ra and rz of the last section in the array of section headers
     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
     534 -    def extendSection(self, sectionIndex, data):
     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                      # we are in the last section or self.sectionHeaders has only 1 sectionHeader instance
     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                  # if it is not the last section ...
     577                  try:
     578                      # adjust data of the section the user wants to extend
     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                          # adjust VA and RO of the next section
     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
     618 -    def _fixPe(self):
     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
     627 -    def _adjustFileAlignment(self, value, fileAlignment):
     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
     652 -    def _adjustSectionAlignment(self, value, fileAlignment, sectionAlignment):
     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
     679 -    def getDwordAtRva(self, rva):
     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
     691 -    def getWordAtRva(self, rva):
     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
     703 -    def getDwordAtOffset(self, offset):
     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
     715 -    def getWordAtOffset(self, offset):
     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
     727 -    def getQwordAtRva(self, rva):
     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
     739 -    def getQwordAtOffset(self, offset):
     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
     751 -    def getDataAtRva(self, rva, size):
     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
     766 -    def getDataAtOffset(self, offset, size):
     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
     782 -    def readStringAtRva(self, rva):
     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
     800 -    def isExe(self):
     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
     811 -    def isDll(self):
     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
     822 -    def isDriver(self):
     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
     838 -    def isPe32(self):
     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
     849 -    def isPe64(self):
     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
     860 -    def isPeBounded(self):
     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
     872 -    def isNXEnabled(self):
     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          # http://www.powerofcommunity.net/poc2014/mj0011.pdf
     883          # https://github.com/DarthTon/Blackbone/blob/master/src/BlackBoneDrv/PEStructs.h
     884          # http://static1.1.sqspcdn.com/static/f/336849/25005618/1402230025800/ep12-FullDump.txt?token=13GN1EahQqnHjM%2Ft3hnDCfQ03iU%3D
     885          # http://www.virtualbox.org/svn/vbox/trunk/src/VBox/Runtime/include/internal/ldrPE.h
     886 -    def isCFGEnabled(self):
     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
     897 -    def isASLREnabled(self):
     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
     907 -    def isSAFESEHEnabled(self):
     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
     928 -    def _parseDirectories(self, dataDirectoryInstance, magic = consts.PE32):
     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
     958 -    def _parseResourceDirectory(self, rva, size, magic = consts.PE32):
     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
     976 -    def _parseExceptionDirectory(self, rva, size, magic = consts.PE32):
     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
     994 -    def _parseDelayImportDirectory(self, rva, size, magic = consts.PE32):
     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
    1012 -    def _parseBoundImportDirectory(self, rva, size, magic = consts.PE32):
    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          # parse the name of every bounded import.
    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
    1044 -    def _parseLoadConfigDirectory(self, rva, size, magic = consts.PE32):
    1045          """
    1046          Parses IMAGE_LOAD_CONFIG_DIRECTORY.
    1047
    1048          @type rva: int
    1049          @param rva: The RVA where the IMAGE_LOAD_CONFIG_DIRECTORY starts.
    1050
    1051          @type size: int
    1052          @param size: The size of the IMAGE_LOAD_CONFIG_DIRECTORY.
    1053
    1054          @type magic: int
    1055          @param magic: (Optional) The type of PE. This value could be L{consts.PE32} or L{consts.PE64}.
    1056
    1057          @rtype: L{ImageLoadConfigDirectory}
    1058          @return: A new L{ImageLoadConfigDirectory}.
    1059          @note: if the L{PE} instance is a PE64 file then a new L{ImageLoadConfigDirectory64} is returned.
    1060          """
    1061          # print "RVA: %x - SIZE: %x" % (rva, size)
    1062
    1063          # I've found some issues when parsing the IMAGE_LOAD_CONFIG_DIRECTORY in some DLLs.
    1064          # There is an inconsistency with the size of the struct between MSDN docs and VS.
    1065          # sizeof(IMAGE_LOAD_CONFIG_DIRECTORY) should be 0x40, in fact, that's the size Visual Studio put
    1066          # in the directory table, even if the DLL was compiled with SAFESEH:ON. But If that is the case, the sizeof the
    1067          # struct should be 0x48.
    1068          # more information here: http://www.accuvant.com/blog/old-meets-new-microsoft-windows-safeseh-incompatibility
    1069          data = self.getDataAtRva(rva, directories.ImageLoadConfigDirectory().sizeof())
    1070          rd = utils.ReadData(data)
    1071
    1072          if magic == consts.PE32:
    1073              return directories.ImageLoadConfigDirectory.parse(rd)
    1074          elif magic == consts.PE64:
    1075              return directories.ImageLoadConfigDirectory64.parse(rd)
    1076          else:
    1077              raise excep.InvalidParameterException("Wrong magic")
    1078
    1079 -    def _parseTlsDirectory(self, rva, size, magic = consts.PE32):
    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
    1106 -    def _parseRelocsDirectory(self, rva, size, magic = consts.PE32):
    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          #print "Length Relocation data: %x" % len(data)
    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
    1132 -    def _parseExportDirectory(self, rva, size, magic = consts.PE32):
    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          # populate the auxFunctionRvaArray
    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              #print "Ordinal value: %d" % ordinal
    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          #print "export table length: %d" % len(iet.exportTable)
    1188
    1189          #print "auxFunctionRvaArray: %r" % auxFunctionRvaArray
    1190          for i in xrange(iet.numberOfFunctions.value):
    1191              #print "auxFunctionRvaArray[%d]: %x" % (i,  auxFunctionRvaArray[i])
    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          #print "export table length: %d" % len(iet.exportTable)
    1201          sorted(iet.exportTable, key=lambda entry:entry.ordinal)
    1202          return iet
    1203
    1204 -    def _parseDebugDirectory(self, rva, size, magic = consts.PE32):
    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
    1226 -    def _parseImportDirectory(self, rva, size, magic = consts.PE32):
    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          #print "RVA: %x - Size: %x" % (rva, size)
    1245          importsDirData = self.getDataAtRva(rva,  size)
    1246          #print "Length importsDirData: %d" % len(importsDirData)
    1247          numberOfEntries = size / consts.SIZEOF_IMAGE_IMPORT_ENTRY32
    1248          rd = utils.ReadData(importsDirData)
    1249
    1250          # In .NET binaries, the size of the data directory corresponding to the import table
    1251          # is greater than the number of bytes in the file. Thats why we check for the last group of 5 null bytes
    1252          # that indicates the end of the IMAGE_IMPORT_DESCRIPTOR array.
    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
    1364 -    def _parseNetDirectory(self, rva, size, magic = consts.PE32):
    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          # create a NETDirectory class to hold the data
    1385          netDirectoryClass = directories.NETDirectory()
    1386
    1387          # parse the .NET Directory
    1388          netDir = directories.NetDirectory.parse(utils.ReadData(self.getDataAtRva(rva,  size)))
    1389
    1390          netDirectoryClass.directory = netDir
    1391
    1392          # get the MetaData RVA and Size
    1393          mdhRva = netDir.metaData.rva.value
    1394          mdhSize = netDir.metaData.size.value
    1395
    1396          # read all the MetaData
    1397          rd = utils.ReadData(self.getDataAtRva(mdhRva, mdhSize))
    1398
    1399          # parse the MetaData headers
    1400          netDirectoryClass.netMetaDataHeader = directories.NetMetaDataHeader.parse(rd)
    1401
    1402          # parse the NET metadata streams
    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          # parse .NET resources
    1438          # get the Resources RVA and Size
    1439          resRva = netDir.resources.rva.value
    1440          resSize = netDir.resources.size.value
    1441
    1442          # read all the MetaData
    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
    1460 -    def getMd5(self):
    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
    1469 -    def getSha1(self):
    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
    1478 -    def getSha256(self):
    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
    1487 -    def getSha512(self):
    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
    1496 -    def getCRC32(self):
    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
    1505 -    def hasImportedFunction(self, funcName):
    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
    1521 -    def getNetMetadataToken(self, token):
    1522          dnh = self.ntHeaders.optionalHeader.dataDirectory[14].info
    1523          if not dnh: return None
    1524          tables = dnh.netMetaDataStreams[0].info.tables
    1525
    1526          tblid = token >> 24 & 0xff
    1527          table = tables.get(tblid)
    1528          if not table:
    1529              return None
    1530
    1531          rowid = (token & 0xffffff) - 1
    1532          if rowid < 0 or rowid >= len(table):
    1533              return None
    1534
    1535          return table[rowid]
    1536
    1537 -    def getNetEntryPointOffset(self):
    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              # print("Native entry point.")
    1546              offset = self.getOffsetFromRva(token)
    1547          else:
    1548              # print("Managed entry point.")
    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                  # print("Tiny header.")
    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                  # print("Fat header.")
    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
    1573 -class DosHeader(baseclasses.BaseStructClass):
    1574      """DosHeader object."""
    1575 -    def __init__(self,  shouldPack = True):
    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) #: L{WORD} e_magic.
    1586           self.e_cblp = datatypes.WORD(0) #: L{WORD} e_cblp.
    1587           self.e_cp = datatypes.WORD(0) #: L{WORD} e_cp.
    1588           self.e_crlc = datatypes.WORD(0) #: L{WORD} e_crlc.
    1589           self.e_cparhdr = datatypes.WORD(0) #: L{WORD} e_cparhdr.
    1590           self.e_minalloc = datatypes.WORD(0) #: L{WORD} e_minalloc.
    1591           self.e_maxalloc = datatypes.WORD(0) #: L{WORD} e_maxalloc.
    1592           self.e_ss = datatypes.WORD(0) #: L{WORD} e_ss.
    1593           self.e_sp = datatypes.WORD(0) #: L{WORD} e_sp.
    1594           self.e_csum = datatypes.WORD(0) #: L{WORD} e_csum.
    1595           self.e_ip = datatypes.WORD(0) #: L{WORD} e_ip.
    1596           self.e_cs = datatypes.WORD(0) #: L{WORD} e_cs.
    1597           self.e_lfarlc = datatypes.WORD(0) #: L{WORD} e_lfarlc.
    1598           self.e_ovno = datatypes.WORD(0) #: L{WORD} e_ovno.
    1599
    1600           self.e_res = datatypes.Array(datatypes.TYPE_WORD) #: L{Array} of type L{WORD} e_res.
    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) #: L{WORD} e_oemid.
    1604           self.e_oeminfo = datatypes.WORD(0) #: L{WORD} e_oeminfo.
    1605
    1606           self.e_res2 = datatypes.Array(datatypes.TYPE_WORD) #: L{Array} of type L{WORD} e_res2.
    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) #: L{DWORD} e_lfanew.
    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
    1617 -    def parse(readDataInstance):
    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
    1658 -    def getType(self):
    1659          """Returns L{consts.IMAGE_DOS_HEADER}."""
    1660          return consts.IMAGE_DOS_HEADER
    1661
    1662 -class NtHeaders(baseclasses.BaseStructClass):
    1663      """NtHeaders object."""
    1664 -    def __init__(self, shouldPack = True):
    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) #: L{DWORD} signature.
    1675          self.fileHeader = FileHeader() #: L{FileHeader} fileHeader.
    1676          self.optionalHeader = OptionalHeader() #: L{OptionalHeader} optionalHeader.
    1677
    1678 -    def __str__(self):
    1679          return str(self.signature) + str(self.fileHeader) + str(self.optionalHeader)
    1680
    1681      @staticmethod
    1682 -    def parse(readDataInstance):
    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
    1698 -    def getType(self):
    1699          """Returns L{consts.IMAGE_NT_HEADERS}."""
    1700          return consts.IMAGE_NT_HEADERS
    1701
    1702 -class FileHeader(baseclasses.BaseStructClass):
    1703      """FileHeader object."""
    1704 -    def __init__(self,  shouldPack = True):
    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) #: L{WORD} machine.
    1715          self.numberOfSections = datatypes.WORD(1) #: L{WORD} numberOfSections.
    1716          self.timeDateStamp = datatypes.DWORD(0) #: L{DWORD} timeDataStamp.
    1717          self.pointerToSymbolTable = datatypes.DWORD(0) #: L{DWORD} pointerToSymbolTable.
    1718          self.numberOfSymbols = datatypes.DWORD(0) #: L{DWORD} numberOfSymbols.
    1719          self.sizeOfOptionalHeader = datatypes.WORD(0xe0) #: L{WORD} sizeOfOptionalHeader.
    1720          self.characteristics = datatypes.WORD(consts.COMMON_CHARACTERISTICS) #: L{WORD} characteristics.
    1721
    1722          self._attrsList = ["machine","numberOfSections","timeDateStamp","pointerToSymbolTable","numberOfSymbols",\
    1723          "sizeOfOptionalHeader","characteristics"]
    1724
    1725      @staticmethod
    1726 -    def parse(readDataInstance):
    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
    1746 -    def getType(self):
    1747          """Returns L{consts.IMAGE_FILE_HEADER}."""
    1748          return consts.IMAGE_FILE_HEADER
    1749
    1750 -class OptionalHeader(baseclasses.BaseStructClass):
    1751      """OptionalHeader object."""
    1752 -    def __init__(self,  shouldPack = True):
    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) #: L{WORD} magic.
    1763          self.majorLinkerVersion = datatypes.BYTE(2) #: L{BYTE} majorLinkerVersion.
    1764          self.minorLinkerVersion = datatypes.BYTE(0x19) #: L{BYTE} minorLinkerVersion.
    1765          self.sizeOfCode = datatypes.DWORD(0x1000) #: L{DWORD} sizeOfCode.
    1766          self.sizeOfInitializedData = datatypes.DWORD(0) #: L{DWORD} sizeOfInitializedData.
    1767          self.sizeOfUninitializedData = datatypes.DWORD(0) #: L{DWORD} sizeOfUninitializedData.
    1768          self.addressOfEntryPoint = datatypes.DWORD(0x1000) #: L{DWORD} addressOfEntryPoint.
    1769          self.baseOfCode = datatypes.DWORD(0x1000) #: L{DWORD} baseOfCode.
    1770          self.baseOfData = datatypes.DWORD(0x1000) #: L{DWORD} baseOfData.
    1771          self.imageBase = datatypes.DWORD(0x400000) #: L{DWORD} imageBase.
    1772          self.sectionAlignment = datatypes.DWORD(0x1000) #: L{DWORD} sectionAlignment.
    1773          self.fileAlignment = datatypes.DWORD(0x200) #: L{DWORD} fileAligment.
    1774          self.majorOperatingSystemVersion = datatypes.WORD(5) #: L{WORD} majorOperatingSystemVersion.
    1775          self.minorOperatingSystemVersion = datatypes.WORD(0) #: L{WORD} minorOperatingSystemVersion.
    1776          self.majorImageVersion = datatypes.WORD(6) #: L{WORD} majorImageVersion.
    1777          self.minorImageVersion = datatypes.WORD(0) #: L{WORD} minorImageVersion.
    1778          self.majorSubsystemVersion = datatypes.WORD(5) #: L{WORD} majorSubsystemVersion.
    1779          self.minorSubsystemVersion = datatypes.WORD(0) #: L{WORD} minorSubsystemVersion.
    1780          self.win32VersionValue = datatypes.DWORD(0) #: L{DWORD} win32VersionValue.
    1781          self.sizeOfImage = datatypes.DWORD(0x2000) #: L{DWORD} sizeOfImage.
    1782          self.sizeOfHeaders = datatypes.DWORD(0x400) #: L{DWORD} sizeOfHeaders.
    1783          self.checksum = datatypes.DWORD(0) #: L{DWORD} checksum.
    1784          self.subsystem = datatypes.WORD(consts.WINDOWSGUI) #: L{WORD} subsystem.
    1785          self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE) #: L{WORD} dllCharacteristics.
    1786          self.sizeOfStackReserve = datatypes.DWORD(0x00100000) #: L{DWORD} sizeOfStackReserve.
    1787          self.sizeOfStackCommit = datatypes.DWORD(0x00004000) #: L{DWORD} sizeOfStackCommit.
    1788          self.sizeOfHeapReserve = datatypes.DWORD(00100000) #: L{DWORD} sizeOfHeapReserve.
    1789          self.sizeOfHeapCommit = datatypes.DWORD(0x1000) #: L{DWORD} sizeOfHeapCommit.
    1790          self.loaderFlags = datatypes.DWORD(0) #: L{DWORD} loaderFlags.
    1791          self.numberOfRvaAndSizes = datatypes.DWORD(0x10) #: L{DWORD} numberOfRvaAndSizes.
    1792          self.dataDirectory = datadirs.DataDirectory() #: L{DataDirectory} 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
    1802 -    def parse(readDataInstance):
    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
    1851 -    def getType(self):
    1852          """Returns L{consts.IMAGE_OPTIONAL_HEADER}."""
    1853          return consts.IMAGE_OPTIONAL_HEADER
    1854
    1855  # typedef struct _IMAGE_OPTIONAL_HEADER64 {
    1856  # WORD        Magic;
    1857  # BYTE        MajorLinkerVersion;
    1858  # BYTE        MinorLinkerVersion;
    1859  # DWORD       SizeOfCode;
    1860  # DWORD       SizeOfInitializedData;
    1861  # DWORD       SizeOfUninitializedData;
    1862  # DWORD       AddressOfEntryPoint;
    1863  # DWORD       BaseOfCode;
    1864  # ULONGLONG   ImageBase;
    1865  # DWORD       SectionAlignment;
    1866  # DWORD       FileAlignment;
    1867  # WORD        MajorOperatingSystemVersion;
    1868  # WORD        MinorOperatingSystemVersion;
    1869  # WORD        MajorImageVersion;
    1870  # WORD        MinorImageVersion;
    1871  # WORD        MajorSubsystemVersion;
    1872  # WORD        MinorSubsystemVersion;
    1873  # DWORD       Win32VersionValue;
    1874  # DWORD       SizeOfImage;
    1875  # DWORD       SizeOfHeaders;
    1876  # DWORD       CheckSum;
    1877  # WORD        Subsystem;
    1878  # WORD        DllCharacteristics;
    1879  # ULONGLONG   SizeOfStackReserve;
    1880  # ULONGLONG   SizeOfStackCommit;
    1881  # ULONGLONG   SizeOfHeapReserve;
    1882  # ULONGLONG   SizeOfHeapCommit;
    1883  # DWORD       LoaderFlags;
    1884  # DWORD       NumberOfRvaAndSizes;
    1885  # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    1886  # } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
    1887 -class OptionalHeader64(baseclasses.BaseStructClass):
    1888      """OptionalHeader64 object."""
    1889 -    def __init__(self,  shouldPack = True):
    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) #: L{WORD} magic.
    1900          self.majorLinkerVersion = datatypes.BYTE(2) #: L{BYTE} majorLinkerVersion.
    1901          self.minorLinkerVersion = datatypes.BYTE(0x19) #: L{BYTE} minorLinkerVersion.
    1902          self.sizeOfCode = datatypes.DWORD(0x1000) #: L{DWORD} sizeOfCode.
    1903          self.sizeOfInitializedData = datatypes.DWORD(0) #: L{DWORD} sizeOfInitializedData.
    1904          self.sizeOfUninitializedData = datatypes.DWORD(0) #: L{DWORD} sizeOfUninitializedData.
    1905          self.addressOfEntryPoint = datatypes.DWORD(0x1000) #: L{DWORD} addressOfEntryPoint.
    1906          self.baseOfCode = datatypes.DWORD(0x1000) #: L{DWORD} baseOfCode.
    1907          self.imageBase = datatypes.QWORD(0x400000) #: L{QWORD} imageBase.
    1908          self.sectionAlignment = datatypes.DWORD(0x1000) #: L{DWORD} sectionAlignment.
    1909          self.fileAlignment = datatypes.DWORD(0x200) #: L{DWORD} fileAligment.
    1910          self.majorOperatingSystemVersion = datatypes.WORD(5) #: L{WORD} majorOperatingSystemVersion.
    1911          self.minorOperatingSystemVersion = datatypes.WORD(0) #: L{WORD} minorOperatingSystemVersion.
    1912          self.majorImageVersion = datatypes.WORD(6) #: L{WORD} majorImageVersion.
    1913          self.minorImageVersion = datatypes.WORD(0) #: L{WORD} minorImageVersion.
    1914          self.majorSubsystemVersion = datatypes.WORD(5) #: L{WORD} majorSubsystemVersion.
    1915          self.minorSubsystemVersion = datatypes.WORD(0) #: L{WORD} minorSubsystemVersion.
    1916          self.win32VersionValue = datatypes.DWORD(0) #: L{DWORD} win32VersionValue.
    1917          self.sizeOfImage = datatypes.DWORD(0x2000) #: L{DWORD} sizeOfImage.
    1918          self.sizeOfHeaders = datatypes.DWORD(0x400) #: L{DWORD} sizeOfHeaders.
    1919          self.checksum = datatypes.DWORD(0) #: L{DWORD} checksum.
    1920          self.subsystem = datatypes.WORD(consts.WINDOWSGUI) #: L{WORD} subsystem.
    1921          self.dllCharacteristics = datatypes.WORD(consts.TERMINAL_SERVER_AWARE) #: L{WORD} dllCharacteristics.
    1922          self.sizeOfStackReserve = datatypes.QWORD(0x00100000) #: L{QWORD} sizeOfStackReserve.
    1923          self.sizeOfStackCommit = datatypes.QWORD(0x00004000) #: L{QWORD} sizeOfStackCommit.
    1924          self.sizeOfHeapReserve = datatypes.QWORD(00100000) #: L{QWORD} sizeOfHeapReserve.
    1925          self.sizeOfHeapCommit = datatypes.QWORD(0x1000) #: L{QWORD} sizeOfHeapCommit.
    1926          self.loaderFlags = datatypes.DWORD(0) #: L{DWORD}  loaderFlags.
    1927          self.numberOfRvaAndSizes = datatypes.DWORD(0x10) #: L{DWORD} numberOfRvaAndSizes.
    1928          self.dataDirectory = datadirs.DataDirectory() #: L{DataDirectory} 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
    1938 -    def parse(readDataInstance):
    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
    1986 -    def getType(self):
    1987          """Returns L{consts.IMAGE_OPTIONAL_HEADER64}."""
    1988          return consts.IMAGE_OPTIONAL_HEADER64
    1989
    1990 -class SectionHeader(baseclasses.BaseStructClass):
    1991      """SectionHeader object."""
    1992 -    def __init__(self,  shouldPack = True):
    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') #: L{String} name.
    2003          self.misc = datatypes.DWORD(0x1000) #: L{DWORD} misc.
    2004          self.virtualAddress = datatypes.DWORD(0x1000) #: L{DWORD} virtualAddress.
    2005          self.sizeOfRawData = datatypes.DWORD(0x200) #: L{DWORD} sizeOfRawData.
    2006          self.pointerToRawData = datatypes.DWORD(0x400) #: L{DWORD} pointerToRawData.
    2007          self.pointerToRelocations = datatypes.DWORD(0) #: L{DWORD} pointerToRelocations.
    2008          self.pointerToLineNumbers = datatypes.DWORD(0) #: L{DWORD} pointerToLineNumbers.
    2009          self.numberOfRelocations = datatypes.WORD(0) #: L{WORD} numberOfRelocations.
    2010          self.numberOfLinesNumbers = datatypes.WORD(0) #: L{WORD} numberOfLinesNumbers.
    2011          self.characteristics = datatypes.DWORD(0x60000000) #: L{DWORD} characteristics.
    2012
    2013          self._attrsList = ["name","misc","virtualAddress","sizeOfRawData","pointerToRawData","pointerToRelocations",\
    2014          "pointerToLineNumbers","numberOfRelocations","numberOfLinesNumbers","characteristics"]
    2015
    2016      @staticmethod
    2017 -    def parse(readDataInstance):
    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
    2040 -    def getType(self):
    2041          """Returns L{consts.IMAGE_SECTION_HEADER}."""
    2042          return consts.IMAGE_SECTION_HEADER
    2043
    2044 -class SectionHeaders(list):
    2045      """SectionHeaders object."""
    2046 -    def __init__(self, numberOfSectionHeaders = 1,  shouldPack = True):
    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
    2065 -    def __str__(self):
    2066          return "".join([str(x) for x in self if x.shouldPack])
    2067
    2068      @staticmethod
    2069 -    def parse(readDataInstance,  numberOfSectionHeaders):
    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
    2099 -class Sections(list):
    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
    2114 -    def __str__(self):
    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              # skip sections with pointerToRawData == 0. According to PECOFF, it contains uninitialized data
    2148              if sectionHdr.pointerToRawData.value:
    2149                  sData.append(readDataInstance.read(sectionHdr.sizeOfRawData.value))
    2150
    2151          return sData
    2152