Package rekall :: Package plugins :: Package renderers :: Module json_storage
[frames] | no frames]

Source Code for Module rekall.plugins.renderers.json_storage

  1  # Rekall Memory Forensics 
  2  # Copyright 2014 Google Inc. All Rights Reserved. 
  3  # 
  4  # Authors: 
  5  # Michael Cohen <scudette@google.com> 
  6  # 
  7  # This program is free software; you can redistribute it and/or modify 
  8  # it under the terms of the GNU General Public License as published by 
  9  # the Free Software Foundation; either version 2 of the License, or (at 
 10  # your option) any later version. 
 11  # 
 12  # This program is distributed in the hope that it will be useful, but 
 13  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 15  # General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU General Public License 
 18  # along with this program; if not, write to the Free Software 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 20  # 
 21   
 22  """This file implements ObjectRenderers for the JsonRenderer. 
 23   
 24  The JsonRenderer aims to serialize and recreate objects exactly at they were 
 25  upon unserializing them. This means that the environment loading the serialized 
 26  data must have access to all the necessary files (i.e. the complete memory image 
 27  file). 
 28   
 29  For example consider an _EPROCESS() instance. In memory, python merely stores 
 30  the following items in the object: 
 31   
 32  - obj_offset: The offset in the address space. 
 33  - obj_profile: The profile this object came from. 
 34  - obj_vm: The address space the object will be read from. 
 35   
 36  When the object is read, the address space is read at obj_offset, the data is 
 37  decoded and possibly other members are created using the profile. We do not know 
 38  the value of the object without reading it from the image. 
 39   
 40  Contrast this with the WebConsoleRenderer which needs to be deserialized in an 
 41  environment which does not have access to the original image. In this case we 
 42  must store all kinds of additional metadata about each object, since the decoder 
 43  is unable to directly get this information. 
 44   
 45  Example: 
 46   
 47  zeus2x4.vmem.E01 23:46:28> x = session.profile._EPROCESS(0x81e8a368) 
 48  zeus2x4.vmem.E01 23:46:32> encoder = json_renderer.JsonEncoder() 
 49  zeus2x4.vmem.E01 23:46:34> print encoder.Encode(x) 
 50  {'offset': 2179507048, 
 51   'profile': ('*', u'nt/GUID/1B2D0DFE2FB942758D615C901BE046922'), 
 52   'type': u'_EPROCESS,_EPROCESS,Struct,BaseAddressComparisonMixIn,BaseObject', 
 53   'type_name': ('*', u'_EPROCESS'), 
 54   'vm': {'base': {'filename': ('*', 
 55      u'/home/scudette/images/zeus2x4.vmem.E01'), 
 56     'type': u'EWFAddressSpace,CachingAddressSpaceMixIn,FDAddressSpace,BaseAddressSpace'}, 
 57    'dtb': 233472, 
 58    'type': u'IA32PagedMemory,PagedReader,BaseAddressSpace'}} 
 59   
 60  zeus2x4.vmem.E01 23:47:25> decoder = json_renderer.JsonDecoder(session=session) 
 61  zeus2x4.vmem.E01 23:48:10> print decoder.Decode(encoder.Encode(x)).ImageFileName 
 62  alg.exe 
 63   
 64  Since the decoder is able to exactly recreate the original object, this object 
 65  can then be subsequently used to dereference the memory image - we can recover 
 66  the _EPROCESS.ImageFileName attribute and print the process name - even though 
 67  the actual name was never encoded. 
 68  """ 
 69  import arrow 
 70   
 71  from rekall import addrspace 
 72  from rekall import obj 
 73  from rekall import session 
 74  from rekall.ui import json_renderer 
 75  from rekall_lib import utils 
