C ProcessAsUser
阅读原文时间:2023年07月13日阅读:2

class Interop
{
public static void CreateProcess(string app, string path)
{
bool result;
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero;

        PROCESS\_INFORMATION pi = new PROCESS\_INFORMATION();  
        SECURITY\_ATTRIBUTES sa = new SECURITY\_ATTRIBUTES();  
        sa.Length = Marshal.SizeOf(sa);

        STARTUPINFO si = new STARTUPINFO();  
        si.cb = Marshal.SizeOf(si);

        int dwSessionID = WTSGetActiveConsoleSessionId();  
        result = WTSQueryUserToken(dwSessionID, out hToken);

        if (!result)  
        {  
            ShowMessageBox("WTSQueryUserToken failed", "AlertService Message");  
        }

        result = DuplicateTokenEx(  
               hToken,  
               GENERIC\_ALL\_ACCESS,  
               ref sa,  
               (int)SECURITY\_IMPERSONATION\_LEVEL.SecurityIdentification,  
               (int)TOKEN\_TYPE.TokenPrimary,  
               ref hDupedToken  
            );

        if (!result)  
        {  
            ShowMessageBox("DuplicateTokenEx failed", "AlertService Message");  
        }

        IntPtr lpEnvironment = IntPtr.Zero;  
        result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);

        if (!result)  
        {  
            ShowMessageBox("CreateEnvironmentBlock failed", "AlertService Message");  
        }

        result = CreateProcessAsUser(  
                              hDupedToken,  
                              app,  
                              String.Empty,  
                              ref sa, ref sa,  
                              false, , IntPtr.Zero,  
                              null, ref si, ref pi);

        if (!result)  
        {  
            int error = Marshal.GetLastWin32Error();  
            string message = String.Format("CreateProcessAsUser Error: {0}", error);  
            ShowMessageBox(message, "AlertService Message");  
        }

