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

Source Code for Module pype32.pype32

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