Enable Boot Logging 选项。

raw.PML。Ctrl-R 重置默认的进程监视器过滤器。boot.PML。Crassus.exe boot.PML。results.csv 中的相应条目。Accenture 创建了一个名为 Spartacus 的工具,用于在 Windows 上发现 DLL 劫持机会。以 Spartacus 为基础,我们创建了 Crassus,将其 Windows 权限提升发现能力扩展到不仅仅是查找缺失文件。特权进程使用的文件和目录的 ACL 可以找到比仅仅查找缺失文件更多的方法来实现目标。
……但 Crassus 有一个特点:它利用了 SysInternals 进程监视器(Process Monitor) 并解析原始的 PML 日志文件。典型用法是使用进程监视器生成引导日志,然后使用 Crassus 解析它。它还会为有漏洞的 DLL 自动生成包含所有相关导出的代理 DLL 源代码。
version.dll 遭受 DLL 劫持,Crassus 将为您创建包含所有导出的 version.cpp 和 version.def 文件。默认情况下,代理 DLL 会启动 calc.exe。构建脚本包含在内,可使用 Visual Studio 或 MinGW 构建 DLL。Crassus 工作的大致要点可总结为以下流程图:






Crassus 是作为 Visual Studio 2019 项目开发的。要构建 Crassus.exe:
Crassus.slnCtrl+Shift+B如果您信任在不知道其作用的情况下运行他人的代码,Crassus.exe 在此存储库中提供。
Enable Boot Logging 选项。