        if (pi.hProcess != IntPtr.Zero)  
            CloseHandle(pi.hProcess);  
        if (pi.hThread != IntPtr.Zero)  
            CloseHandle(pi.hThread);  
        if (hDupedToken != IntPtr.Zero)  
            CloseHandle(hDupedToken);  
    }

    \[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 = ,  
        TokenImpersonation  
    }

    public const int GENERIC\_ALL\_ACCESS = 0x10000000;

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

    \[DllImport("advapi32.dll", 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", SetLastError = true)\]  
    public static extern bool DuplicateTokenEx(  
        IntPtr hExistingToken,  
        Int32 dwDesiredAccess,  
        ref SECURITY\_ATTRIBUTES lpThreadAttributes,  
        Int32 ImpersonationLevel,  
        Int32 dwTokenType,  
        ref IntPtr phNewToken);

    \[DllImport("wtsapi32.dll", SetLastError = true)\]  
    public static extern bool WTSQueryUserToken(  
        Int32 sessionId,  
        out IntPtr Token);

    \[DllImport("userenv.dll", SetLastError = true)\]  
    static extern bool CreateEnvironmentBlock(  
        out IntPtr lpEnvironment,  
        IntPtr hToken,  
        bool bInherit);

    public static IntPtr WTS\_CURRENT\_SERVER\_HANDLE = IntPtr.Zero;  
    public static void ShowMessageBox(string message, string title)  
    {  
        int resp = ;  
        WTSSendMessage(  
            WTS\_CURRENT\_SERVER\_HANDLE,  
            WTSGetActiveConsoleSessionId(),  
            title, title.Length,  
            message, message.Length,  
            , , out resp, false);  
    }

    \[DllImport("kernel32.dll", SetLastError = true)\]  
    public static extern int WTSGetActiveConsoleSessionId();

    \[DllImport("wtsapi32.dll", SetLastError = true)\]  
    public static extern bool WTSSendMessage(  
        IntPtr hServer,  
        int SessionId,  
        String pTitle,  
        int TitleLength,  
        String pMessage,  
        int MessageLength,  
        int Style,  
        int Timeout,  
        out int pResponse,  
        bool bWait);  
}

[StructLayout(LayoutKind.Sequential)]
struct STARTUPINFO
{
public Int32 cb;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpReserved;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpDesktop;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpTitle;
public UInt32 dwX;
public UInt32 dwY;
public UInt32 dwXSize;
public UInt32 dwYSize;
public UInt32 dwXCountChars;
public UInt32 dwYCountChars;
public UInt32 dwFillAttribute;
public UInt32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public HandleRef hStdInput;
public HandleRef hStdOutput;
public HandleRef hStdError;
}

     const int NORMAL\_PRIORITY\_CLASS = 0x00000020;

     struct PROCESS\_INFORMATION  
     {  
         public HandleRef hProcess;  
         public HandleRef hThread;  
         public UInt32 dwProcessId;  
         public UInt32 dwThreadId;  
     }

     struct SECURITY\_ATTRIBUTES  
     {  
         public UInt32 nLength;  
         public IntPtr lpSecurityDescriptor;  
         public Boolean bInheritHandle;  
     }

     \[DllImport("advapi32.dll", CharSet = CharSet.Unicode)\]  
     static extern Boolean CreateProcessAsUser(  
     IntPtr hToken,  
     String lpApplicationName,  
     String lpCommandLine,  
     IntPtr lpProcessAttributes,  
     IntPtr lpThreadAttributes,  
    Boolean bInheritHandles,  
    UInt32 dwCreationFlags,  
     IntPtr lpEnvironment,  
     String lpCurrentDirectory,  
     ref STARTUPINFO lpStartupInfo,  
     out PROCESS\_INFORMATION lpProcessInformation);

     \[DllImport("advapi32.dll", CharSet = CharSet.Unicode)\]  
     static extern Boolean LogonUser(  
     String lpszUsername,  
     String lpszDomain,  
     String lpszPassword,  
     Int32 dwLogonType,  
     Int32 dwLogonProvider,  
     ref IntPtr phToken  
     );  
     const int LOGON32\_LOGON\_INTERACTIVE = ;

     public void Execute(string File)  
     {  
         try  
         {  
             //unsafe  
             {  
                 PROCESS\_INFORMATION pi = new PROCESS\_INFORMATION();

                 STARTUPINFO si = new STARTUPINFO();  
                 si.cb = Marshal.SizeOf(si);  
                 si.lpDesktop = "winsta0\\\\default";

                 IntPtr hToken = new IntPtr();  
                 if (LogonUser("auser", "mydomain", "Passw0rd!",  
                     LOGON32\_LOGON\_INTERACTIVE, , ref hToken))  
                 {  
                     Boolean bResult = CreateProcessAsUser(  
                         hToken,  
                         File, // file to execute  
                         null, // command line  
                         IntPtr.Zero, // pointer to process SECURITY\_ATTRIBUTES  
                         IntPtr.Zero, // pointer to thread SECURITY\_ATTRIBUTES  
                         false, // handles are not inheritable  
                         , // creation flags  
                         IntPtr.Zero, // pointer to new environment block  
                         null, // name of current directory  
                         ref si, // pointer to STARTUPINFO structure  
                         out pi // receives information about new process  
                         );

                     if (bResult)  
                     {  
                     }  
                 }  
             }  
         }  
         catch(Exception e)  
         {  
         }  
     }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace WindowsService1
{
public class WinAPI_Interop
{
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
///

/// 服务程序执行消息提示,前台MessageBox.Show ///
/// 消息内容
/// 标题
public static void ShowServiceMessage(string message, string title)
{
int resp = ;
WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId(), title, title.Length, message, message.Length, , , out resp, false);
}

    \[DllImport("kernel32.dll", SetLastError = true)\]  
    public static extern int WTSGetActiveConsoleSessionId();

    \[DllImport("wtsapi32.dll", SetLastError = true)\]  
    public static extern bool WTSSendMessage(IntPtr hServer, int SessionId, String pTitle, int TitleLength, String pMessage, int MessageLength,int Style, int Timeout, out int pResponse, bool bWait);  
    #region P/Invoke WTS APIs  
    private enum WTS\_CONNECTSTATE\_CLASS  
    {  
        WTSActive,  
        WTSConnected,  
        WTSConnectQuery,  
        WTSShadow,  
        WTSDisconnected,  
        WTSIdle,  
        WTSListen,  
        WTSReset,  
        WTSDown,  
        WTSInit  
    }

    \[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)\]  
    private struct WTS\_SESSION\_INFO  
    {  
        public UInt32 SessionID;  
        public string pWinStationName;  
        public WTS\_CONNECTSTATE\_CLASS State;  
    }

    \[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)\]  
    static extern bool WTSEnumerateSessions(  
        IntPtr hServer,  
        \[MarshalAs(UnmanagedType.U4)\] UInt32 Reserved,  
        \[MarshalAs(UnmanagedType.U4)\] UInt32 Version,  
        ref IntPtr ppSessionInfo,  
        \[MarshalAs(UnmanagedType.U4)\] ref UInt32 pSessionInfoCount  
        );

    \[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)\]  
    static extern void WTSFreeMemory(IntPtr pMemory);

    \[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)\]  
    static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);  
    #endregion

    #region P/Invoke CreateProcessAsUser  
    /// <summary>  
    /// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser.  
    /// </summary>  
    ///  

    \[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)\]  
    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 dwYSize;  
        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, CharSet = CharSet.Auto)\]  
    struct PROCESS\_INFORMATION  
    {  
        public IntPtr hProcess;  
        public IntPtr hThread;  
        public int dwProcessId;  
        public int dwThreadId;  
    }

    /// <summary>  
    /// 以当前登录的windows用户(角色权限)运行指定程序进程  
    /// </summary>  
    /// <param name="hToken"></param>  
    /// <param name="lpApplicationName">指定程序(全路径)</param>  
    /// <param name="lpCommandLine">参数</param>  
    /// <param name="lpProcessAttributes">进程属性</param>  
    /// <param name="lpThreadAttributes">线程属性</param>  
    /// <param name="bInheritHandles"></param>  
    /// <param name="dwCreationFlags"></param>  
    /// <param name="lpEnvironment"></param>  
    /// <param name="lpCurrentDirectory"></param>  
    /// <param name="lpStartupInfo">程序启动属性</param>  
    /// <param name="lpProcessInformation">最后返回的进程信息</param>  
    /// <returns>是否调用成功</returns>  
    \[DllImport("ADVAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)\]  
    static extern bool CreateProcessAsUser(IntPtr hToken,string lpApplicationName,string lpCommandLine,IntPtr lpProcessAttributes,IntPtr lpThreadAttributes,  
                                                  bool bInheritHandles,uint dwCreationFlags,string lpEnvironment,string lpCurrentDirectory,  
                                                  ref STARTUPINFO lpStartupInfo,out PROCESS\_INFORMATION lpProcessInformation);

    \[DllImport("KERNEL32.DLL", SetLastError = true, CharSet = CharSet.Auto)\]  
    static extern bool CloseHandle(IntPtr hHandle);  
    #endregion

    /// <summary>  
    /// 以当前登录系统的用户角色权限启动指定的进程  
    /// </summary>  
    /// <param name="ChildProcName">指定的进程(全路径)</param>  
    public static void CreateProcess(string ChildProcName)  
    {  
        IntPtr ppSessionInfo = IntPtr.Zero;  
        UInt32 SessionCount = ;  
        if (WTSEnumerateSessions(  
                                (IntPtr)WTS\_CURRENT\_SERVER\_HANDLE,  // Current RD Session Host Server handle would be zero.  
                                ,  // This reserved parameter must be zero.  
                                ,  // The version of the enumeration request must be 1.  
                                ref ppSessionInfo, // This would point to an array of session info.  
                                ref SessionCount  // This would indicate the length of the above array.  
                                ))  
        {  
            for (int nCount = ; nCount < SessionCount; nCount++)  
            {  
                WTS\_SESSION\_INFO tSessionInfo = (WTS\_SESSION\_INFO)Marshal.PtrToStructure(ppSessionInfo + nCount \* Marshal.SizeOf(typeof(WTS\_SESSION\_INFO)), typeof(WTS\_SESSION\_INFO));  
                if (WTS\_CONNECTSTATE\_CLASS.WTSActive == tSessionInfo.State)  
                {  
                    IntPtr hToken = IntPtr.Zero;  
                    if (WTSQueryUserToken(tSessionInfo.SessionID, out hToken))  
                    {  
                        PROCESS\_INFORMATION tProcessInfo;  
                        STARTUPINFO tStartUpInfo = new STARTUPINFO();  
                        tStartUpInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));  
                        bool ChildProcStarted = CreateProcessAsUser(  
                                                                    hToken,             // Token of the logged-on user.  
                                                                    ChildProcName,      // Name of the process to be started.  
                                                                    null,               // Any command line arguments to be passed.  
                                                                    IntPtr.Zero,        // Default Process' attributes.  
                                                                    IntPtr.Zero,        // Default Thread's attributes.  
                                                                    false,              // Does NOT inherit parent's handles.  
                                                                    ,                  // No any specific creation flag.  
                                                                    null,               // Default environment path.  
                                                                    null,               // Default current directory.  
                                                                    ref tStartUpInfo,   // Process Startup Info.  
                                                                    out tProcessInfo    // Process information to be returned.  
                                                 );  
                        if (ChildProcStarted)  
                        {  
                            CloseHandle(tProcessInfo.hThread);  
                            CloseHandle(tProcessInfo.hProcess);  
                        }  
                        else  
                        {  
                            ShowServiceMessage("CreateProcessAsUser失败", "CreateProcess");  
                        }  
                        CloseHandle(hToken);  
                        break;  
                    }  
                }  
            }  
            WTSFreeMemory(ppSessionInfo);  
        }  
    }  
}  

}

