refactor: move directories around 1/2

This commit is contained in:
Dobin
2024-03-29 18:02:16 +00:00
parent 0296537ec5
commit a6dbbe69ac
14 changed files with 103 additions and 180 deletions
+8 -17
View File
@@ -1,21 +1,12 @@
*.exe.injected
*-verify.exe
*.infected.exe
app/upload/*
data/exes_more/
*.obj
*.lnk
/*.bin
__pycache__ __pycache__
bak/ bak/
build/
out/
tools/ tools/
doc/ doc/
*.pickle
logs/ data/exes_more/
app/projects/* data/source/payload/
data_orig/
app/upload_orig/ log-*
data/source/payload/ *.verify.exe
*.infected.exe
BIN
View File
Binary file not shown.
+10 -17
View File
@@ -124,7 +124,8 @@ def dev_build_route(name):
@views.route("/project/<name>") @views.route("/project/<name>")
def project(name): def project(name):
project = storage.get_project(name) project = storage.get_project(name)
log_files = get_logfiles() project.settings.prep()
log_files = get_logfiles(project.settings.main_dir)
exes = [] exes = []
for file in os.listdir(PATH_EXES): for file in os.listdir(PATH_EXES):
@@ -153,7 +154,7 @@ def project(name):
injectstyles=injectstyles, injectstyles=injectstyles,
log_files=log_files, log_files=log_files,
) )
@views.route("/project_add", methods=['POST', 'GET']) @views.route("/project_add", methods=['POST', 'GET'])
@@ -235,16 +236,6 @@ def supermega_thread(project: Project):
start(project.settings) start(project.settings)
thread_running = False thread_running = False
# copy generated file to project folder
file_basename = os.path.basename(project.settings.inject_exe_out)
project.project_exe = file_basename
dest = PATH_WEB_PROJECT + "{}/{}".format(project.name, file_basename)
logger.info("Copy {} to project folder {}".format(project.settings.inject_exe_out, dest))
shutil.copy(
project.settings.inject_exe_out,
dest,
)
@views.route("/project/<project_name>/build", methods=['POST', 'GET']) @views.route("/project/<project_name>/build", methods=['POST', 'GET'])
def build_project(project_name): def build_project(project_name):
@@ -323,18 +314,20 @@ def start_project(project_name):
return redirect("/project/{}".format(project_name), code=302) return redirect("/project/{}".format(project_name), code=302)
def get_logfiles(): def get_logfiles(directory):
log_files = [] log_files = []
id = 0 id = 0
asm_a = "" # for diff asm_a = "" # for diff
asm_b = "" asm_b = ""
for file in os.listdir(f"{logs_dir}/"): for file in os.listdir(f"{directory}/"):
if file.startswith("."): if file.startswith("."):
continue continue
if not file.startswith("log-"):
continue
if file.endswith(".bin"):
continue
with open(os.path.join(f"{logs_dir}/", file), "r") as f: with open(os.path.join(f"{directory}/", file), "r") as f:
if file.endswith(".bin"):
continue
data = f.read() data = f.read()
if 'main_c' in file: if 'main_c' in file:
data = highlight(data, CLexer(), HtmlFormatter(full=False)) data = highlight(data, CLexer(), HtmlFormatter(full=False))
+9 -14
View File
@@ -13,25 +13,20 @@ logger = logging.getLogger("Helper")
SHC_VERIFY_SLEEP = 0.1 SHC_VERIFY_SLEEP = 0.1
def clean_files(): def clean_files(settings):
logger.info("--( Remove old files") logger.info("--( Remove old files")
files_to_clean = [ files_to_clean = [
# compile artefacts in current dir # compile artefacts in current working dir
"main-clean.obj", "main-clean.obj",
"main.obj", "main.obj",
"mllink$.lnk", "mllink$.lnk",
#"out/7z-verify.exe",
#"out/wifiinfoview-verify.exe", # temporary files
#"out/procexp64-verify.exe", settings.main_c_path,
# out/ stuff settings.main_asm_path,
os.path.join(build_dir, "main.asm"), settings.main_shc_path,
os.path.join(build_dir, "main.bin"), settings.main_exe_path,
os.path.join(build_dir, "main.c"),
os.path.join(build_dir, "peb_lookup.h"),
os.path.join(build_dir, "main.exe"),
VerifyFilename,
] ]
for file in files_to_clean: for file in files_to_clean:
pathlib.Path(file).unlink(missing_ok=True) pathlib.Path(file).unlink(missing_ok=True)
+2 -12
View File
@@ -7,6 +7,7 @@ class FilePath(str):
# with data/shellcodes/createfile.bin # with data/shellcodes/createfile.bin
VerifyFilename: FilePath = r'C:\Temp\a' VerifyFilename: FilePath = r'C:\Temp\a'
# Directory structure
PATH_EXES = "data/binary/exes/" PATH_EXES = "data/binary/exes/"
PATH_SHELLCODES = "data/binary/shellcodes/" PATH_SHELLCODES = "data/binary/shellcodes/"
PATH_PEB_WALK = "data/source/carrier/peb_walk/" PATH_PEB_WALK = "data/source/carrier/peb_walk/"
@@ -14,8 +15,7 @@ PATH_IAT_REUSE = "data/source/carrier/iat_reuse/"
PATH_PAYLOAD = "data/source/payload/" PATH_PAYLOAD = "data/source/payload/"
PATH_DECODER = "data/source/carrier/decoder/" PATH_DECODER = "data/source/carrier/decoder/"
PATH_WEB_PROJECT = "app/projects/" PATH_WEB_PROJECT = "app/projects/" # web only
PATH_WORKING = "working/"
# Correlated with real template files # Correlated with real template files
@@ -62,13 +62,3 @@ class IatEntry():
self.dll_name: str = dll_name self.dll_name: str = dll_name
self.func_name: str = func_name self.func_name: str = func_name
self.iat_vaddr: int = iat_vaddr self.iat_vaddr: int = iat_vaddr
# no slash at end
build_dir = "working/build"
logs_dir = "working/logs"
main_c_file = os.path.join(build_dir, "main.c")
main_asm_file = os.path.join(build_dir, "main.asm")
main_exe_file = os.path.join(build_dir, "main.exe")
main_shc_file = os.path.join(build_dir, "main.bin")
+9
View File
@@ -27,3 +27,12 @@ class Settings():
self.generate_asm_from_c: bool = True self.generate_asm_from_c: bool = True
self.generate_shc_from_asm: bool = True self.generate_shc_from_asm: bool = True
def prep(self):
self.main_dir = "data/source/carrier/" + self.source_style.value + "/"
self.template_path = self.main_dir + "template.c"
self.main_c_path = self.main_dir + "main.c"
self.main_asm_path = self.main_dir + "main.asm"
self.main_exe_path = self.main_dir + "main.exe"
self.main_shc_path = self.main_dir + "main.bin"
-1
View File
@@ -14,7 +14,6 @@ from model.carrier import Carrier
from model.exehost import ExeHost from model.exehost import ExeHost
logger = logging.getLogger("Compiler") logger = logging.getLogger("Compiler")
use_templates = True
# NOTE: Mostly copy-pasted from compiler.py::compile() # NOTE: Mostly copy-pasted from compiler.py::compile()
def compile_dev( def compile_dev(
+2 -2
View File
@@ -16,7 +16,7 @@ logger = logging.getLogger("Injector")
def inject_exe( def inject_exe(
main_shc_file: FilePath, main_shc_path: FilePath,
settings: Settings, settings: Settings,
project: Project, project: Project,
): ):
@@ -32,7 +32,7 @@ def inject_exe(
# Read prepared loader shellcode # Read prepared loader shellcode
# And check if it fits into the target code section # And check if it fits into the target code section
main_shc = file_readall_binary(main_shc_file) main_shc = file_readall_binary(main_shc_path)
l = len(main_shc) l = len(main_shc)
if l + 128 > project.exe_host.code_section.Misc_VirtualSize: if l + 128 > project.exe_host.code_section.Misc_VirtualSize:
logger.error("Error: Shellcode {}+128 too small for target code section {}".format( logger.error("Error: Shellcode {}+128 too small for target code section {}".format(
+34 -76
View File
@@ -1,98 +1,56 @@
from jinja2 import Template from jinja2 import Template
import pprint
import shutil import shutil
import logging import logging
from helper import * from helper import *
from observer import observer from observer import observer
from model.defs import * from model.defs import *
from model.settings import Settings
use_templates = True
logger = logging.getLogger("Assembler") logger = logging.getLogger("Assembler")
# INPUT: def create_c_from_template(settings: Settings, payload_len: int):
# data/plugins/
# data/source/
#
# Output:
# build/main.c
# build/*.h
def create_c_from_template(
source_style: SourceStyle,
alloc_style: AllocStyle,
exec_style: ExecStyle,
decoder_style: DecoderStyle,
payload_len: int,
):
plugin_allocator = ""
plugin_decoder = ""
plugin_executor = ""
logger.info("--[ Create C from template") logger.info("--[ Create C from template")
plugin_decoder = ""
#filepath = "data/plugins/allocator/{}.c".format(alloc_style.value) # Decoder
#with open(filepath, "r", encoding='utf-8') as file: filepath_decoder = PATH_DECODER + "{}.c".format(settings.decoder_style.value)
# plugin_allocator = file.read() with open(filepath_decoder, "r", encoding='utf-8') as file:
# plugin_allocator = Template(plugin_allocator).render({
# 'PAYLOAD_LEN': payload_len,
# })
filepath = PATH_DECODER + "{}.c".format(decoder_style.value)
with open(filepath, "r", encoding='utf-8') as file:
plugin_decoder = file.read() plugin_decoder = file.read()
plugin_decoder = Template(plugin_decoder).render({ plugin_decoder = Template(plugin_decoder).render({
'PAYLOAD_LEN': payload_len, 'PAYLOAD_LEN': payload_len,
'XOR_KEY': config.xor_key, 'XOR_KEY': config.xor_key,
}) })
#filepath = "data/plugins/executor/{}.c".format(exec_style.value) # C Template: peb_walk
#with open("data/plugins/executor/direct_1.c", "r", encoding='utf-8') as file: if settings.source_style == SourceStyle.peb_walk:
# plugin_executor = file.read() with open(settings.template_path, 'r', encoding='utf-8') as file:
# plugin_executor = Template(plugin_executor).render({ template_content = file.read()
# 'PAYLOAD_LEN': payload_len, observer.add_text_file("main_c_template", template_content)
# })
if source_style == SourceStyle.peb_walk:
if use_templates:
with open(PATH_PEB_WALK + "template.c", 'r', encoding='utf-8') as file:
template_content = file.read()
observer.add_text_file("main_c_template", template_content)
template = Template(template_content) template = Template(template_content)
rendered_template = template.render({ rendered_template = template.render({
'plugin_allocator': plugin_allocator, 'plugin_decoder': plugin_decoder,
'plugin_decoder': plugin_decoder, 'PAYLOAD_LEN': payload_len,
'plugin_executor': plugin_executor, })
'PAYLOAD_LEN': payload_len, with open(settings.main_c_path, "w", encoding='utf-8') as file:
}) file.write(rendered_template)
with open(main_c_file, "w", encoding='utf-8') as file: observer.add_text_file("main_c_rendered", rendered_template)
file.write(rendered_template)
observer.add_text_file("main_c_rendered", rendered_template)
# TODO PEB # C Template: iat_reuse
shutil.copy(PATH_PEB_WALK + "peb_lookup.h", f"{build_dir}/peb_lookup.h") elif settings.source_style == SourceStyle.iat_reuse:
else: with open(PATH_IAT_REUSE + "template.c", 'r', encoding='utf-8') as file:
observer.add_text_file("main_c", file_readall_text(PATH_PEB_WALK + "main.c")) template_content = file.read()
shutil.copy(PATH_PEB_WALK + "main.c", main_c_file) observer.add_text_file("main_c_template", template_content)
# TODO PEB template = Template(template_content)
shutil.copy(PATH_PEB_WALK + "peb_lookup.h", f"{build_dir}/peb_lookup.h") rendered_template = template.render({
'plugin_decoder': plugin_decoder,
'PAYLOAD_LEN': payload_len,
})
with open(settings.main_c_path, "w", encoding='utf-8') as file:
file.write(rendered_template)
observer.add_text_file("main_c_rendered", rendered_template)
elif source_style == SourceStyle.iat_reuse: else:
if use_templates: raise Exception("Invalid source style: {}".format(settings.source_style))
with open(PATH_IAT_REUSE + "template.c", 'r', encoding='utf-8') as file:
template_content = file.read()
observer.add_text_file("main_c_template", template_content)
template = Template(template_content)
rendered_template = template.render({
'plugin_allocator': plugin_allocator,
'plugin_decoder': plugin_decoder,
'plugin_executor': plugin_executor,
'PAYLOAD_LEN': payload_len,
})
with open(main_c_file, "w", encoding='utf-8') as file:
file.write(rendered_template)
observer.add_text_file("main_c_rendered", rendered_template)
else:
observer.add_text_file("main_c", file_readall_text(PATH_IAT_REUSE + "main.c"))
shutil.copy(PATH_IAT_REUSE + "main.c", main_c_file)
-9
View File
@@ -1,9 +1,7 @@
import requests as req import requests as req
import logging import logging
import brotli import brotli
import os
import time import time
import shutil
from config import config from config import config
@@ -32,10 +30,3 @@ def scannerDetectsBytes(data: bytes, filename: str, useBrotli=True, verify=False
raise Exception("Server error, aborting") raise Exception("Server error, aborting")
return jsonRes return jsonRes
def main():
with open("data/exes/7z-verify.exe", "rb") as f:
data = f.read()
res = scannerDetectsBytes(data, "test.exe")
print("Answer: {}".format(res))
+25 -28
View File
@@ -18,7 +18,6 @@ from model.project import Project
from model.settings import Settings from model.settings import Settings
from model.defs import * from model.defs import *
from log import setup_logging from log import setup_logging
from utils import delete_all_files_in_directory
def main(): def main():
@@ -104,25 +103,29 @@ def main():
def start(settings: Settings) -> int: def start(settings: Settings) -> int:
"""Main entry point for the application. Will handle log files and cleanup""" """Main entry point for the application. Will handle log files and cleanup"""
settings.prep()
# Delete: all old files # Delete: all old files
if settings.cleanup_files_on_start: if settings.cleanup_files_on_start:
clean_files() clean_files(settings)
delete_all_files_in_directory(f"{logs_dir}/")
# And logs # And logs
observer.reset() observer.reset()
# Do the thing and catch errors
try: try:
start_real(settings) start_real(settings)
except Exception as e: except Exception as e:
logger.error(f'Error compiling: {e}') logger.error(f'Error compiling: {e}')
write_logs() write_logs(settings.main_dir)
return 1 return 1
# Cleanup files # Cleanup files
if settings.cleanup_files_on_exit: if settings.cleanup_files_on_exit:
clean_files() clean_files(settings)
write_logs() # Write logs (on success)
write_logs(settings.main_dir)
return 0 return 0
@@ -142,19 +145,13 @@ def start_real(settings: Settings):
)) ))
# Create: Carrier C source files from template (C->C) # Create: Carrier C source files from template (C->C)
phases.templater.create_c_from_template( phases.templater.create_c_from_template(settings, project.payload.len)
source_style = settings.source_style,
alloc_style = settings.alloc_style,
exec_style = settings.exec_style,
decoder_style= settings.decoder_style,
payload_len = project.payload.len,
)
# Compile: Carrier to .asm (C -> ASM) # Compile: Carrier to .asm (C -> ASM)
if settings.generate_asm_from_c: if settings.generate_asm_from_c:
phases.compiler.compile( phases.compiler.compile(
c_in = main_c_file, c_in = settings.main_c_path,
asm_out = main_asm_file, asm_out = settings.main_asm_path,
payload_len = project.payload.len, payload_len = project.payload.len,
carrier = project.carrier, carrier = project.carrier,
source_style = project.settings.source_style, source_style = project.settings.source_style,
@@ -164,15 +161,15 @@ def start_real(settings: Settings):
# Assemble: Assemble .asm to .shc (ASM -> SHC) # Assemble: Assemble .asm to .shc (ASM -> SHC)
if settings.generate_shc_from_asm: if settings.generate_shc_from_asm:
phases.assembler.asm_to_shellcode( phases.assembler.asm_to_shellcode(
asm_in = main_asm_file, asm_in = settings.main_asm_path,
build_exe = main_exe_file, build_exe = settings.main_exe_path,
shellcode_out = main_shc_file) shellcode_out = settings.main_shc_path)
# Merge: shellcode/loader with payload (SHC + PAYLOAD -> SHC) # Merge: shellcode/loader with payload (SHC + PAYLOAD -> SHC)
if settings.dataref_style == DataRefStyle.APPEND: if settings.dataref_style == DataRefStyle.APPEND:
phases.assembler.merge_loader_payload( phases.assembler.merge_loader_payload(
shellcode_in = main_shc_file, shellcode_in = settings.main_shc_path,
shellcode_out = main_shc_file, shellcode_out = settings.main_shc_path,
payload_data = project.payload.payload_data, payload_data = project.payload.payload_data,
decoder_style = settings.decoder_style) decoder_style = settings.decoder_style)
@@ -181,12 +178,12 @@ def start_real(settings: Settings):
logger.info("--[ RWX section {} found. Will obfuscate loader+payload and inject into it".format( logger.info("--[ RWX section {} found. Will obfuscate loader+payload and inject into it".format(
project.exe_host.rwx_section.Name.decode().rstrip('\x00') project.exe_host.rwx_section.Name.decode().rstrip('\x00')
)) ))
obfuscate_shc_loader(main_shc_file, main_shc_file + ".sgn") obfuscate_shc_loader(settings.main_shc_path, settings.main_shc_path + ".sgn")
observer.add_code_file("payload_sgn", file_readall_binary(main_shc_file + ".sgn")) observer.add_code_file("payload_sgn", file_readall_binary(settings.main_shc_path + ".sgn"))
shutil.move(main_shc_file + ".sgn", main_shc_file) shutil.move(settings.main_shc_path + ".sgn", settings.main_shc_path)
# inject merged loader into an exe # inject merged loader into an exe
phases.injector.inject_exe(main_shc_file, settings, project) phases.injector.inject_exe(settings.main_shc_path, settings, project)
observer.add_code_file("exe_final", extract_code_from_exe_file_ep(settings.inject_exe_out, 300)) observer.add_code_file("exe_final", extract_code_from_exe_file_ep(settings.inject_exe_out, 300))
if config.get("avred_server") != "": if config.get("avred_server") != "":
@@ -210,21 +207,21 @@ def start_real(settings: Settings):
], check=True) ], check=True)
def write_logs(): def write_logs(working_dir: str):
# Our log output # Our log output
with open(f"{logs_dir}/supermega.log", "w") as f: with open(f"{working_dir}log-supermega.log", "w") as f:
for line in observer.get_logs(): for line in observer.get_logs():
f.write(line + "\n") f.write(line + "\n")
# Stdout of executed commands # Stdout of executed commands
with open(f"{logs_dir}/cmdoutput.log", "w") as f: with open(f"{working_dir}log-cmdoutput.log", "w") as f:
for line in observer.get_cmd_output(): for line in observer.get_cmd_output():
f.write(line) f.write(line)
# Write all files # Write all files
idx = 0 idx = 0
for name, data in observer.files: for name, data in observer.files:
with open(f"{logs_dir}/{idx}-{name}", "w") as f: with open(f"{working_dir}log-{idx}-{name}", "w") as f:
f.write(data) f.write(data)
idx += 1 idx += 1
+4 -4
View File
@@ -22,7 +22,7 @@ def main():
settings.source_style = SourceStyle.peb_walk settings.source_style = SourceStyle.peb_walk
settings.inject_mode = InjectStyle.ChangeEntryPoint settings.inject_mode = InjectStyle.ChangeEntryPoint
settings.inject_exe_in = PATH_EXES + "7z.exe" settings.inject_exe_in = PATH_EXES + "7z.exe"
settings.inject_exe_out = PATH_EXES + "7z-verify.exe" settings.inject_exe_out = PATH_EXES + "7z.verify.exe"
if start(settings) != 0: if start(settings) != 0:
print("Error") print("Error")
return 1 return 1
@@ -31,7 +31,7 @@ def main():
settings.source_style = SourceStyle.peb_walk settings.source_style = SourceStyle.peb_walk
settings.inject_mode = InjectStyle.BackdoorCallInstr settings.inject_mode = InjectStyle.BackdoorCallInstr
settings.inject_exe_in = PATH_EXES + "7z.exe" settings.inject_exe_in = PATH_EXES + "7z.exe"
settings.inject_exe_out = PATH_EXES + "7z-verify.exe" settings.inject_exe_out = PATH_EXES + "7z.verify.exe"
if start(settings) != 0: if start(settings) != 0:
print("Error") print("Error")
return 1 return 1
@@ -40,7 +40,7 @@ def main():
settings.source_style = SourceStyle.iat_reuse settings.source_style = SourceStyle.iat_reuse
settings.inject_mode = InjectStyle.ChangeEntryPoint settings.inject_mode = InjectStyle.ChangeEntryPoint
settings.inject_exe_in = PATH_EXES + "procexp64.exe" settings.inject_exe_in = PATH_EXES + "procexp64.exe"
settings.inject_exe_out = PATH_EXES + "procexp64-verify.exe" settings.inject_exe_out = PATH_EXES + "procexp64.verify.exe"
if start(settings) != 0: if start(settings) != 0:
print("Error") print("Error")
return 1 return 1
@@ -49,7 +49,7 @@ def main():
settings.source_style = SourceStyle.iat_reuse settings.source_style = SourceStyle.iat_reuse
settings.inject_mode = InjectStyle.ChangeEntryPoint settings.inject_mode = InjectStyle.ChangeEntryPoint
settings.inject_exe_in = PATH_EXES + "procexp64.exe" settings.inject_exe_in = PATH_EXES + "procexp64.exe"
settings.inject_exe_out = PATH_EXES + "procexp64-verify.exe" settings.inject_exe_out = PATH_EXES + "procexp64.verify.exe"
if start(settings) != 0: if start(settings) != 0:
print("Error") print("Error")
return 1 return 1
View File
View File