
aggrokatz 是一个用于 CobaltStrike 的 Aggressor 插件扩展,它使 pypykatz 能够远程与 beacon 交互。
当前版本的 aggrokatz 允许 pypykatz 解析 LSASS 转储文件和注册表配置单元文件,以提取凭据和其他机密,而无需下载文件,也无需向 beacon 上传任何可疑代码(Cobalt Strike 本身已在运行)。
未来,该项目旨在为隐蔽操作提供更多功能,例如搜索和解密所有 DPAPI 机密/kerberoasting 等。
我们为此工具发布了一篇简短的 博客文章,其中包含一些截图。
LSASS/注册表转储并非本项目目标,仅进行解析。原因:
在 CS 客户端中,不要使用“重新加载”或尝试手动卸载后重新加载脚本(如果你修改了它)。你必须卸载它,关闭客户端并重新启动,然后加载修改后的脚本。否则,多个版本会同时运行,导致大量错误和异常行为!
在远程端解析 LSASS/注册表文件时,请不要与你启动脚本所在的具体 beacon 交互。正常情况下这不会引起任何问题,但我无法提供保证。
pycobalt 的 aggressor.cna 文件已设置,并且知道你的 Python 解释器的位置aggrokatz.cna 中的 pycobalt_path 更改为指向 pycobalt.cnaView > Script Console 和 Cobalt Strike > Script Manager 窗口。使用 Script Manager 加载 aggkatz.cna 脚本。aggkatz.cna 脚本加载成功,在右键点击 beacon 时,你将看到一个新的菜单项 pypykatz。Script Console 窗口中看到调试消息。Script Console 窗口和 Beacon 自身的窗口中。LSASS file:远程计算机上 lsass.dmp 文件的路径。你也可以使用 UNC 路径通过 SMB 访问共享的 lsass.dmp 文件。chunksize:每次读取的最大大小BOF file:允许分块读取的 BOF 文件(Beacon Object File)。该文件将在每次读取新块时被上传并执行(内存中)。(module):指定要解析的模块。默认:allOutput:指定输出格式Populate Credential tab:成功解析后,所有获取的凭据将显示在 Cobalt Strike 的 Credential 选项卡中。此功能为 beta 版Delete remote file after parsing:成功解析后,将删除目标上的 LSASS 转储文件SYSTEM file:远程计算机上 SYSTEM.reg 文件的路径。你也可以使用 UNC 路径通过 SMB 访问共享文件。SAM file (optional):远程计算机上 SAM.reg 文件的路径。你也可以使用 UNC 路径通过 SMB 访问共享文件。SECURITY file (optional):远程计算机上 SECURITY.reg 文件的路径。你也可以使用 UNC 路径通过 SMB 访问共享文件。SOFTWARE file (optional):远程计算机上 SOFTWARE.reg 文件的路径。你也可以使用 UNC 路径通过 SMB 访问共享文件。chunksize:每次读取的最大大小BOF file:允许分块读取的 BOF 文件(Beacon Object File)。该文件将在每次读取新块时被上传并执行(内存中)。Output:指定输出格式文件读取 BOF 目前支持最大 4GB 的文件读取。经过一些修改可以扩展,但截至目前尚未观察到如此大的文件。
通常 pypykatz 的解析器会执行一系列磁盘文件读取操作,但借助 aggrokatz,这些读取操作通过一个特制的 BOF(Beacon Object File)被隧道传输到 beacon,该 BOF 允许分块读取远程文件内容。这使得 pypykatz 能够从远程文件中提取所有机密,而无需读取整个文件,仅抓取机密所在的关键块。
要全面了解整个过程,需要强调两个部分:
pypykatz 如何与 CobaltStrike 集成pypykatz 如何在不读取整个文件的情况下执行凭据提取CobaltStrike(代理)是用 Java 编写的,而 pypykatz 是用 Python 编写的。这是个问题。幸运的是,有匿名人士创建了 pycobalt,它为两个世界之间提供了简洁的接口,并附带可直接从 Python 调用的有用 API。尽管 pycobalt 是一个出色的工程作品,但存在一些我们需要指出的问题/缺点:
pycobalt 项目:pycobalt 项目在未来会得到维护。pycobalt 开发的任何方面。pycobalt 和 CobaltSrike 之间存在编码问题。这导致某些 API 调用返回的字节无法使用,因为部分字节被编码器损坏。通过检查代码,我们得出结论,大多数编码/解码问题是因为 pycobalt 使用 STDOUT/STDIN 与 Java 进程通信。bof_pack API 调用必须以纯 Aggressor 脚本实现,并仅使用基本数据结构(字符串和整数)从 Python 调用,而不能使用字节。pycobalt 包仅提供阻塞式 API,不支持线程。至少我们观察到线程会随机中断,但这也在预期之中。pypykatz 及其配套模块 minidump 必须进行修改,以实现比先前实现更高效的分块解析,但这又是另一回事了。
在 pypykatz 能够通过 pycobalt 与 CobaltStrike 交互后,下一步就是允许分块文件读取。遗憾的是,此功能并非任何我们见过的 C2 解决方案的默认功能,因此我们必须自行实现。我们解决这个问题的方法是通过使用 CobaltStrike 的 Beacon Object Files 接口(简称 BOF)来实现分块读取。BOF 是以 C 程序形式运行的代码,它们不在 beacon 上作为单独的进程执行,而是作为已有 beacon 的一部分运行。该接口非常有用,因为所有代码都在内存中执行,无需写入磁盘,从而使得 BOF 更加隐蔽。
我们的 BOF 方案是一个简单的函数,接受 4 个参数:
fileName:LSASS 转储文件或注册表配置单元文件的完整路径(远程端)buffsize:要从文件中读取的大小(字节)seekSize:文件读取操作应开始的位置(从文件开头算起)rplyid:一个标识号,用于嵌入回复以避免可能的冲突通过这些参数,pypykatz(在代理上运行)可以向目标 beacon(目标计算机)发出文件读取操作,精确定位文件的特定部分。
在另一端(CobaltStrike 中),aggrokatz 注册了一个回调,用于监控目标 beacon 返回的每条消息。如果消息头部与文件读取操作的头部匹配,则将其作为 minidump 文件的一个块进行处理,并分发给 minidump 解析器,解析器再将结果分发给 pypykatz。如果需要更多读取操作,pypykatz 将通过 minidump 读取器发起新读取,然后通过 BOF 接口在 beacon 上分派新的读取命令。此过程重复直到文件被解析完毕。
通过这种方法解析了大约 100 个 LSASS 转储后,我们可以得出以下结论(使用的块大小为 20k):