Ctrl-R 重置默认的进程监视器过滤器。boot.PML。重新保存日志文件的原因有两个:
| 参数 | 描述 |
|---|---|
<PMLFILE> | 现有 ProcMon 事件日志文件的位置(文件)。 |
--verbose | 启用详细输出。 |
--debug | 启用调试输出。 |
解析保存在 boot.PML 中的进程监视器引导日志。所有存在漏洞的路径将保存为 results.csv,所有代理 DLL 源文件保存在 stubs 子目录中。
C:\tmp> Crassus.exe boot.PML
以下是生成代理 DLL 时使用的模板。对于 Crassus 发现的 DLL,代理 DLL 将包含与 %_EXPORTS_% 中指定的相同导出名称,以及 .def 文件中指定的相同序号。Crassus 会通过查看父进程的架构,并相应地在 %_BUILD_AS_% 字段中标记源代码,来检测 DLL 需要构建为 32 位库还是 64 位库。
如果无法通过进程监视器日志找到真实的 DLL,或者导出名称有问题,构建脚本将回退到创建没有指定导出的 DLL。
#pragma once
//%_BUILD_AS%
#include <windows.h>;
extern "C" {
VOID Payload() {
// 在此运行您的载荷。
WinExec("calc.exe", 1);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
Payload();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#ifdef ADD_EXPORTS
%_EXPORTS_%
#endif
}
对于不安全使用 OPENSSLDIR 变量值的应用程序,可以将精心构造的 openssl.cnf 文件放置在指定位置。在此示例中,软件将加载 C:\tmp\calc.dll。请确保使用 32 位库用于 32 位进程,使用 64 位库用于 64 位进程。
[openssl_init]
# 这将尝试在 OpenSSL 初始化时加载文件 c:\tmp\calc.dll
# 构建脚本应检测 calc.dll 库需要构建为 32 位还是 64 位
/tmp/calc = asdf
可以使用 Visual Studio 随附的 cl.exe 二进制文件进行编译。具体命令如下:
cl.exe /DADD_EXPORTS /D_USRDLL /D_WINDLL <target>.cpp /LD /Fe<target>.dll /link /DEF:<target>.def
要自动化构建过程,包括指定库应为 64 位还是 32 位:
build.bat 脚本构建 DLL。.dll 结尾,则根据需要重命名编译后的文件。注意: 由于 vcvarsall.bat 的一个不幸行为(这绝对不是一个 bug),您可能在同一 Visual Studio 开发者命令提示符会话中尝试多次运行 build.bat 时遇到问题。如果遇到错误,只需关闭窗口并重新启动它。
如果 Visual Studio 不易使用,代理 DLL 也可以使用 MinGW-w64 进行编译。例如,在 Ubuntu 平台上,可以通过以下命令安装 MinGW:sudo apt install g++-mingw-w64-x86-64-win32 g++-mingw-w64-i686-win32
# 创建 32 位 DLL
i686-w64-mingw32-g++ -c -o <target>.o <target>.cpp -D ADD_EXPORTS
i686-w64-mingw32-g++ -o <target>.dll <target>.o <target>.def -s -shared -Wl,--subsystem,windows
# 创建 64 位 DLL
x86_64-w64-mingw32-g++ -c -o <target>.o <target>.cpp -D ADD_EXPORTS
x86_64-w64-mingw32-g++ -o <target>.dll <target>.o <target>.def -s -shared -Wl,--subsystem,windows
要自动化构建过程,包括指定库应为 64 位还是 32 位:
bash ./build.sh.dll 结尾,则根据需要重命名编译后的文件。如 VU#114757 所述,旧版 Acronis 软件包含多个权限提升漏洞。
openssl.cnf。C:\ProgramData\Acronis 目录的 ACL 不当。Crassus 自动发现这两个问题。

通过将我们编译的 curl.dll 文件放置在 C:\ProgramData\Acronis\Agent\var\atp-downloader\ 目录中,并使用新的进程监视器引导日志重新启动,我们可以看到我们的载荷(运行 calc.exe)以 SYSTEM 权限运行。

存在漏洞的 Acronis 软件尝试从两个不同的位置加载 openssl.cnf。我们将模板 openssl.cnf 文件放置在 c:\jenkins_agent\workspace\tp-openssl-win-vs2013\17\product\out\standard\vs_2013_release\openssl\ssl 中,并将 32 位 calc.dll 载荷放置在 c:\tmp 中。

如 VU#240785 所述,旧版 Atlassian Bitbucket 软件由于安装目录的 ACL 较弱而容易受到权限提升攻击。与任何安装在 C:\Program Files\ 或其他 ACL 受限位置之外的 Windows 软件一样,需要软件安装程序显式设置目标目录的 ACL。
Crassus 发现该软件的许多权限提升方法,包括:

在 Crassus 输出中,我们可以看到 c:\atlassian\bitbucket\7.9.1\elasticsearch\bin\elasticsearch-service-x64.exe 是特权进程,但由于它正在运行,我们不能简单地替换它。然而,我们可以使用另一种技巧来劫持它。我们可以简单地重命名它所在的目录,创建一个同名的新目录,并将我们的载荷以相同的名称放置在其中。

一旦我们用进程监视器引导日志重新启动,就可以看到我们的放置的 elasticsearch-service-x64.exe 文件正在运行,而不是真正的文件,从 Windows 计算器图标可以判断。

如 VU#287178 所述,旧版 McAfee 软件容易通过 openssl.cnf 进行权限提升。让我们来看一下:

要了解为什么引导日志中有两个不同的 openssl.cnf 引用,我们可以查看 results.csv 文件:

请注意,从 D:\ 路径加载 openssl.cnf 文件需要进一步的手动调查,因为加载此类路径的可行性取决于目标平台以及可用的系统访问权限。有可能创建一个光碟,提供 openssl.cnf 文件,该文件也指向光驱中的某个路径。
除非安装到非标准位置,否则 SQL Server 2022 不会因为 ACL 较弱而明显易受权限提升攻击。如果它安装在 C:\Program Files 之外的位置,Crassus 将发现多个权限提升的可能性。大多数包含特权组件的 Windows 应用程序,如果安装到没有固有安全 ACL 的目录,似乎都可能以这种方式被利用。

如果 Crassus 报告特权加载了一个用户可以放置或修改的文件,这并不一定意味着这是一个可利用的场景。虽然 Crassus 会查找潜在感兴趣的文件类型,但进程监视器日志文件不会直接指示相关进程对该文件本会做什么(如果它存在的话)。可能只是提取程序图标。在进程监视器中调查文件操作的回溯栈可能会提示该操作本会做什么。或者简单地放置文件并使用新的进程监视器引导日志调查行为,如果您更喜欢更简单的暴力方法。您也可能遇到这样的情况:缺少一个库,而 Crassus 要么无法找到该库以知道应该存在哪些导出,要么 Crassus 发现的导出存在冲突,从而阻止正确的 DLL 编译。在这种情况下,Crassus 将回退到创建一个不导出任何函数名称的 DLL。根据目标应用程序加载库的方式,缺少预期的函数名称和/或序号可能会导致目标应用程序无法成功加载该库。这种情况需要手动确定代理 DLL 应该是什么样的。
Crassus 会查找特权文件操作以发现感兴趣的路径。您可能会遇到这样一种情况:特权进程和非特权进程都会访问某个路径,但只有非特权进程会执行可能存在的代码。或者,您可能会遇到父进程确实以特权运行,但它可能显式生成具有较低特权的子进程的情况。
特别是在首次安装软件或安装更新时,进程监视器可能会记录一个看起来可被利用的文件操作,但该操作并非每次系统启动时都会发生。利用这些操作可能在事件发生后的第一次重启时才有可能。为避免此类边界情况,请确认后续的引导日志在后续重启中包含相同的报告文件操作。
无论是拼写错误、错误还是新功能,Crassus 都欢迎贡献,只要我们达成以下共识: