1

我可以通过 CreateProcessAsUser 从我在这里找到的代码中创建一个新进程: https ://odetocode.com/blogs/scott/archive/2004/10/28/createprocessasuser.aspx

它工作正常,但新进程不包含由 IIS Asp.net Impersonation 模拟的新用户的 Kerberos 票证。我知道 IIS 有 Kerberos 票,我只是不知道如何以编程方式将它从父工作进程获取到我生成的调用 OpenSSH 的新进程。

编辑:使用 @Steve 提到的 DupliateHandlers 函数更新了 Impersonation 块

var CurrentIdentity = ((WindowsIdentity)User.Identity).Token;
            IntPtr parentHandle = IntPtr.Zero;

            QuerySecurityContextToken(ref CurrentIdentity, out parentHandle);


            using (WindowsImpersonationContext impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate())
            {
                IntPtr childHandle = CreateProcessAsUser();

                IntPtr lpTargetHandle = IntPtr.Zero;

                if (CloneParentProcessToken.DuplicateHandle(parentHandle, null, childHandle, out lpTargetHandle,
                    null, true, DuplicateOptions.DUPLICATE_SAME_ACCESS, ) > 0)
                {
                    if(ImpersonateLoggedOnUser(lpTargetHandle))
                    {

                    }
                }


                impersonationContext.Undo();
            }

private void CreateProcessAsUser()
    {
        IntPtr hToken = WindowsIdentity.GetCurrent().Token;
        IntPtr hDupedToken = IntPtr.Zero;

        ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();

        try
        {
            ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
            sa.Length = Marshal.SizeOf(sa);

            bool result = ProcessUtility.DuplicateTokenEx(
                  hToken,
                  ProcessUtility.GENERIC_ALL_ACCESS,
                  ref sa,
                  (int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                  (int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
                  ref hDupedToken
               );

            if (!result)
            {
                throw new ApplicationException("DuplicateTokenEx failed");
            }


            ProcessUtility.STARTUPINFO si = new ProcessUtility.STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = String.Empty;

            result = ProcessUtility.CreateProcessAsUser(
                                 hDupedToken,
                                 null,
                                 "powershell.exe -Command SSHCommand.ps1",
                                 ref sa, ref sa,
                                 true, 0, IntPtr.Zero,
                                 @"C:\", ref si, ref pi
                           );

            if (!result)
            {
                int error = Marshal.GetLastWin32Error();
                string message = String.Format("CreateProcessAsUser Error: {0}", error);
                throw new ApplicationException(message);
            }
        }
        finally
        {
            if (pi.hProcess != IntPtr.Zero)
                ProcessUtility.CloseHandle(pi.hProcess);
            if (pi.hThread != IntPtr.Zero)
                ProcessUtility.CloseHandle(pi.hThread);
            if (hDupedToken != IntPtr.Zero)
                ProcessUtility.CloseHandle(hDupedToken);
        }
    }

}

public class ProcessUtility
{
    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public Int32 dwProcessID;
        public Int32 dwThreadID;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public Int32 Length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }

    public enum SECURITY_IMPERSONATION_LEVEL
    {
        SecurityAnonymous,
        SecurityIdentification,
        SecurityImpersonation,
        SecurityDelegation
    }

    public enum TOKEN_TYPE
    {
        TokenPrimary = 1,
        TokenImpersonation
    }

    public const int GENERIC_ALL_ACCESS = 0x10000000;
    public const int TOKEN_ASSIGN_PRIMARY = 0x0001;

    [
       DllImport("kernel32.dll",
          EntryPoint = "CloseHandle", SetLastError = true,
          CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)
    ]
    public static extern bool CloseHandle(IntPtr handle);

    [
       DllImport("advapi32.dll",
          EntryPoint = "CreateProcessAsUser", SetLastError = true,
          CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)
    ]
    public static extern bool
       CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
                           ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,
                           bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,
                           string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
                           ref PROCESS_INFORMATION lpProcessInformation);

    [
       DllImport("advapi32.dll",
          EntryPoint = "DuplicateTokenEx")
    ]
    public static extern bool
       DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,
                        ref SECURITY_ATTRIBUTES lpThreadAttributes,
                        Int32 ImpersonationLevel, Int32 dwTokenType,
                        ref IntPtr phNewToken);
}
4

1 回答 1

0

这应该是评论,但我无法添加评论。我不知道这是否有任何区别,但我认为您的 STARTUPINFO 结构在 dwXSize 之后缺少元素 dwYSize

于 2019-08-23T22:22:30.537 回答