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

Source Code for Module rekall.plugins.renderers.xls

  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 an xls renderer based on the openpyxl project. 
 23   
 24  We produce xls (Excel spreadsheet files) with the output from Rekall plugins. 
 25  """ 
 26  import time 
 27  import openpyxl 
 28   
 29  from openpyxl import styles 
 30  from openpyxl.styles import colors 
 31  from openpyxl.styles import fills 
 32   
 33  from rekall import utils 
 34  from rekall.ui import renderer 
 35  from rekall.ui import text 
 36   
 37  # pylint: disable=unexpected-keyword-arg,no-value-for-parameter 
 38  # pylint: disable=redefined-outer-name 
 39   
 40  HEADER_STYLE = styles.Style(font=styles.Font(bold=True)) 
 41  SECTION_STYLE = styles.Style( 
 42      fill=styles.PatternFill( 
 43          fill_type=fills.FILL_SOLID, start_color=styles.Color(colors.RED))) 
 44  FORMAT_STYLE = styles.Style( 
 45      alignment=styles.Alignment(vertical="top", wrap_text=False)) 
 46   
 47   
48 -class XLSObjectRenderer(renderer.ObjectRenderer):
49 """By default the XLS renderer delegates to the text renderer.""" 50 renders_type = "object" 51 renderers = ["XLSRenderer"] 52 53 STYLE = None 54
55 - def _GetDelegateObjectRenderer(self, item):
56 return self.ForTarget(item, "TextRenderer")( 57 session=self.session, renderer=self.renderer.delegate_text_renderer)
58
59 - def RenderHeader(self, worksheet, column):
60 cell = worksheet.cell( 61 row=worksheet.current_row, column=worksheet.current_column) 62 63 cell.value = column.name 64 cell.style = HEADER_STYLE 65 66 # Advance the pointer by 1 cell. 67 worksheet.current_column += 1
68
69 - def RenderCell(self, value, worksheet, **options):
70 # By default just render a single value into the current cell. 71 cell = worksheet.cell( 72 row=worksheet.current_row, column=worksheet.current_column) 73 cell.value = self.GetData(value, **options) 74 if self.STYLE: 75 cell.style = self.STYLE 76 77 # Advance the pointer by 1 cell. 78 worksheet.current_column += 1
79
80 - def GetData(self, value, **options):
81 if isinstance(value, (int, float, long)): 82 return value 83 84 return unicode(self._GetDelegateObjectRenderer(value).render_row( 85 value, **options))
86 87
88 -class XLSColumn(text.TextColumn):
89
90 - def __init__(self, type=None, table=None, renderer=None, session=None, 91 **options):
92 super(XLSColumn, self).__init__(table=table, renderer=renderer, 93 session=session, **options) 94 95 if type: 96 self.object_renderer = self.renderer.get_object_renderer( 97 type=type, target_renderer="XLSRenderer", **options)
98 99
100 -class XLSTable(text.TextTable):
101 column_class = XLSColumn 102
103 - def render_header(self):
104 current_ws = self.renderer.current_ws 105 for column in self.columns: 106 if column.object_renderer: 107 object_renderer = column.object_renderer 108 else: 109 object_renderer = XLSObjectRenderer( 110 session=self.session, renderer=self.renderer) 111 112 object_renderer.RenderHeader(self.renderer.current_ws, column) 113 114 current_ws.current_row += 1 115 current_ws.current_column = 1
116
117 - def render_row(self, row=None, highlight=None, **options):
118 merged_opts = self.options.copy() 119 merged_opts.update(options) 120 121 # Get each column to write its own header. 122 current_ws = self.renderer.current_ws 123 for item in row: 124 # Get the object renderer for the item. 125 object_renderer = self.renderer.get_object_renderer( 126 target=item, type=merged_opts.get("type"), **merged_opts) 127 128 object_renderer.RenderCell(item, current_ws, **options) 129 130 current_ws.current_row += 1 131 current_ws.current_column = 1
132 133
134 -class XLSRenderer(renderer.BaseRenderer):
135 """A Renderer for xls files.""" 136 137 name = "xls" 138 139 table_class = XLSTable 140 tablesep = "" 141
142 - def __init__(self, output=None, **kwargs):
143 super(XLSRenderer, self).__init__(**kwargs) 144 145 # Make a single delegate text renderer for reuse. Most of the time we 146 # will just replicate the output from the TextRenderer inside the 147 # spreadsheet cell. 148 self.delegate_text_renderer = text.TextRenderer(session=self.session) 149 150 self.output = output or self.session.GetParameter("output") 151 152 # If no output filename was give, just make a name based on the time 153 # stamp. 154 if self.output == None: 155 self.output = "%s.xls" % time.ctime() 156 157 try: 158 self.wb = openpyxl.load_workbook(self.output) 159 self.current_ws = self.wb.create_sheet() 160 except IOError: 161 self.wb = openpyxl.Workbook() 162 self.current_ws = self.wb.active
163
164 - def start(self, plugin_name=None, kwargs=None):
165 super(XLSRenderer, self).start(plugin_name=plugin_name, kwargs=kwargs) 166 167 # Make a new worksheet for this run. 168 if self.current_ws is None: 169 self.current_ws = self.wb.create_sheet() 170 171 ws = self.current_ws 172 ws.title = plugin_name or "" 173 ws.current_row = 1 174 ws.current_column = 1 175 176 return self
177
178 - def flush(self):
179 super(XLSRenderer, self).flush() 180 self.current_ws = None 181 # Write the spreadsheet to a file. 182 self.wb.save(self.output)
183
184 - def section(self, name=None, **_):
185 ws = self.current_ws 186 for i in range(10): 187 cell = ws.cell(row=ws.current_row, column=i + 1) 188 if i == 0: 189 cell.value = name 190 191 cell.style = SECTION_STYLE 192 193 ws.current_row += 1 194 ws.current_column = 1
195
196 - def format(self, formatstring, *data):
197 worksheet = self.current_ws 198 if "%" in formatstring: 199 data = formatstring % data 200 else: 201 data = formatstring.format(*data) 202 203 cell = worksheet.cell( 204 row=worksheet.current_row, column=worksheet.current_column) 205 cell.value = data 206 cell.style = FORMAT_STYLE 207 208 worksheet.current_column += 1 209 if "\n" in data: 210 worksheet.current_row += 1 211 worksheet.current_column = 1
212
213 - def table_header(self, *args, **options):
214 super(XLSRenderer, self).table_header(*args, **options) 215 216 self.table.render_header()
217 218 219 # Following here are object specific renderers. 220 221
222 -class XLSEProcessRenderer(XLSObjectRenderer):
223 """Expands an EPROCESS into three columns (address, name and PID).""" 224 renders_type = "_EPROCESS" 225
226 - def RenderHeader(self, worksheet, column):
227 for heading in ["_EPROCESS", "Name", "PID"]: 228 cell = worksheet.cell( 229 row=worksheet.current_row, column=worksheet.current_column) 230 cell.value = heading 231 cell.style = HEADER_STYLE 232 233 worksheet.current_column += 1
234
235 - def RenderCell(self, item, worksheet, **options):
236 for value in ["%#x" % item.obj_offset, item.name, item.pid]: 237 object_renderer = self.ForTarget(value, self.renderer)( 238 session=self.session, renderer=self.renderer, **options) 239 object_renderer.RenderCell(value, worksheet, **options)
240 241
242 -class XLSStringRenderer(XLSObjectRenderer):
243 renders_type = "String" 244
245 - def GetData(self, item, **_):
246 return utils.SmartStr(item)
247 248
249 -class XLSStructRenderer(XLSObjectRenderer):
250 """Hex format struct's offsets.""" 251 renders_type = "Struct" 252
253 - def GetData(self, item, **_):
254 return "%#x" % item.obj_offset
255 256
257 -class XLSPointerRenderer(XLSObjectRenderer):
258 """Renders the address of the pointer target as a hex string.""" 259 renders_type = "Pointer" 260
261 - def GetData(self, item, **_):
262 result = item.v() 263 if result == None: 264 return "-" 265 266 return "%#x" % result
267 268
269 -class XLSNativeTypeRenderer(XLSObjectRenderer):
270 """Renders native types as python objects.""" 271 renders_type = "NativeType" 272
273 - def GetData(self, item, **options):
274 result = item.v() 275 if result != None: 276 return result
277 278
279 -class XLS_UNICODE_STRING_Renderer(XLSNativeTypeRenderer):
280 renders_type = "_UNICODE_STRING"
281 282
283 -class XLSNoneObjectRenderer(XLSObjectRenderer):
284 renders_type = "NoneObject" 285
286 - def GetData(self, item, **_):
287 _ = item 288 return "-"
289 290
291 -class XLSDateTimeRenderer(XLSObjectRenderer):
292 """Renders timestamps as python datetime objects.""" 293 renders_type = "UnixTimeStamp" 294 STYLE = styles.Style(number_format='MM/DD/YYYY HH:MM:SS') 295
296 - def GetData(self, item, **options):
297 if item.v() == 0: 298 return None 299 300 return item.as_datetime()
301