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