
Cargador dinámico de shellcode con sofisticadas capacidades de evasión
AsmLdr es un cargador de shellcode avanzado implementado en lenguaje ensamblador x64, diseñado para entornos Windows x64. Su propósito principal es ejecutar payloads cifrados mientras minimiza la detección por parte de antivirus avanzados, sistemas de detección y respuesta de endpoints (EDR), sandboxes y depuradores. Logra esto resolviendo módulos, APIs y llamadas al sistema de forma dinámica en tiempo de ejecución, eliminando dependencias estáticas como tablas de importación o direcciones hardcodeadas. Este enfoque crea un binario compacto con un perfil de detección bajo.
El cargador utiliza module stomping para colocar el shellcode en la sección ejecutable de una DLL existente, descifra el payload en memoria y lo ejecuta mediante syscalls indirectas con suplantación de pila (stack spoofing). Incluye funciones de evasión como medidas anti-depuración, ajustes de temporización para imitar patrones normales de aplicaciones y la omisión del seguimiento de eventos de Windows (ETW). Estas capacidades lo convierten en una herramienta para red teaming e investigación de seguridad. Aviso ético: Este proyecto es solo para fines educativos y de investigación. Demuestra aspectos internos de bajo nivel de Windows, incluido el recorrido del PEB, el análisis de tablas de exportación, el unhooking de syscalls y la manipulación de la protección de memoria. Úsese en entornos controlados (p. ej., máquinas virtuales). El uso indebido para actividades maliciosas es ilegal y poco ético. El autor declina toda responsabilidad por cualquier uso indebido.
AsmLdr ofrece una serie de funciones para la ejecución sigilosa de payloads y la evasión. Cada una se describe a continuación, centrándose en su función y beneficios:
Resolución de módulos mediante recorrido del PEB: El cargador enumera los módulos en ejecución siguiendo la cadena de módulos del PEB. Compara los nombres de los módulos mediante comparaciones Unicode para encontrar y devolver la dirección base de la DLL deseada. Este método evita las funciones de carga estándar, reduciendo el riesgo de intercepción.
Resolución de APIs desde tablas de exportación: El cargador examina el directorio de exportación de una DLL para localizar funciones. Coincide las APIs mediante hashing u, opcionalmente, comprobaciones directas de nombres con verificación de longitud para evitar confusiones entre nombres de funciones similares. Esto proporciona la dirección de la función sin depender de importaciones preenlazadas.
Protecciones anti-depuración: El cargador detecta la depuración mediante múltiples comprobaciones y sale de forma limpia si alguna indica análisis.
Generación de código basura para resistir el análisis: El cargador ejecuta secuencias de operaciones no esenciales para crear patrones confusos en el desensamblado, dificultando el análisis estático sin afectar la eficiencia en tiempo de ejecución.
Normalización de tiempos y comportamiento: El cargador mide la velocidad del sistema para ejecutar cargas de trabajo simuladas que coinciden con los patrones normales de las aplicaciones, lo que le permite mezclarse con procesos legítimos. También hace una pausa breve antes de acciones clave para normalizar los tiempos de ejecución.
Omisión del registro de ETW: El cargador establece puntos de interrupción de hardware en las APIs de registro de ETW para interceptar y omitir las llamadas de registro de eventos, evitando rastros en los registros del sistema.
Unhooking multicapa: El cargador obtiene dinámicamente números de syscall válidos (SSN) comprobando las funciones directamente, escaneando el código cercano si está hookeado, o contando patrones en ntdll para estimar el número, ajustando las excepciones conocidas.
Técnicas utilizadas:
Syscall indirecto y suplantación de pila: El cargador encuentra rutas de código limpias en ntdll para las llamadas al sistema y encadena hasta 32 operaciones, ocultando la pila de llamadas para evadir el rastreo. Restaura el estado original al finalizar.
DLL hollowing: El cargador carga una DLL objetivo, permite temporalmente la escritura en su sección de código, inserta el shellcode cifrado, lo descifra y restablece las protecciones a solo ejecución.
Descifrado en memoria: El cargador descifra el shellcode aplicando un patrón de clave repetido directamente en la memoria inyectada.
Funciones de utilidad: El cargador incluye herramientas para medir longitudes de cadenas, comparar cadenas (caracteres estándar o anchos), aplicar hash a nombres para búsquedas, validar punteros de memoria y leer marcas de tiempo para los controles de temporización.
El script de Python generate.py cifra el archivo de shellcode sin procesar. Añade relleno para la alineación, crea o utiliza una clave y aplica XOR a cada byte con la clave en un ciclo repetido. El archivo de salida shellcode.asm define tamaños, arrays para los datos cifrados y la clave, y una rutina para cargar los datos en tiempo de ejecución. El descifrado del cargador coincide con este proceso en memoria. Ten en cuenta que las claves más largas aumentan el tiempo de espera.
Prepara un binario de shellcode sin procesar (p. ej., payload.bin). Ejecuta python generate.py payload.bin [optional_key] para generar shellcode.asm.
Modifica szDllName (palabras hexadecimales Unicode en evader.asm) para DLL alternativas como urlmon.dll. Recalcula los hashes DJB2 para nuevas APIs usando la lógica de str_hash. Comenta las macros (p. ej., KILL_DEBUGGERS) para depurar.
AsmLdr está optimizado para Windows 10 y 11 x64; las actualizaciones del kernel pueden alterar los desplazamientos (p. ej., PEB+0x18) o los patrones de NTDLL (p. ej., 0xb8d18b4c), por lo que se requiere validación. El manejo de errores se basa en los valores de retorno NTSTATUS (p. ej., <0 fallo), sin registro incorporado. Las operaciones basura y falsas consumen ciclos de CPU, lo que podría alertar a los monitores de recursos en sistemas limitados. Úsalo únicamente en entornos controlados.