1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21  """This module implements base object renderers.""" 
 22   
 23  from rekall.ui import renderer as renderer_module 
 24  from rekall.ui import text 
 25  from rekall_lib import utils 
 26   
 27   
 28 -class PluginObjectTextRenderer(text.TextObjectRenderer): 
  29      renders_type = "Plugin" 
 30   
 31 -    def render_full(self, target, **_): 
  32          return text.Cell(repr(target)) 
  33   
 34 -    def render_compact(self, target, **_): 
   36   
 37   
 38 -class BaseObjectTextRenderer(text.TextObjectRenderer): 
  39      renders_type = "BaseObject" 
 40   
 41 -    def render_address(self, target, **options): 
  42          return text.Cell( 
 43              self.format_address(target.obj_offset, **options) 
 44          ) 
  45   
 46 -    def render_full(self, target, **options): 
  47          result = text.Cell(unicode(target.v()), **options) 
 48          return result 
  49   
 50 -    def render_value(self, target, **_): 
  51          return text.Cell(unicode(target.v())) 
   52   
 53   
 54 -class StringTextRenderer(BaseObjectTextRenderer): 
  55      renders_type = "String" 
 56   
 57 -    def render_full(self, target, **_): 
  58          return text.Cell( 
 59              utils.SmartUnicode(target).split("\x00")[0] or u"") 
  60   
 61      render_value = render_full 
 62      render_compact = render_full 
  63   
 64   
 65 -class NoneObjectTextRenderer(BaseObjectTextRenderer): 
  66      """NoneObjects will be rendered with a single dash '-'.""" 
 67      renders_type = "NoneObject" 
 68   
 69 -    def render_row(self, target, **_): 
   71   
 72   
 73 -class NoneTextRenderer(NoneObjectTextRenderer): 
  74      renders_type = "NoneType" 
  75   
 76   
 88   
 89   
103   
104   
105 -class PythonBoolTextRenderer(text.TextObjectRenderer): 
 106      renders_type = "bool" 
107   
108 -    def render_full(self, target, **_): 
 109          color = "GREEN" if target else "RED" 
110          return text.Cell( 
111              value=unicode(target), 
112              highlights=[(0, -1, color, None)]) 
 113   
114      render_value = render_full 
115      render_compact = render_full 
 116   
117   
118 -class NativeTypeTextRenderer(BaseObjectTextRenderer): 
 119      renders_type = "NativeType" 
120   
121 -    def render_address(self, target, width=None, **options): 
 122          return text.Cell( 
123              self.format_address(target.v(), **options), 
124              width=width) 
  125   
126   
127 -class BaseBoolTextRenderer(PythonBoolTextRenderer): 
 128      renders_type = "Bool" 
129   
130 -    def render_row(self, target, **kwargs): 
 131          return super(BaseBoolTextRenderer, self).render_row(bool(target), 
132                                                              **kwargs) 
  133   
134   
135 -class FlagsTextRenderer(BaseObjectTextRenderer): 
 136      renders_type = "Flags" 
137   
138 -    def render_full(self, target, **_): 
 139          flags = [] 
140          value = target.v() 
141          for k, v in sorted(target.maskmap.items()): 
142              if value & v: 
143                  flags.append(k) 
144   
145          return text.Cell(u', '.join(flags)) 
 146   
147 -    def render_value(self, target, **_): 
 148          return text.Cell(unicode(self.v())) 
 149   
150 -    def render_compact(self, target, **_): 
 151          lines = self.render_full(target).lines 
152          if not lines: 
153              return text.Cell("-") 
154   
155          elided = lines[0] 
156          if len(elided) > 40: 
157              elided = elided[:39] + u"…" 
158   
159          return text.Cell(elided) 
  160   
161   
162 -class EnumerationTextRenderer(BaseObjectTextRenderer): 
 163      renders_type = "Enumeration" 
164   
165 -    def render_full(self, target, **_): 
 166          value = target.v() 
167          name = target.choices.get(utils.SmartStr(value), target.default) or ( 
168              u"UNKNOWN (%s)" % utils.SmartUnicode(value)) 
169   
170          return text.Cell(name) 
 171   
