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