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