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