EntropyReducer: Reduce La Entropía De Tu Payload Y Ofúscalo Con Listas Enlazadas Serializadas
Cómo Funciona
El algoritmo de EntropyReducer está determinado por los valores de BUFF_SIZE y NULL_BYTES. A continuación se muestra cómo organizaría EntropyReducer tu payload si BUFF_SIZE se estableciera en 4 y NULL_BYTES en 2.

Algoritmo de Ofuscación
- EntropyReducer primero comprueba si el payload sin procesar de entrada tiene un tamaño que sea múltiplo de
BUFF_SIZE; si no es así, lo rellena para que lo sea.
- Luego toma cada fragmento de
BUFF_SIZE del payload y crea un nodo de lista enlazada para él, usando la función InitializePayloadList, inicializando el payload como una lista enlazada.
- El nodo creado tendrá un búfer vacío de tamaño
NULL_BYTES, que se utilizará para reducir la entropía
- En este punto, aunque EntropyReducer completó su tarea reduciendo la entropía del payload, no se detiene aquí. Luego continúa aleatorizando el orden de cada nodo en la lista enlazada, descomponiendo el orden del payload sin procesar. Este paso se realiza mediante un Algoritmo de Ordenamiento por Mezcla que se implementa a través de la función MergeSort.
- La lista enlazada ordenada queda en orden aleatorio porque el valor por el cual se ordena la lista enlazada es el valor XOR de los primeros tres bytes del payload sin procesar; este valor determina su posición en la lista enlazada reorganizada, este paso se puede ver aquí
- Dado que guardar una lista enlazada en un archivo es imposible debido a que está enlazada mediante punteros. Nos vemos obligados a serializarla.
- La serialización de la lista enlazada generada se realiza mediante la función
Obfuscate aquí.
- Después de eso, los datos serializados están listos para escribirse en el archivo de salida.
Algoritmo de Desofuscación
- Dado que el último paso en el
Algoritmo de Ofuscación fue serializar la lista enlazada, lo primero que debe hacerse aquí es deserializar el payload ofuscado, generando una lista enlazada a partir de él, este paso se realiza aquí en la función Deobfuscate.
- El siguiente paso es ordenar la lista enlazada usando el Id del nodo, lo cual se realiza usando el mismo Algoritmo de Ordenamiento por Mezcla usado anteriormente.
- Ahora, la lista enlazada está en el orden correcto para reconstruir los bytes del payload tal como deberían ser. Así que simplemente extraemos los bytes originales del payload de cada nodo, como se hace aquí.
- El último paso es liberar los nodos asignados, lo cual se hace aquí.
Uso
- EntropyReducer simplemente lee el archivo de payload sin procesar desde la línea de comandos y escribe la versión ofuscada en el mismo nombre de archivo con el prefijo ".ER".
- El tamaño del payload ofuscado final varía según los valores de
BUFF_SIZE y NULL_BYTES. Sin embargo, puede determinarse usando la siguiente ecuación
FinalSize = ((OriginalSize + BUFF_SIZE - OriginalSize % BUFF_SIZE ) / BUFF_SIZE) * (BUFF_SIZE + NULL_BYTES + sizeof(INT))
El proyecto PoC en este repositorio se utiliza para ejecutar el archivo ".ER" generado como ejemplo de deserialización y desofuscación del mismo.
Incluir en tus proyectos
Todo lo que tienes que hacer es añadir los archivos EntropyReducer.c y EntropyReducer.h a tu proyecto, y llamar a la función Deobfuscate. Puedes consultar PoC/main.c como referencia.
Ejemplo de salida
En este ejemplo, BUFF_SIZE se estableció en 3, y NULL_BYTES en 1.
- El payload en bruto, primer fragmento del payload (
FC 48 83)

- El mismo fragmento del payload, pero en un desplazamiento diferente

Beneficio
- El shellcode calc para x64 generado por metasploit tiene una entropía de
5.883, según pestudio.

- El mismo archivo, cifrado con AES, obtiene una puntuación de entropía de
7.110.

- Un resultado casi idéntico también con el algoritmo RC4;
7.210

- Sin embargo, usando EntropyReducer, la puntuación de entropía es incluso menor que la del payload en bruto original;
4.093

El algoritmo Merge Sort está tomado de c-linked-list.