这套脚本旨在从被认为已感染的终端收集各类数据,以协助应急响应流程。这些数据不应被视为完整的取证数据收集,但确实捕获了大量有用的取证信息。
如需真正的取证数据,您应实际捕获完整的内存转储并对整个驱动器进行镜像。这不在本工具包的范围内。
脚本必须在运行中的系统上执行,而非镜像或其他取证数据存储库。它严格来说并不要求 root 权限才能运行,但若无 root 权限,将无法收集大部分预期数据。
数据将以两种形式收集。第一种是汇总文件,包含 shell 命令输出、从数据库提取的数据等。例如,browser 模块会输出一个 browser_extensions.txt 文件,汇总 Safari、Chrome 和 Firefox 中安装的所有浏览器扩展。
第二种是从文件系统收集的完整文件。这些文件存储在收集文件夹内的 artifacts 子文件夹中。
脚本运行非常简单。它仅需一个必需参数,即传入 JSON 格式的配置文件:
./pict.py -c /path/to/config.json
配置文件描述了脚本将收集哪些数据以及如何收集。其内容大致如下:
{
"collection_dest" : "~/Desktop/",
"all_users" : true,
"collectors" : {
"browser" : "BrowserExtCollector",
"persist" : "PersistenceCollector",
"suspicious" : "SuspiciousBehaviorCollector",
"browserhist" : "BrowserHistoryCollector",
"bash_config" : "BashConfigCollector",
"bash_hist" : "BashHistoryCollector",
"processes" : "ProcessCollector",
"network_config" : "NetworkConfigCollector",
"profiles" : "ProfileCollector",
"certs" : "TrustedCertCollector"
},
"settings" : {
"keepLSData" : true,
"zipIt" : true
},
"moduleSettings" : {
"browser" : {
"collectArtifacts" : true
}
},
"unused" : {
"installs" : "InstallationCollector"
}
}
指定存储收集数据的路径。可以是绝对路径,也可以是以波浪号开头的相对于用户主文件夹的路径。若未指定,默认路径为 /Users/Shared。
数据将存储在该路径下创建的文件夹中。文件夹名称格式为 PICT-计算机名-YYYY-MM-DD,其中计算机名是系统偏好设置 > 共享中指定的机器名称,日期为收集日期。
若为 true,则尽可能从机器上的所有用户收集数据。若为 false,则仅从运行脚本的用户收集数据。若未指定,默认值为 true。
PICT 是模块化的,可通过更改所使用的 Collector 模块轻松扩展或缩小范围。
collectors 数据是一个字典,其中键是要加载的模块名称(Python 文件名不含 .py 扩展名),值是该模块中找到的 Collector 子类名称。您可以为自定义模块添加额外条目(参见编写自己的模块),也可以删除条目以防止这些模块运行。一种简单的删除模块方式(无需记住确切名称,以便日后如需再次添加)是将它们移到一个名为 unused 的顶级字典中。
该字典提供全局设置。
keepLSData 指定是否保留 lsregister.txt 文件——该文件可能非常大。(此文件自动生成,用于构建其他模块的输出。它包含大量有用信息,但可能超过 100 MB。如果您不需要所有这些数据,或不想处理如此庞大的数据,可将其设为 false,收集完成后该文件将被删除。)
zipIt 指定是否自动生成包含收集文件夹内容的 zip 文件。请注意,压缩和解压数据的过程会更改某些属性,例如文件所有权。
该字典指定模块特有的设置。并非所有模块都有各自的设置,但如果某个模块允许自定义设置,您可以在此处提供。在上述示例中,您可以看到一个名为 collectArtifacts 的布尔设置与 browser 模块一起使用。
此外,还有由 Collector 类维护的全局模块设置,可为每个模块单独设置。
collectArtifacts 指定是否收集该模块通常会收集的文件工件。若为 false,则该模块的所有工件将被省略。这在存储空间有限且收集的工件较大,或收集的工件可能对受分析系统的用户构成隐私问题时可能需要用到。
模块必须包含一个文件,其中含有一个继承自 Collector 的类(定义在 collectors/collector.py 中),并且必须放置在 collectors 文件夹中。您可以通过复制 collectors/template.py 文件并根据自己的需求进行自定义,轻松创建新的 Collector 模块。
def __init__(self, collectionPath, allUsers)如有必要,可重写此方法,但在此情况下必须调用父类 Collector.init(),最好在自定义代码执行之前调用。这能让对象在您的代码尝试使用其属性之前有机会设置好这些属性。
def printStartInfo(self)这是一个非常简单的函数,当此模块开始收集时会被调用。其目的是向 stdout 输出一条消息,让用户了解进度,提供当前操作的反馈。
def applySettings(self, settingsDict)这使模块有机会应用任何自定义设置。每个模块可以有自己的自定义设置,但 settingsDict 也应传递给父类,以便 Collector 类处理其定义的任何设置。
def collect(self)此方法是模块的核心。当模块需要开始收集时被调用。它可以按需写入任意数量的文件,但应将操作限制在 self.collectionPath 路径内的文件,并使用未被其他模块占用的文件名。
如果您希望收集工件,请不要自行处理。只需将路径添加到 self.pathsToCollect 数组中,Collector 类会负责将这些路径复制到 artifacts 文件夹内相应的子路径中,并维护工件的元数据(权限、扩展属性、标志等)。
方法结束时,请务必调用父类的方法(Collector.collect(self)),以便 Collector 类有机会处理其职责,例如收集工件。
您的 collect 方法可以使用在 self.collectionPath 中找到的 basic_info.txt 或 lsregister.txt 文件中的任何数据。这些文件由 pict.py 脚本在开始时收集,并可假定其他模块可以使用。但是,您不应依赖任何其他模块的输出,因为无法保证当您的模块运行时这些文件可用。模块可能不会按照配置 JSON 中的顺序运行,因为 Python 字典是无序的。
感谢 Greg Neagle 提供 FoundationPlist.py,它解决了读取二进制 plist、包含日期数据类型的 plist 等许多问题。