76 77 78 -class BaseAddressSpaceObjectRenderer(json_renderer.StateBasedObjectRenderer):
79 renders_type = "BaseAddressSpace" 80 81 @json_renderer.CacheableState
82 - def DecodeFromJsonSafe(self, value, options):
83 value = super(BaseAddressSpaceObjectRenderer, 84 self).DecodeFromJsonSafe(value, options) 85 86 cls_name = value.pop("cls") 87 cls = addrspace.BaseAddressSpace.classes[cls_name] 88 89 if value["base"] == "PhysicalAS": 90 value["base"] = (self.session.physical_address_space or 91 self.session.plugins.load_as().GetPhysicalAddressSpace()) 92 93 return cls(session=self.session, **value)
94
95 - def GetState(self, item, **_):
96 result = dict(cls=unicode(item.__class__.__name__)) 97 if item.base is not item: 98 result["base"] = item.base 99 100 if item.base is self.renderer.session.physical_address_space: 101 result["base"] = "PhysicalAS" 102 103 return result
104
105 106 -class FileAddressSpaceObjectRenderer(BaseAddressSpaceObjectRenderer):
107 renders_type = "FileAddressSpace" 108
109 - def GetState(self, item, **options):
110 state = super(FileAddressSpaceObjectRenderer, self).GetState( 111 item, **options) 112 state["filename"] = utils.SmartUnicode(item.fname) 113 114 return state
115
116 117 -class AttributeDictObjectRenderer(json_renderer.StateBasedObjectRenderer):
118 renders_type = "AttributeDict" 119
120 - def GetState(self, item, **_):
121 return dict(data=dict(item))
122
123 - def DecodeFromJsonSafe(self, state, options):
124 state = super(AttributeDictObjectRenderer, self).DecodeFromJsonSafe( 125 state, options) 126 127 return utils.AttributeDict(state.get("data", {}))
128
129 130 -class SlottedObjectObjectRenderer(json_renderer.StateBasedObjectRenderer):
131 renders_type = "SlottedObject" 132
133 - def GetState(self, item, **_):
134 return dict((k, getattr(item, k)) 135 for k in item.__slots__ if not k.startswith("_"))
136
137 - def DecodeFromJsonSafe(self, state, options):
138 state = super(SlottedObjectObjectRenderer, self).DecodeFromJsonSafe( 139 state, options) 140 141 # Deliberately do not go through the constructor. Use __new__ directly 142 # so we can restore object state by assigning to the slots. 143 result = utils.SlottedObject.__new__(utils.SlottedObject) 144 for k, v in state.iteritems(): 145 setattr(result, k, v) 146 147 return result
148
149 150 -class IA32PagedMemoryObjectRenderer(BaseAddressSpaceObjectRenderer):
151 renders_type = "IA32PagedMemory" 152
153 - def GetState(self, item, **options):
154 state = super(IA32PagedMemoryObjectRenderer, self).GetState( 155 item, **options) 156 state["dtb"] = item.dtb 157 158 return state
159
160 161 -class SessionObjectRenderer(json_renderer.StateBasedObjectRenderer):
162 renders_type = "Session" 163
164 - def GetState(self, item, **options):
165 state = super(SessionObjectRenderer, self).GetState(item, **options) 166 state["session_id"] = item.session_id 167 state_dict = state["state"] = {} 168 for parameter, type in item.SERIALIZABLE_STATE_PARAMETERS: 169 value = None 170 if item.HasParameter(parameter): 171 value = item.GetParameter(parameter) 172 173 state_dict[parameter] = (value, type) 174 175 return state
176 177 @json_renderer.CacheableState
178 - def DecodeFromJsonSafe(self, state, options):
179 state = super(SessionObjectRenderer, self).DecodeFromJsonSafe( 180 state, options) 181 182 mro = state["mro"].split(":") 183 result = session.Session.classes[mro[0]]() 184 with result: 185 for k, v in state["state"].iteritems(): 186 result.SetParameter(k, v[0]) 187 188 return result
189
190 191 -class ProfileObjectRenderer(json_renderer.StateBasedObjectRenderer):
192 renders_type = "Profile" 193
194 - def GetState(self, item, **_):
195 return dict(name=item.name)
196 197 @json_renderer.CacheableState
198 - def DecodeFromJsonSafe(self, state, options):
199 state = super(ProfileObjectRenderer, self).DecodeFromJsonSafe( 200 state, options) 201 202 result = self.session.LoadProfile(state["name"]) 203 if result == None: 204 return None 205 206 return result
207
208 209 -class SetObjectRenderer(json_renderer.StateBasedObjectRenderer):
210 """Encode a python set().""" 211 renders_type = ("set", "frozenset") 212
213 - def GetState(self, item, **_):
214 return dict(data=list(item))
215
216 - def DecodeFromJsonSafe(self, state, options):
217 return set(state["data"])
218
219 220 -class NoneObjectRenderer(json_renderer.StateBasedObjectRenderer):
221 """Encode a None Object.""" 222 renders_type = "NoneObject" 223
224 - def GetState(self, item, **_):
225 return dict(reason=item.FormatReason())
226
227 - def DecodeFromJsonSafe(self, state, options):
228 state = super(NoneObjectRenderer, self).DecodeFromJsonSafe( 229 state, options) 230 231 return obj.NoneObject(state.get("reason"))
232
233 234 -class UnixTimestampJsonObjectRenderer(json_renderer.StateBasedObjectRenderer):
235 renders_type = "UnixTimeStamp" 236
237 - def Summary(self, item, **_):
238 return item.get("string_value", "")
239
240 - def GetState(self, item, **_):
241 return dict(epoch=item.v(), 242 string_value=unicode(item))
243
244 - def DecodeFromJsonSafe(self, state, options):
245 return self.session.profile.UnixTimeStamp(value=state.get("epoch", 0))
246
247 248 -class ArrowObjectRenderer(json_renderer.StateBasedObjectRenderer):
249 renders_type = "Arrow" 250
251 - def GetState(self, item, **_):
252 return dict(epoch=item.float_timestamp, 253 string_value=item.isoformat())
254
255 - def DecodeFromJsonSafe(self, state, options):
256 return arrow.Arrow.fromtimestamp(state["epoch"])
257
258 259 -class PointerObjectRenderer(json_renderer.BaseObjectRenderer):
260 """Encode a Pointer.""" 261 renders_type = "Pointer" 262
263 - def GetState(self, item, **options):
264 state = super(PointerObjectRenderer, self).GetState(item, **options) 265 state["target"] = item.target 266 state["target_args"] = item.target_args 267 268 return state
269
270 271 -class ArrayObjectRenderer(PointerObjectRenderer):
272 renders_type = "Array" 273
274 - def GetState(self, item, **options):
275 state = super(ArrayObjectRenderer, self).GetState(item, **options) 276 state["count"] = item.count 277 278 return state
279
280 281 -class JsonAttributedStringRenderer(json_renderer.StateBasedObjectRenderer):
282 """Encode an attributed string.""" 283 renders_type = "AttributedString" 284
285 - def GetState(self, item, **options):
286 state = super(JsonAttributedStringRenderer, self).GetState( 287 item, **options) 288 289 state["value"] = utils.SmartUnicode(item.value) 290 state["highlights"] = item.highlights 291 return state
292
293 294 -class JsonHexdumpRenderer(json_renderer.StateBasedObjectRenderer):
295 """Encode a hex dumped string.""" 296 renders_type = "HexDumpedString" 297
298 - def GetState(self, item, **options):
299 state = super(JsonHexdumpRenderer, self).GetState(item, **options) 300 state["value"] = unicode(item.value.encode("hex")) 301 state["highlights"] = item.highlights 302 303 return state
304
305 306 -class JsonInstructionRenderer(json_renderer.StateBasedObjectRenderer):
307 renders_type = "Instruction" 308
309 - def GetState(self, item, **_):
310 return dict(value=unicode(item))
311
312 313 -class JsonEnumerationRenderer(json_renderer.StateBasedObjectRenderer):
314 """For enumerations store both their value and the enum name.""" 315 renders_type = ["Enumeration", "BitField"] 316
317 - def GetState(self, item, **_):
318 return dict(enum=unicode(item), 319 value=int(item))
320
321 - def Summary(self, item, **_):
322 return item.get("enum", "")
323
324 325 -class JsonFormattedAddress(json_renderer.StateBasedObjectRenderer):
326 renders_type = ["FormattedAddress"] 327
328 - def GetState(self, item, **_):
329 return dict(address=item.address, 330 symbol=utils.SmartStr(item))
331
332 - def Summary(self, item, **_):
333 return utils.SmartStr(item)
334
335 336 -class JsonRangedCollectionObjectRenderer( 337 json_renderer.StateBasedObjectRenderer):
338 """Serialize RangedCollection objects.""" 339 renders_type = ["RangedCollection"] 340
341 - def EncodeToJsonSafe(self, item, **_):
342 # Optimized this since we know we do not need to escape any item since 343 # this is a simple list of integers. 344 encoded = [] 345 for start, end, data in item: 346 encoded.append((start, end, self._encode_value(data))) 347 348 return dict(data=encoded, mro="RangedCollection")
349
350 - def DecodeFromJsonSafe(self, state, options):
351 result = utils.RangedCollection() 352 for start, end, encoded_data in state["data"]: 353 result.insert( 354 start, end, self._decode_value(encoded_data, options)) 355 356 return result
357