1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
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
84
86 return len(self.value)
87
89 """
90 Returns the size of the string.
91 """
92 return len(self)
93
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
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
136 return ''.join([str(x) for x in self])
137
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
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):
208
210 return pack(self.endianness + ("b" if self.signed else "B"), self.value)
211
213 return len(str(self))
214
216 """
217 Returns L{TYPE_BYTE}.
218 """
219 return TYPE_BYTE
220
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):
244
246 return pack(self.endianness + ("h" if self.signed else "H"), self.value)
247
249 return len(str(self))
250
252 """
253 Returns L{TYPE_WORD}.
254 """
255 return TYPE_WORD
256
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):
278
280 return pack(self.endianness + ("l" if self.signed else "L"), self.value)
281
283 return len(str(self))
284
286 """Returns L{TYPE_DWORD}."""
287 return TYPE_DWORD
288
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):
310
312 return pack(self.endianness + ("q" if self.signed else "Q"), self.value)
313
315 return len(str(self))
316
318 """Returns L{TYPE_QWORD}."""
319 return TYPE_QWORD
320
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