mirror of
https://github.com/dobin/SuperMega
synced 2026-06-03 01:27:11 +00:00
refactor: cleanup
This commit is contained in:
@@ -84,7 +84,7 @@ def project(name):
|
|||||||
if superpe.get_section_by_name(".rdata") != None:
|
if superpe.get_section_by_name(".rdata") != None:
|
||||||
data_sect_size = superpe.get_section_by_name(".rdata").virt_size
|
data_sect_size = superpe.get_section_by_name(".rdata").virt_size
|
||||||
else:
|
else:
|
||||||
logger.warn("No .rdata section found in {}".format(project.settings.inject_exe_in))
|
logger.warning("No .rdata section found in {}".format(project.settings.inject_exe_in))
|
||||||
|
|
||||||
has_rodata_section = superpe.has_rodata_section()
|
has_rodata_section = superpe.has_rodata_section()
|
||||||
if has_rodata_section:
|
if has_rodata_section:
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ class RangeManager:
|
|||||||
self.intervals.merge_overlaps(strict=False)
|
self.intervals.merge_overlaps(strict=False)
|
||||||
|
|
||||||
|
|
||||||
|
def print_all(self):
|
||||||
|
logger.info("Min: {} Max: {}".format(self.min, self.max))
|
||||||
|
for i in self.intervals:
|
||||||
|
logger.info("Interval: {}-{}".format(i.begin, i.end))
|
||||||
|
|
||||||
|
|
||||||
def add_range(self, start, end):
|
def add_range(self, start, end):
|
||||||
if start < self.min or end > self.max:
|
if start < self.min or end > self.max:
|
||||||
raise ValueError("Ranges must be within 0x{:X} and 0x{:X}, not 0x{:X}/0x{:X}".format(
|
raise ValueError("Ranges must be within 0x{:X} and 0x{:X}, not 0x{:X}/0x{:X}".format(
|
||||||
@@ -33,6 +39,12 @@ class RangeManager:
|
|||||||
return (last_end + 1, start - 1)
|
return (last_end + 1, start - 1)
|
||||||
last_end = max(last_end, end)
|
last_end = max(last_end, end)
|
||||||
|
|
||||||
|
# at the end
|
||||||
|
if last_end < self.max:
|
||||||
|
return last_end
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_holes(self, hole_size):
|
def find_holes(self, hole_size):
|
||||||
sorted_intervals = sorted(self.intervals)
|
sorted_intervals = sorted(self.intervals)
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ class Observer():
|
|||||||
try:
|
try:
|
||||||
f.write(line + "\n")
|
f.write(line + "\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn("Error: {}".format(e))
|
logger.warning("Error: {}".format(e))
|
||||||
|
|
||||||
# Stdout of executed commands
|
# Stdout of executed commands
|
||||||
with open(f"{working_dir}log-cmdoutput.log", "w") as f:
|
with open(f"{working_dir}log-cmdoutput.log", "w") as f:
|
||||||
|
|||||||
+2
-33
@@ -45,10 +45,10 @@ class FunctionBackdoorer:
|
|||||||
it = IntervalTree()
|
it = IntervalTree()
|
||||||
it.addi(addr, addr+len(compiled_trampoline))
|
it.addi(addr, addr+len(compiled_trampoline))
|
||||||
if it.overlap(shellcode_addr, shellcode_addr+shellcode_len):
|
if it.overlap(shellcode_addr, shellcode_addr+shellcode_len):
|
||||||
logger.warn("Attempt to patch jump (0x{:X}-0x{:X}) to shellcode (0x{:X}-0x{:X}) but they overlap and probably dont work".format(
|
logger.warning("Attempt to patch jump (0x{:X}-0x{:X}) to shellcode (0x{:X}-0x{:X}) but they overlap and probably dont work".format(
|
||||||
addr, addr+len(compiled_trampoline), shellcode_addr, shellcode_addr+shellcode_len
|
addr, addr+len(compiled_trampoline), shellcode_addr, shellcode_addr+shellcode_len
|
||||||
))
|
))
|
||||||
logger.warn("Text section too small?")
|
logger.warning("Text section too small?")
|
||||||
|
|
||||||
# write
|
# write
|
||||||
#logger.info("Trampoline: {}".format(compiled_trampoline))
|
#logger.info("Trampoline: {}".format(compiled_trampoline))
|
||||||
@@ -108,34 +108,3 @@ class FunctionBackdoorer:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_trampoline(self, addr, shellcode_addr):
|
|
||||||
addrOffset = -1
|
|
||||||
|
|
||||||
if not self.superpe.is_64():
|
|
||||||
raise Exception("Not 64 bit")
|
|
||||||
reg = random.choice(['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi']).upper()
|
|
||||||
full_shellcode_addr = shellcode_addr + self.superpe.pe.OPTIONAL_HEADER.ImageBase
|
|
||||||
|
|
||||||
enc, count = self.ks.asm(f'MOV {reg}, 0x{full_shellcode_addr:X}')
|
|
||||||
for instr2 in cs.disasm(bytes(enc), 0):
|
|
||||||
addrOffset = len(instr2.bytes) - instr2.addr_size
|
|
||||||
break
|
|
||||||
|
|
||||||
jump = random.choice([
|
|
||||||
f'CALL {reg}',
|
|
||||||
|
|
||||||
#
|
|
||||||
# During my tests I found that CALL reg works stabily all the time, whereas below two gadgets
|
|
||||||
# are known to crash on seldom occassions.
|
|
||||||
#
|
|
||||||
|
|
||||||
#f'JMP {reg}',
|
|
||||||
#f'PUSH {reg} ; RET',
|
|
||||||
])
|
|
||||||
|
|
||||||
trampoline_text = f'MOV {reg}, 0x{full_shellcode_addr:X} ; {jump}'
|
|
||||||
trampoline_compiled, count = ks.asm(trampoline_text)
|
|
||||||
|
|
||||||
return trampoline_compiled, trampoline_text, addrOffset
|
|
||||||
|
|
||||||
+3
-3
@@ -199,8 +199,8 @@ class SuperPe():
|
|||||||
sizeOfReloc = 2 * len(relocs) + 2 * 4
|
sizeOfReloc = 2 * len(relocs) + 2 * 4
|
||||||
|
|
||||||
if sizeOfReloc >= self.getRemainingRelocsDirectorySize():
|
if sizeOfReloc >= self.getRemainingRelocsDirectorySize():
|
||||||
self.logger.warn('WARNING! Cannot add any more relocations to this file. Probably TLS Callback execution technique wont work.')
|
self.logger.warning('WARNING! Cannot add any more relocations to this file. Probably TLS Callback execution technique wont work.')
|
||||||
self.logger.warn(' Will try disabling relocations on output file. Expect corrupted executable though!')
|
self.logger.warning(' Will try disabling relocations on output file. Expect corrupted executable though!')
|
||||||
|
|
||||||
self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0
|
self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0
|
||||||
self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0
|
self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[SuperPe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0
|
||||||
@@ -269,7 +269,7 @@ class SuperPe():
|
|||||||
if self.pe.DIRECTORY_ENTRY_EXPORT.symbols == 0:
|
if self.pe.DIRECTORY_ENTRY_EXPORT.symbols == 0:
|
||||||
return []
|
return []
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn("get_exports_full(): No exports found in PE")
|
logger.debug("get_exports_full(): No exports found in PE")
|
||||||
return []
|
return []
|
||||||
res = []
|
res = []
|
||||||
for e in self.pe.DIRECTORY_ENTRY_EXPORT.symbols:
|
for e in self.pe.DIRECTORY_ENTRY_EXPORT.symbols:
|
||||||
|
|||||||
+2
-2
@@ -60,13 +60,13 @@ def inject_exe(main_shc: bytes, settings: Settings, carrier: Carrier):
|
|||||||
|
|
||||||
# Special case: DLL exported function direct overwrite
|
# Special case: DLL exported function direct overwrite
|
||||||
if superpe.is_dll() and settings.dllfunc != "" and carrier_invoke_style == CarrierInvokeStyle.ChangeEntryPoint:
|
if superpe.is_dll() and settings.dllfunc != "" and carrier_invoke_style == CarrierInvokeStyle.ChangeEntryPoint:
|
||||||
logger.warn("---[ Inject DLL: Overwrite exported function {} with shellcode".format(settings.dllfunc))
|
logger.warning("---[ Inject DLL: Overwrite exported function {} with shellcode".format(settings.dllfunc))
|
||||||
rva = superpe.getExportEntryPoint(settings.dllfunc)
|
rva = superpe.getExportEntryPoint(settings.dllfunc)
|
||||||
|
|
||||||
# Size and sanity checks
|
# Size and sanity checks
|
||||||
function_size = superpe.get_size_of_exported_function(settings.dllfunc)
|
function_size = superpe.get_size_of_exported_function(settings.dllfunc)
|
||||||
if shellcode_len >= function_size:
|
if shellcode_len >= function_size:
|
||||||
logger.warn("Shellcode larger than function: {} > {} exported function {}".format(
|
logger.warning("Shellcode larger than function: {} > {} exported function {}".format(
|
||||||
shellcode_len, function_size, settings.dllfunc
|
shellcode_len, function_size, settings.dllfunc
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user