172      render_compact = render_full 
 173   
174   
175 -class DatetimeTextRenderer(text.TextObjectRenderer): 
 176      renders_type = "datetime" 
177   
178 -    def render_row(self, target, **_): 
 179          return text.Cell(target.strftime("%Y-%m-%d %H:%M:%S%z")) 
  180   
181   
182 -class PointerTextRenderer(NativeTypeTextRenderer): 
 183      renders_type = "Pointer" 
184   
185 -    def render_value(self, *args, **kwargs): 
 186          return self.render_address(*args, **kwargs) 
 187   
188 -    def render_full(self, target, **_): 
 189          target_obj = target.deref() 
190          if target_obj == None: 
191              return text.Cell("-") 
192   
193          delegate_cls = renderer_module.ObjectRenderer.ForTarget( 
194              target_obj, renderer=self.renderer) 
195   
196          return delegate_cls(session=self.session, 
197                              renderer=self.renderer).render_full(target_obj) 
 198   
199 -    def render_compact(self, target, **options): 
 200          return text.Cell( 
201              "(%s *) %s" % ( 
202                  target.target, 
203                  self.format_address(target.v(), **options)) 
204          ) 
  205   
206   
208      """Renders a list of other objects.""" 
209      renders_type = ("list", "set", "frozenset", "ListRepetition") 
210   
221   
 229   
230   
232      """Special handling for named tuples.""" 
233      renders_type = ("tuple", ) 
234   
236          if not target: 
237              return None 
238   
239          if hasattr(target, "_fields"): 
240              new_target = {} 
241              for field in target._fields: 
242                  new_target[field] = getattr(target, field) 
243   
244              object_renderer = self.ForTarget(new_target, self.renderer)( 
245                  session=self.session, renderer=self.renderer) 
246   
247              return object_renderer.render_row(new_target, **options) 
248   
249          result = [] 
250          width = options.pop("width", None) 
251          result = [] 
252          for item in target: 
253              object_renderer = self.ForTarget(item, self.renderer)( 
254                  session=self.session, renderer=self.renderer) 
255   
256              options["wrap"] = False 
257              cell = object_renderer.render_row(item, **options) 
258              result.append("\\n".join(cell.lines).strip()) 
259   
260          return text.Cell(", ".join(result), width=width) 
  261   
262   
263 -class VoidTextRenderer(PointerTextRenderer): 
 264      renders_type = "Void" 
265   
266 -    def render_full(self, target, **options): 
 267          return text.Cell( 
268              "(void *) %s" % self.format_address(target.v(), **options)) 
 269   
270      render_compact = render_full 
 271   
272   
273 -class FunctionTextRenderer(BaseObjectTextRenderer): 
 274      renders_type = "Function" 
275   
276 -    def render_full(self, target, width=None, **_): 
 277          table = text.TextTable( 
278              columns=[ 
279                  dict(name="Address", style="address"), 
280                  dict(name="OpCode", width=16), 
281                  dict(name="Op", width=width) 
282              ], 
283              renderer=self.renderer, 
284              session=self.session) 
285   
286          result = [] 
287          for instruction in target.disassemble(): 
288              result.append(unicode(table.get_row( 
289                  instruction.address, instruction.hexbytes, instruction.text))) 
290   
291          return text.Cell("\n".join(result)) 
 292   
293 -    def render_compact(self, target, **options): 
 294          return text.Cell(self.format_address(target.obj_offset, **options)) 
 295   
296      render_value = render_compact 
 297   
298   
299 -class StructTextRenderer(text.TextObjectRenderer): 
 300      renders_type = "Struct" 
301      DEFAULT_STYLE = "compact" 
302      renderers = ["TextRenderer", "TestRenderer"] 
303      COLUMNS = None 
304      table = None 
305   
306 -    def __init__(self, *args, **kwargs): 
 307          self.columns = kwargs.pop("columns", self.COLUMNS) 
308   
309          super(StructTextRenderer, self).__init__(*args, **kwargs) 
310   
311          if self.columns: 
312              self.table = text.TextTable( 
313                  columns=self.columns, 
314                  renderer=self.renderer, 
315                  session=self.session) 
 316   
