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