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

# Source Code for Module pype32.datatypes

      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  Data types objects.
     33
     34  @group Strings:
     35      String, AlignedString
     36
     37  @group Native:
     38      BYTE, WORD, DWORD, QWORD, Array
     39  """
     40
     41  __revision__ = "$Id$"
     42
     43  __all__ = [
     44             "String",
     45             "AlignedString",
     46             "BYTE",
     47             "WORD",
     48             "DWORD",
     49             "QWORD",
     50             "Array",
     51             ]
     52
     53  import utils
     54  import excep
     55
     56  from baseclasses import DataTypeBaseClass
     57  from struct import pack,  unpack
     58
     59  TYPE_QWORD = 0xFECAFECA
     60  TYPE_DWORD = 0xDEADBEEF
     61  TYPE_WORD = 0xCAFECAFE
     62  TYPE_BYTE = 0xC00FEE
     63  TYPE_ARRAY = 0xFECA
     64  UNKNOWN_ARRAY_TYPE = 0xFFFF
     65  TYPE_STRING_HEAP_INDEX = 0x1000
     66
     67 -class String(object):
     68      """String object."""
     69 -    def __init__(self, value = "", shouldPack = True):
     70          """
     71          @type value: str
     72          @param value: the string to be built.
     73
     74          @type shouldPack: bool
     75          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
     76
     77          @todo: Add a UnicodeString class.
     78          """
     79          self.value = value
     80          self.shouldPack = shouldPack
     81
     82 -    def __str__(self):
     83          return self.value
     84
     85 -    def __len__(self):
     86          return len(self.value)
     87
     88 -    def sizeof(self):
     89          """
     90          Returns the size of the string.
     91          """
     92          return len(self)
     93
     94 -class AlignedString(String):
     95      """Aligned string object."""
     96 -    def __init__(self, value, shouldPack = True, align = 4):
     97          """
     98          This object represent an aligned ASCII string.
     99
    100          @type value: str
    101          @param value: The string to be built.
    102
    103          @type shouldPack: bool
    104          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
    105
    106          @type align: int
    107          @param align: (Optional) The alignment to be used. The default alignment is 4.
    108          """
    109          String.__init__(self,  value)
    110
    111          self.align = align
    112          self.value = value + "\x00" * (self.align - len(value) % self.align)
    113          self.shouldPack = shouldPack
    114
    115 -class Array(list):
    116      """Array object."""
    117 -    def __init__(self, arrayType,  shouldPack = True):
    118          """
    119          @type arrayType: int
    120          @param arrayType: The type of array to be built. This value can be C{TYPE_BYTE}, C{TYPE_WORD}, C{TYPE_DWORD} or C{TYPE_QWORD}.
    121
    122          @type shouldPack: bool
    123          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
    124
    125          @todo: Before to add an element to the array we must check if the type of that element is one we are expecting.
    126          """
    127          list.__init__(self)
    128
    129          self.arrayType = arrayType
    130          self.shouldPack = shouldPack
    131
    132          if not self.arrayType in [TYPE_BYTE,  TYPE_WORD,  TYPE_DWORD,  TYPE_QWORD]:
    133              raise TypeError("Couldn\'t create an Array of type %r" % self.arrayType)
    134
    135 -    def __str__(self):
    136          return ''.join([str(x) for x in self])
    137
    138 -    def sizeof(self):
    139          """
    140          Returns the size of the array.
    141          """
    142          return len(self)
    143
    144      @staticmethod
    145 -    def parse(readDataInstance,  arrayType,  arrayLength):
    146          """
    147          Returns a new L{Array} object.
    148
    149          @type readDataInstance: L{ReadData}
    150          @param readDataInstance: The L{ReadData} object containing the array data.
    151
    152          @type arrayType: int
    153          @param arrayType: The type of L{Array} to be built.
    154
    155          @type arrayLength: int
    156          @param arrayLength: The length of the array passed as an argument.
    157
    158          @rtype: L{Array}
    159          @return: New L{Array} object.
    160          """
    161          newArray = Array(arrayType)
    162
    163          dataLength = len(readDataInstance)
    164
    165          if arrayType is TYPE_DWORD:
    166              toRead = arrayLength * 4
    167              if dataLength >= toRead:
    168                  for i in range(arrayLength):
    169                      newArray.append(DWORD(readDataInstance.readDword()))
    170              else:
    171                  raise excep.DataLengthException("Not enough bytes to read.")
    172
    173          elif arrayType is TYPE_WORD:
    174              toRead = arrayLength * 2
    175              if dataLength >= toRead:
    176                  for i in range(arrayLength):
    177                      newArray.append(DWORD(readDataInstance.readWord()))
    178              else:
    179                  raise excep.DataLengthException("Not enough bytes to read.")
    180
    181          elif arrayType is TYPE_QWORD:
    182              toRead = arrayLength * 8
    183              if dataLength >= toRead:
    184                  for i in range(arrayLength):
    185                      newArray.append(QWORD(readDataInstance.readQword()))
    186              else:
    187                  raise excep.DataLengthException("Not enough bytes to read.")
    188
    189          elif arrayType is TYPE_BYTE:
    190              for i in range(arrayLength):
    191                  newArray.append(BYTE(readDataInstance.readByte()))
    192
    193          else:
    194              raise excep.ArrayTypeException("Could\'t create an array of type %d" % arrayType)
    195
    196          return newArray
    197
    198 -    def getType(self):
    199          """
    200          Returns an integer value identifying the type of object.
    201          """
    202          return TYPE_ARRAY
    203
    204 -class BYTE(DataTypeBaseClass):
    205      """Byte object."""
    206 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    207          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    208
    209 -    def __str__(self):
    210          return pack(self.endianness  + ("b" if self.signed else "B"),  self.value)
    211
    212 -    def __len__(self):
    213          return len(str(self))
    214
    215 -    def getType(self):
    216          """
    217          Returns L{TYPE_BYTE}.
    218          """
    219          return TYPE_BYTE
    220
    221 -    def sizeof(self):
    222          """
    223          Returns the size of L{BYTE}.
    224          """
    225          return len(self)
    226
    227      @staticmethod
    228 -    def parse(readDataInstance):
    229          """
    230          Returns a new L{BYTE} object.
    231
    232          @type readDataInstance: L{ReadData}
    233          @param readDataInstance: A L{ReadData} object with the corresponding data to generate a new L{BYTE} object.
    234
    235          @rtype: L{BYTE}
    236          @return: A new L{BYTE} object.
    237          """
    238          return BYTE(readDataInstance.readByte())
    239
    240 -class WORD(DataTypeBaseClass):
    241      """Word object."""
    242 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    243          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    244
    245 -    def __str__(self):
    246          return pack(self.endianness + ("h" if self.signed else "H"),  self.value)
    247
    248 -    def __len__(self):
    249          return len(str(self))
    250
    251 -    def getType(self):
    252          """
    253          Returns L{TYPE_WORD}.
    254          """
    255          return TYPE_WORD
    256
    257 -    def sizeof(self):
    258          """Returns the size of L{WORD}."""
    259          return len(self)
    260
    261      @staticmethod
    262 -    def parse(readDataInstance):
    263          """
    264          Returns a new L{WORD} object.
    265
    266          @type readDataInstance: L{ReadData}
    267          @param readDataInstance: A L{ReadData} object containing the necessary data to build a new L{WORD} object.
    268
    269          @rtype: L{WORD}
    270          @return: A new L{WORD} object.
    271          """
    272          return WORD(readDataInstance.readWord())
    273
    274 -class DWORD(DataTypeBaseClass):
    275      """Dword object."""
    276 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    277          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    278
    279 -    def __str__(self):
    280          return pack(self.endianness  + ("l" if self.signed else "L"),  self.value)
    281
    282 -    def __len__(self):
    283          return len(str(self))
    284
    285 -    def getType(self):
    286          """Returns L{TYPE_DWORD}."""
    287          return TYPE_DWORD
    288
    289 -    def sizeof(self):
    290          """Returns the size of L{DWORD}."""
    291          return len(self)
    292
    293      @staticmethod
    294 -    def parse(readDataInstance):
    295          """
    296          Returns a new L{DWORD} object.
    297
    298          @type readDataInstance: L{ReadData}
    299          @param readDataInstance: A L{ReadData} object with the necessary data to build a new L{DWORD} object.
    300
    301          @rtype: L{DWORD}
    302          @return: A new L{DWORD} object.
    303          """
    304          return DWORD(readDataInstance.readDword())
    305
    306 -class QWORD(DataTypeBaseClass):
    307      """Qword object."""
    308 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    309          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    310
    311 -    def __str__(self):
    312          return pack(self.endianness + ("q" if self.signed else "Q"),  self.value)
    313
    314 -    def __len__(self):
    315          return len(str(self))
    316
    317 -    def getType(self):
    318          """Returns L{TYPE_QWORD}."""
    319          return TYPE_QWORD
    320
    321 -    def sizeof(self):
    322          """Returns the size of L{QWORD}."""
    323          return len(self)
    324
    325      @staticmethod
    326 -    def parse(readDataInstance):
    327          """
    328          Returns a new L{QWORD} object.
    329
    330          @type readDataInstance: L{ReadData}
    331          @param readDataInstance: A L{ReadData} object with the necessary data to build a new L{QWORD} object.
    332
    333          @rtype: L{QWORD}
    334          @return: A new L{QWORD} object.
    335          """
    336          return QWORD(readDataInstance.readQword())
    337