OnStart(string[] args) { //Interop.ShowMessageBox("This a message from AlertService.","AlertService Message");
            WinAPI_Interop.CreateProcess(@"E:\work\box\GreenlandBox\BinFiles\ClientBin\BufferBox.exe");
//Interop.CreateProcess("cmd.exe", @"C:\Windows\System32\");
}

-----------------------------------------------------------------------------

do
{
// if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hThisToken ))
// {
// PrintfDbgStr(TEXT("OpenProcessToken error !error code:%d\n"),GetLastError());
// bSuccess = FALSE;
// break;
// }
// if(!SetPrivilege(hThisToken,SE_TCB_NAME,TRUE))
// {
// PrintfDbgStr(TEXT("SetPrivilege error !error code:%d\n"),GetLastError());
// bSuccess = FALSE;
// break;
// }
DWORD dwSessionId = WTSGetActiveConsoleSessionId();
if(!WTSQueryUserToken(dwSessionId,&hToken))
{
PrintfDbgStr(TEXT("WTSQueryUserToken error !error code:%d\n"),GetLastError());
bSuccess = FALSE;
break;
}

    STARTUPINFO si;  
    PROCESS\_INFORMATION pi;  
    ZeroMemory(&si,sizeof(STARTUPINFO));  
    ZeroMemory(&pi,sizeof(PROCESS\_INFORMATION));  
    si.cb = sizeof(STARTUPINFO);  
    si.lpDesktop = \_T("WinSta0\\\\Default");  
    si.wShowWindow = TRUE;  
    si.dwFlags     = STARTF\_USESHOWWINDOW;

    LPVOID pEnv = NULL;  
    DWORD dwCreationFlag = NORMAL\_PRIORITY\_CLASS | CREATE\_NEW\_CONSOLE;  
    if(!CreateProcessAsUser(hToken,NULL,pBuf,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))  
    {  
        PrintfDbgStr(TEXT("CreateProcessAsUser error !error code:%d\\n"),GetLastError());  
        bSuccess = FALSE;  
        break;  
    }

}while();

