
ShellcodeFluctuation PoC portado a Nim
Port en Nim del repositorio original: https://github.com/mgeeky/ShellcodeFluctuation Todos los comentarios se copiaron y pegaron tal cual del repositorio original, ya que realmente me ayudaron a entender la técnica. Para obtener más información sobre la técnica en sí, recomiendo encarecidamente revisar el README del repositorio original.
Instalar dependencias:
nimble install winim ptr_math
Soy totalmente consciente de que esta técnica de cifrado de memoria no es la mejor en términos de OpSec. Solo cifrará exactamente aquellas regiones que se definieron para ello. Así, por ejemplo, en un implante C2, todas las direcciones de memoria de los módulos recién ejecutados no se cifrarán durante el Sleep. Para detecciones basadas en heap (como las de la configuración de Cobalt Strike), todavía tendrías que añadir cifrado de heap aquí.
Pero aun así, la técnica de cifrado de memoria se puede usar perfectamente para evitar detecciones automáticas de escáneres de memoria durante el Sleep for the main implante C2. Probé el PoC con éxito con Covenant y un payload sin stager personalizado como este.
La clave de cifrado/descifrado, más la dirección del Shellcode y otros valores como la protección (RW), tienen que definirse manualmente en este Port. En el repositorio original, la dirección de llamada del Shellcode se obtenía automágicamente.
El archivo Example.nim contiene todo lo que necesitas para empezar. Por supuesto, cuando se usa Shellcode de C2 no necesitas llamar a Sleep por ti mismo (esto es solo para activar todo en el PoC), eso debería hacerlo tu propio C2. Por el momento esto solo es compatible con frameworks C2 que usan la función Sleep de Win32, pero si modificas el Hook para otra función funcionará de la misma manera.
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)
Probar el PoC de cifrado se puede hacer, p. ej., así:
nim c --debuginfo --linedir:on Example.nim
Empieza con un depurador:
gdb Example.exe
Establece puntos de interrupción antes y después de Sleep:
# Before encryption
break Example.nim:31
# After encryption
break Fluctuation.nim:98
# Original value restored
break Example.nim:33
Después, comprueba el valor de la dirección del Shellcode en cada punto de interrupción así:

Fluctuation a NA aún no funciona, ya que el Vectored Exception Handler nunca se activó en mi prueba y la aplicación falló. Tendré que hacer más pruebas/solución de problemas en el futuro. ¡Siéntete libre de probarlo tú mismo! :-)