欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

从PowerShell内存中提取取证脚本内容

来源:本站整理 作者:佚名 时间:2019-02-02 TAG: 我要投稿


 
在发布了《从PowerShell进程转储中提取活动历史记录》这篇文章后,我收到了一个有趣的问题:“如果没有捕获到原始文件,是否可以提取到已执行的脚本内容呢(从磁盘里)?”
答案是“可以”,但是操作起来很复杂。 我们从头开始一步一步看看是如何进行取证的,第一步先安装PowerShell的WinDbg模块,我们需要它来做一些自动化的工作。
首先搭建我们的取证实验环境,在C:temp之类的目录下创建如下简单的脚本:

打开PowerShell会话,运行这个脚本。然后在任务管理器中Dump Powershell 内存:

现在,使用WinDbg模块连接到Dump下来的文件:
Connect-DbgSession -ArgumentList '-z "C:UsersleeAppDataLocalTemppowershell.DMP"'
 
开始取证
在开始我们的取证之前,让我们脑暴一下。我们的目的是提取Powershell会话中运行的脚本对象内容(如果存在的话),那么问题就是,如何找到这个脚本对象呢?
首先,我们使用SOS的Dump Object命令来转储进程内存中的所有对象内容。然后,我们用!DumpHeap命令开始查找所有对象实例(eg:这里我们甚至没有用-Type过滤指令)。这一步和接下来的操作将花费很长时间,所以建议在睡觉之前跑这个命令 : D
$allReferences = dbg !dumpheap -short
一旦我们导出了所有对象引用,便可使用!do(Dump Object)命令将它们全部可视化。转储对象的输出中不包括被转储对象的地址,因此我们用Add-Member来跟踪它。
$allObjects = $allReferences | Foreach-Object { $object = dbg "!do $_"; Add-Member -InputObject $object Address $_ -PassThru -Force }
(第二天)确实是一大堆数据呢!这个进程大概有100万个被SOS识别出来的对象实例。他们中有SOS可以可视化的GUID吗? 我们来看看:

看起来我们运气还不错。在上百万个对象中,我们设法将范围缩小到PowerShell内存中的7个System.String对象,这些对象以某种方式引用了GUID。如果我们认为信息可能一直在System.String中,我们可以使用$allReferences = dbg !dumpheap –type System.String –short代替一开始的$allObjects来加快查询。 问题又来了,我们怎么知道谁包含了这些GUID呢?
为了找到答案,我们使用SOS的!gcroot命令。 这个命令通常用于诊断托管内存的泄漏问题。例如:“为什么CLR保留了字符串的一千万个实例?”。对于任何给定对象,!gcroot命令告诉您哪个对象引用了它,这样递归一直到对象树的根节点。 让我们探讨一下这些根节点。

好了,所以最后一个元素( 数组中的第6个 )并不是最终的根节点。它不会再被引用,很快就会被垃圾收集器清理干净。
第5个是以一个对象数组为根节点的,其中一个元素是ConcurrentDictionary,它包含一个ScriptBlock,ScriptBlock中包含CompiledScriptBlockData,CompiledScriptBlockData包含了PowerShell AST中的节点,最后PowerShell AST引用了CommandAst AST,最终引用了这个GUID。
看起来还不错,那其他的呢,我们看看实例中的第4项:

有意思! 这个是以相同的根对象数组(0000026e101e9a40),相同的ConcurrentDictionary(0000026e003bc440)开头的,但这次最后是一个简单配对的元组(包含我们要找的String和另一个String)。 让我们深入了解那个元组及其包含的字符串:

这个元组有两个元素。 第一个元素看起来是执行脚本的路径,第二个元素看起来是该脚本中的内容。 让我们看看PowerShell Source怎么定义这些数据结构的。 搜索一下ConcurrentDictionary, 在第三页我们可以看到:

有一个名为CompiledScriptBlock的类。 它包含一个名为s_cachedScripts的静态(进程范围)缓存。 这是一个将一对字符串映射到ScriptBlock实例的字典。 如果您阅读了源代码,您可以确切地看到Tuple的内容(一个脚本路径到ScriptBlock缓存内容的映射):

这个数据结构就是我们最终要关心的。出于性能原因,PowerShell维护一个内部脚本块缓存,这样每次看到脚本时都不需要重新编译脚本块。 该缓存是路径和脚本内容的关键。 存储在缓存中的东西是ScriptBlock类的一个实例,它包含了已编译脚本的AST。

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载