
ShellcodeFluctuation PoC ported to Nim
Port em Nim do repositório original: https://github.com/mgeeky/ShellcodeFluctuation Todos os comentários foram copiados e colados exatamente como estavam no repositório original, pois eles realmente me ajudaram a entender a técnica. Para mais informações sobre a técnica em si, recomendo fortemente a leitura do README do repositório original!
Instale as dependências:
nimble install winim ptr_math
Estou totalmente ciente de que esta técnica de criptografia de memória não é a melhor em termos de OpSec. Ela criptografará apenas exatamente as regiões que foram definidas para ela. Assim, por exemplo, em um C2-Implant, todos os endereços de memória de módulos recém-executados não serão criptografados durante o Sleep. Para detecções baseadas em Heap (como as da configuração do Cobalt-Strike), você ainda precisaria adicionar criptografia de Heap aqui.
Mesmo assim, a técnica de criptografia de memória pode ser usada perfeitamente para evitar detecções automáticas de scanners de memória durante o Sleep para o C2-Implant principal. Testei o PoC com sucesso com o Covenant e um Payload stageless personalizado como este.
A chave de criptografia/descriptografia, juntamente com o endereço do Shellcode e outros valores como a proteção (RW), precisam ser definidos manualmente neste Port. No Repo original, o Caller-Address do Shellcode era recuperado automaticamente.
O arquivo Example.nim contém tudo o que você precisa para começar. Naturalmente, ao usar Shellcode de C2, você não precisa chamar Sleep por conta própria (isso serve apenas para acionar tudo no PoC), isso deve ser feito pelo próprio C2. Por enquanto, isso só é compatível com C2-Frameworks que usam a função Sleep do Win32, mas se você modificar o Hook para outra função, funcionará da mesma forma.
import winim
import Fluctuation
echo "Trying to hook Sleep"
if (hookSleep()):
echo "Hooked Sleep successfully!"
type
PocArray = array[12, byte]
let names: PocArray = [byte 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA]
g_fluctuationData.shellcodeAddr = unsafeAddr names[0]
echo "Shellcode address:"
echo repr(g_fluctuationData.shellcodeAddr)
g_fluctuationData.shellcodeSize = size_t(len(names))
echo "Shellcode Size:"
echo repr(g_fluctuationData.shellcodeSize)
when defined(amd64):
g_fluctuationData.encodeKey = 0xDEADB33f
when defined(i386):
g_fluctuationData.encodeKey = 0xDEAD
g_fluctuationData.currentlyEncrypted = false
g_fluctuationData.protect = PAGE_READWRITE
g_fluctuate = FluctuateToRW
echo "Calling Sleep"
Sleep(2500)
echo "Everything went fine and as expected"
else:
echo "Failed to hook Sleep"
quit(1)
O teste do PoC de criptografia pode ser feito, por exemplo, assim:
nim c --debuginfo --linedir:on Example.nim
Inicie com um depurador:
gdb Example.exe
Defina breakpoints antes e depois do Sleep:
# Before encryption
break Example.nim:31
# After encryption
break Fluctuation.nim:98
# Original value restored
break Example.nim:33
Em seguida, verifique o valor do endereço do Shellcode em cada breakpoint assim:

Fluctuation para NA ainda não funciona, pois o Vectored Exception Handler nunca foi acionado no meu teste e o aplicativo travou. Preciso fazer mais alguns testes/depurações em algum momento no futuro. Sinta-se à vontade para testar você mesmo! :-)