317 -    def render_full(self, target, **_): 
 318          """Full render of a struct outputs every field.""" 
319          result = repr(target) + "\n" 
320          width_name = 0 
321   
322          fields = [] 
323           
324          for k in target.members: 
325              width_name = max(width_name, len(k)) 
326              obj = getattr(target, k) 
327              if obj == None: 
328                  obj = target.m(k) 
329   
330              fields.append( 
331                  (getattr(obj, "obj_offset", target.obj_offset) - 
332                   target.obj_offset, k, utils.SmartUnicode(repr(obj)))) 
333   
334          fields.sort() 
335   
336          result = result + u"\n".join( 
337              [u"  0x%02X %s%s %s" % (offset, k, " " * (width_name - len(k)), v) 
338               for offset, k, v in fields]) + "\n" 
339   
340          return text.Cell(result) 
 341   
343          style = kwargs.get("style", self.DEFAULT_STYLE) 
344   
345          if style == "compact" and self.table: 
346              return self.table.render_header() 
347          else: 
348              return super(StructTextRenderer, self).render_header(**kwargs) 
 349   
350 -    def render_compact(self, target, **_): 
 351          """Compact render outputs only a few select columns, or repr.""" 
352          if not self.table: 
353              return self.render_repr(target) 
354   
355          values = [] 
356          for column in self.columns: 
357              name = column.get("name") 
358              if not name: 
359                  raise ValueError( 
360                      "Column spec %r doesn't specify 'name'." % column) 
361   
362              values.append(getattr(target, name)) 
363   
364          return self.table.get_row(*values) 
 365   
366 -    def render_repr(self, target, **_): 
 367          """Explicitly just render the repr.""" 
368          return text.Cell(repr(target)) 
  369   
370   
371 -class AttributeDictTextRenderer(text.TextObjectRenderer): 
 372      renders_type = "dict" 
373      renderers = ["TextRenderer", "TestRenderer"] 
374   
375 -    def __init__(self, *args, **kwargs): 
 376          """We make a sub table for key, values.""" 
377          super(AttributeDictTextRenderer, self).__init__(*args, **kwargs) 
378          self.table = text.TextTable( 
379              columns=[ 
380                  dict(name="Key"), 
381                  dict(name="Value"), 
382              ], 
383              auto_widths=True, 
384              renderer=self.renderer, 
385              session=self.session) 
 386   
387 -    def render_row(self, item, **options): 
 388          result = [] 
389          for key, value in sorted(item.iteritems()): 
390              result.append(self.table.get_row(key, value)) 
391   
392          return text.StackedCell(*result) 
  393   
394   
395 -class HexIntegerTextRenderer(text.TextObjectRenderer): 
 396      renders_type = "HexInteger" 
397      renderers = ["TextRenderer", "TestRenderer"] 
398   
399 -    def render_row(self, item, **options): 
 400          return text.Cell(hex(item), align="r") 
  401   
402   
403 -class TextHexdumpRenderer(text.TextObjectRenderer): 
 404      renders_type = "HexDumpedString" 
405      renderers = ["TextRenderer", "TestRenderer"] 
406   
407 -    def render_row(self, item, hex_width=None, **options): 
 408          if hex_width is None: 
409              hex_width = (item.options.get("hex_width") or 
410                           self.session.GetParameter("hexdump_width", 8)) 
411   
412          data = item.value 
413          highlights = item.highlights or [] 
414          hex_highlights = [] 
415          for x, y, f, b in highlights: 
416              hex_highlights.append((3 * x, 3 * y, f, b)) 
417   
418          hexcell = text.Cell( 
419              width=hex_width * 3, highlights=hex_highlights, 
420              colorizer=self.renderer.colorizer) 
421          datacell = text.Cell( 
422              width=hex_width, highlights=highlights, 
423              colorizer=self.renderer.colorizer) 
424   
425          for _, hexdata, translated_data in utils.Hexdump(data, width=hex_width): 
426              hexcell.append_line(hexdata) 
427              datacell.append_line("".join(translated_data)) 
428   
429          return text.JoinedCell(hexcell, datacell) 
  430