创建的进程不是管理员权限的,因为是调用了用户的令牌创建的进程。

HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
do
{
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken))
{
if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
{
DWORD dwSessionId = WTSGetActiveConsoleSessionId();
if(!SetTokenInformation(hTokenDup,TokenSessionId,&dwSessionId,sizeof(DWORD)))
{
PrintfDbgStr(TEXT("SetTokenInformation error !error code:%d\n"),GetLastError());
bSuccess = FALSE;
break;
}

            STARTUPINFO si;  
            PROCESS\_INFORMATION pi;  
            ZeroMemory(&si,sizeof(STARTUPINFO));  
            ZeroMemory(&pi,sizeof(PROCESS\_INFORMATION));  
            si.cb = sizeof(STARTUPINFO);  
            si.lpDesktop = \_T("WinSta0\\\\Default");  
            si.wShowWindow = SW\_SHOW;  
            si.dwFlags     =   STARTF\_USESHOWWINDOW /\*|STARTF\_USESTDHANDLES\*/;

            LPVOID pEnv = NULL;  
            DWORD dwCreationFlag = NORMAL\_PRIORITY\_CLASS | CREATE\_NEW\_CONSOLE | CREATE\_UNICODE\_ENVIRONMENT;  
            if(!CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))  
            {  
                PrintfDbgStr(TEXT("CreateEnvironmentBlock error !error code:%d\\n"),GetLastError());  
                bSuccess = FALSE;  
                break;  
            }

            if(!CreateProcessAsUser(hTokenDup,NULL,pBuf,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))  
            {  
                PrintfDbgStr(TEXT("CreateProcessAsUser error !error code:%d\\n"),GetLastError());  
                bSuccess = FALSE;  
                break;  
            }

            if(pEnv)  
            {  
                DestroyEnvironmentBlock(pEnv);  
            }  
        }  
        else  
        {  
            PrintfDbgStr(TEXT("DuplicateTokenEx error !error code:%d\\n"),GetLastError());  
            bSuccess = FALSE;  
            break;  
        }

    }  
    else  
    {  
        PrintfDbgStr(TEXT("cannot get administror!error code:%d\\n"),GetLastError());  
        bSuccess = FALSE;  
        break;  
    }  
}while();

if(hTokenDup != NULL && hTokenDup != INVALID\_HANDLE\_VALUE)  
    CloseHandle(hTokenDup);  
if(hToken != NULL && hToken != INVALID\_HANDLE\_VALUE)  
    CloseHandle(hToken);

管理员权限  注意dwCreationFlag和si的参数设定