Package rekall :: Package plugins :: Package common :: Module api
[frames] | no frames]

Source Code for Module rekall.plugins.common.api

  1  # Rekall Memory Forensics 
  2  # Copyright (C) 2016 Michael Cohen 
  3  # Copyright 2016 Google Inc. All Rights Reserved. 
  4  # 
  5  # This program is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 2 of the License, or (at 
  8  # your option) any later version. 
  9  # 
 10  # This program is distributed in the hope that it will be useful, but 
 11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  # General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the Free Software 
 17  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 18  # 
 19   
 20  """Rekall specifies an external API where plugins can be invoked.""" 
 21  import copy 
 22  import textwrap 
 23   
 24  from rekall import config 
 25  from rekall import plugin 
 26  from rekall_lib import yaml_utils 
 27   
 28   
29 -class APIGenerator(plugin.TypedProfileCommand, 30 plugin.Command):
31 """Generate the plugin API document.""" 32 name = "api" 33 34 __args = [ 35 dict(name="output_file", 36 help="If specified we write the API into this file in YAML."), 37 ] 38 39 table_header = [ 40 dict(name="plugin", width=40), 41 dict(name="api", width=80), 42 dict(name="raw_api", hidden=True), 43 ] 44
45 - def get_active_modes(self, cls):
46 """Calculate the declared modes under which the plugin is active.""" 47 modes = set() 48 for subclass in cls.__mro__: 49 mode = getattr(subclass, "mode", None) 50 51 if isinstance(mode, basestring): 52 modes.add(mode) 53 54 elif isinstance(mode, (list, tuple)): 55 modes.update(mode) 56 57 return sorted(modes)
58
59 - def get_command_dict(self, option):
60 """Describes CommandOption instance as a dict.""" 61 result = yaml_utils.OrderedYamlDict(type=option.type) 62 for attr in ["default", "choices", "help"]: 63 value = getattr(option, attr, None) 64 if value is not None: 65 result[attr] = copy.copy(value) 66 67 for attr in ["positional", "required", "hidden"]: 68 value = getattr(option, attr, False) 69 if value: 70 result[attr] = copy.copy(value) 71 72 return result
73
74 - def get_plugin_args(self, cls):
75 """Collects the args from the plugin.""" 76 args = yaml_utils.OrderedYamlDict() 77 for subclass in cls.__mro__: 78 for definition in getattr( 79 subclass, "_%s__args" % subclass.__name__, []): 80 # Definitions can be just simple dicts. 81 if isinstance(definition, dict): 82 definition = plugin.CommandOption(**definition) 83 84 # We have seen this arg before. 85 previous_definition = args.get(definition.name) 86 if previous_definition: 87 # Since we traverse the definition in reverse MRO order, 88 # later definitions should be masked by earlier (more 89 # derived) definitions. 90 continue 91 92 args[definition.name] = self.get_command_dict(definition) 93 94 return args
95
96 - def _clean_up_doc(self, doc):
97 title = body = "" 98 doc = doc.strip() 99 if doc: 100 lines = doc.splitlines() 101 title = lines[0] 102 if len(lines) > 1: 103 body = "\n".join(lines[1:]) 104 body = textwrap.dedent(body) 105 106 return "%s\n%s" % (title, body)
107
108 - def generate_api(self):
109 # All plugins are registered with the base plugin. 110 for plugin_name, cls in sorted(self.classes.iteritems()): 111 if not cls.name: 112 continue 113 114 docstring = self._clean_up_doc( 115 cls.__doc__ or cls.__init__.__doc__ or "") 116 117 # Control the order of entries in the yaml file. 118 result = yaml_utils.OrderedYamlDict() 119 result["plugin"] = plugin_name 120 result["name"] = cls.name 121 result["description"] = docstring 122 args = self.get_plugin_args(cls) 123 if args: 124 result["args"] = args 125 126 result["active_modes"] = self.get_active_modes(cls) 127 128 yield result
129
130 - def collect(self):
131 apis = [] 132 for plugin_api in self.generate_api(): 133 apis.append(plugin_api) 134 yield dict(plugin=plugin_api["plugin"], 135 api=yaml_utils.safe_dump(plugin_api), 136 raw_api=plugin_api) 137 138 if self.plugin_args.output_file: 139 with open(self.plugin_args.output_file, "wb") as fd: 140 fd.write(yaml_utils.safe_dump(apis))
141 142
143 -class APISessionGenerator(APIGenerator):
144 name = "session_api" 145 146 table_header = [ 147 dict(name="option", width=40), 148 dict(name="api", width=80), 149 dict(name="raw_api", hidden=True), 150 ] 151
152 - def collect(self):
153 apis = [] 154 for option, api in config.OPTIONS.args.items(): 155 for k, v in api.items(): 156 if callable(v): 157 api[k] = v() 158 159 apis.append(api) 160 yield dict(option=option, 161 api=yaml_utils.safe_dump(api), 162 raw_api=api) 163 164 if self.plugin_args.output_file: 165 with open(self.plugin_args.output_file, "wb") as fd: 166 fd.write(yaml_utils.safe_dump(apis))
167