volatility插件解析
为了了解volatility的运作机制和插件情况(以实现开发新插件的计划),代码审计如下:
0x00 volatility主线程
审计核心代码vol.py
,源码:
1 | def main(): |
总结的流程图如下:
上面主要是主线程的启动流程。
1、vol从自身配置中获取插件字典,该字典的格式是[插件名:插件体]
2、主线程从命令行参数里获取第一个长得像是插件名的参数,就像我们输入的linux_arp一样的参数
3、参数:
1、不存在像是插件名的字符串则报错并退出
2、存在则以插件名、配置来初始化插件
4、在插件上hook help函数
5、开始执行插件
注意的:get_plugin_classes
函数用于获取一切以commands.Command
为父类的派生类字典。
0x01 插件的类派生
如上图,volatility中的插件以commands
的Command
类为父类,分别派生出AbstractWindowsCommand
类、AbstractMacCommand
类以及AbstractLinuxCommand
类,这分别代表三个平台插件的基类。
这三类为不同平台的插件定义了一些共同的函数,以供具体的插件继承调用,也方便了我们自定义插件时复用这些函数。
0x02 插件运行机理
如上是插件的运行机理:
首先获取所有已注册的Profile的派生类集合。
1 | def execute(self): |
接着除了kdbgscan和imageinfo两个插件可以不提供profile而使用默认的profile–WinXPSP2x86以外,其他插件没有提供profile参数就不给运行的机会。
1 | if plugin_name != "mac_get_profile": |
接着执行插件的calculate函数,这个函数我们在自定义插件的时候一般会实现,作为vol和我们的自定义插件之间的调用接口,即插件的执行。
1 | # # 首先执行calculate |
随后基于输出格式确定渲染函数。
1 | function_name = "render_{0}".format(self._config.OUTPUT) |
若非sqlite输出且存在输出的目标文件,则进行写文件。否则将结果输出至标准输出。
1 | if not self._config.OUTPUT == "sqlite" and self._config.OUTPUT_FILE: |
其中默认以时间戳_插件名的命名方式来创建输出文件,若指定了输出文件,则使用用户自定义的。
1 | out_file = '{0}_{1}.txt'.format(time.strftime('%Y%m%d%H%M%S'), plugin_name) if self._config.OUTPUT_FILE == '.' else self._config.OUTPUT_FILE |
接着执行插件对应的渲染函数render_output
1 | func = getattr(self, function_name) |
最后将结果输出到输出对象里。
1 | func(outfd, data) |
以上