8

ユーザー権限のみで呼び出されるC#アプリケーションを介して管理者権限でプログラムを実行しようとしています。

コード

        ProcessStartInfo psi;
        try
        {
            psi = new ProcessStartInfo(@"WINZIP32.EXE");

            psi.UseShellExecute = false;
            SecureString pw = new SecureString();
            pw.AppendChar('p');
            pw.AppendChar('a');
            pw.AppendChar('s');
            pw.AppendChar('s');   
            pw.AppendChar('w');
            pw.AppendChar('o');
            pw.AppendChar('r');
            pw.AppendChar('d');
            psi.Password = pw;
            psi.UserName = "administrator";

            Process.Start(psi);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

winzipを起動しますが、ユーザー権限のみを使用します。私が間違っていることはありますか、それともより高い権利でプロセスを開始することさえ可能ですか?

ありがとう!

編集:これが質問の背後にある理由です、多分それは私が実際に必要としているものを理解するのに役立ちます。

たとえば、winzipを使用して、コードのどこが間違っているかを一般的に把握しました。実際の問題は、当社が2つのバージョンのプログラムを使用していることです。ただし、いずれかのバージョンを開始する前に、(管理者権限を持つ)zippy32を使用してdllファイルをインポートする必要があります。ここで、ユーザーがバージョンを選択し、dllをインポートして、正しいアプリケーションを起動できるようにするプログラムを作成したいと思います。

4

3 に答える 3

10

ProcessStartInfo.UseShellExecuteをに設定しtrueProcessStartInfo.Verbrunas次のように設定する必要があります。

Process process = null;
ProcessStartInfo processStartInfo = new ProcessStartInfo();

processStartInfo.FileName = "WINZIP32.EXE";

processStartInfo.Verb = "runas";
processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;

process = Process.Start(processStartInfo);

これにより、アプリケーションが管理者として実行されます。ただし、UACはユーザーに確認を求めます。これが望ましくない場合は、マニフェストを追加して、ホストプロセスの特権を永続的に昇格させる必要があります。

于 2012-04-12T10:55:46.140 に答える
3

CreateProcessAsUser 関数(Win32 API)を使用して、別のユーザー (管理者であっても) としてプロセスを実行できます。CreateProcessAsUser は、偽装トークンであるユーザー トークンを最初のパラメーターとして受け入れます。

Windows DLL から関数をロードするには、DLLImport を使用する必要があります。

私のプロジェクトの 1 つで使用したこの実装例を見てください。

    [StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public uint dwProcessId;
    public uint dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    public bool bInheritHandle;
}

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

}

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

internal enum TOKEN_TYPE
{
    TokenPrimary = 1,
    TokenImpersonation
}

public class ProcessAsUser
{

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CreateProcessAsUser(
    IntPtr hToken,
    string lpApplicationName,
    string lpCommandLine,
    ref SECURITY_ATTRIBUTES lpProcessAttributes,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    bool bInheritHandles,
    uint dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
    private static extern bool DuplicateTokenEx(
    IntPtr hExistingToken,
    uint dwDesiredAccess,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    Int32 ImpersonationLevel,
    Int32 dwTokenType,
    ref IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(
    IntPtr ProcessHandle,
    UInt32 DesiredAccess,
    ref IntPtr TokenHandle);

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

    [DllImport("userenv.dll", SetLastError = true)]
    private static extern bool DestroyEnvironmentBlock(
    IntPtr lpEnvironment);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(
    IntPtr hObject);

    private const short SW_SHOW = 5;
    private const uint TOKEN_QUERY = 0x0008;
    private const uint TOKEN_DUPLICATE = 0x0002;
    private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
    private const int GENERIC_ALL_ACCESS = 0x10000000;
    private const int STARTF_USESHOWWINDOW = 0x00000001;
    private const int STARTF_FORCEONFEEDBACK = 0x00000040;
    private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
    private const int STARTF_RUNFULLSCREEN = 0x00000020;

    private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
    {
        bool result = false;

        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

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

        //if this member is NULL, the new process inherits the desktop
        //and window station of its parent process. If this member is
        //an empty string, the process does not inherit the desktop and
        //window station of its parent process; instead, the system
        //determines if a new desktop and window station need to be created.
        //If the impersonated user already has a desktop, the system uses the
        //existing desktop.

        si.lpDesktop = @"WinSta0\Default"; //Modify as needed
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
        si.wShowWindow = SW_SHOW;

        //Set other si properties as required.

        result = CreateProcessAsUser(
        token,
        null,
        cmdLine,
        ref saProcess,
        ref saThread,
        false,
        CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        null,
        ref si,
        out pi);

        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Debug.WriteLine(message);

        }

        return result;
    }

    /// <summary>
    /// LaunchProcess As User Overloaded for Window Mode 
    /// </summary>
    /// <param name="cmdLine"></param>
    /// <param name="token"></param>
    /// <param name="envBlock"></param>
    /// <param name="WindowMode"></param>
    /// <returns></returns>
    private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock,uint WindowMode)
    {
        bool result = false;

        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

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

        //if this member is NULL, the new process inherits the desktop
        //and window station of its parent process. If this member is
        //an empty string, the process does not inherit the desktop and
        //window station of its parent process; instead, the system
        //determines if a new desktop and window station need to be created.
        //If the impersonated user already has a desktop, the system uses the
        //existing desktop.

        si.lpDesktop = @"WinSta0\Default"; //Default Vista/7 Desktop Session
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;

        //Check the Startup Mode of the Process 
        if (WindowMode == 1)
            si.wShowWindow = SW_SHOW;
        else if (WindowMode == 2)
        { //Do Nothing
        }
        else if (WindowMode == 3)
            si.wShowWindow = 0; //Hide Window 
        else if (WindowMode == 4)
            si.wShowWindow = 3; //Maximize Window
        else if (WindowMode == 5)
            si.wShowWindow = 6; //Minimize Window
        else
            si.wShowWindow = SW_SHOW;


        //Set other si properties as required.
        result = CreateProcessAsUser(
        token,
        null,
        cmdLine,
        ref saProcess,
        ref saThread,
        false,
        CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        null,
        ref si,
        out pi);

        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Debug.WriteLine(message);

        }

        return result;
    }

    private static IntPtr GetPrimaryToken(int processId)
    {
        IntPtr token = IntPtr.Zero;
        IntPtr primaryToken = IntPtr.Zero;
        bool retVal = false;
        Process p = null;

        try
        {
            p = Process.GetProcessById(processId);
        }

        catch (ArgumentException)
        {

            string details = String.Format("ProcessID {0} Not Available", processId);
            Debug.WriteLine(details);
            throw;
        }

        //Gets impersonation token
        retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
        if (retVal == true)
        {

            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
            sa.nLength = (uint)Marshal.SizeOf(sa);

            //Convert the impersonation token into Primary token
            retVal = DuplicateTokenEx(
            token,
            TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
            ref sa,
            (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
            (int)TOKEN_TYPE.TokenPrimary,
            ref primaryToken);

            //Close the Token that was previously opened.
            CloseHandle(token);
            if (retVal == false)
            {
                string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
                Debug.WriteLine(message);
            }

        }

        else
        {

            string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
            Debug.WriteLine(message);

        }

        //We'll Close this token after it is used.
        return primaryToken;

    }

    private static IntPtr GetEnvironmentBlock(IntPtr token)
    {

        IntPtr envBlock = IntPtr.Zero;
        bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
        if (retVal == false)
        {

            //Environment Block, things like common paths to My Documents etc.
            //Will not be created if "false"
            //It should not adversley affect CreateProcessAsUser.

            string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
            Debug.WriteLine(message);

        }
        return envBlock;
    }

    public static bool Launch(string appCmdLine /*,int processId*/)
    {

        bool ret = false;

        //Either specify the processID explicitly
        //Or try to get it from a process owned by the user.
        //In this case assuming there is only one explorer.exe

        Process[] ps = Process.GetProcessesByName("explorer");
        int processId = -1;//=processId
        if (ps.Length > 0)
        {
            processId = ps[0].Id;
        }

        if (processId > 1)
        {
            IntPtr token = GetPrimaryToken(processId);

            if (token != IntPtr.Zero)
            {

                IntPtr envBlock = GetEnvironmentBlock(token);
                ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
                if (envBlock != IntPtr.Zero)
                    DestroyEnvironmentBlock(envBlock);

                CloseHandle(token);
            }

        }
        return ret;
    }
于 2012-04-12T11:05:15.577 に答える
0

参照:
C# で管理者モードとしてプロセスを開始する方法
プログラムでプロセス特権を昇格させるには?

  var psi = new ProcessStartInfo
    {
        FileName = "notepad",
        UserName = "admin",
        Domain = "",
        Password = pass,
        UseShellExecute = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        Verb = "runas";
    };
    Process.Start(psi);

///

var pass = new SecureString();
pass.AppendChar('s');
pass.AppendChar('e');
pass.AppendChar('c');
pass.AppendChar('r');
pass.AppendChar('e');
pass.AppendChar('t');
Process.Start("notepad", "admin", pass, "");

//Vista以上チェック

if (System.Environment.OSVersion.Version.Major >= 6)
{
   p.StartInfo.Verb = "runas";
}

参照: 管理者権限で新しいプロセスを実行/開始する方法は? ASP.net フォーラム

もう 1 つの方法は、管理者ユーザーになりすますことです。これを行うには、Logon 関数を呼び出して、トークンを取得するユーザーを偽装します。コードでユーザーを偽装するには、次を参照してください: WindowsImpersonationContext Class 。GetCurrentUserのチェック http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=31611を使用して、なりすましが成功したかどうかを確認します。

コードスニペット:

System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;

processStartInfo = new System.Diagnostics.ProcessStartInfo();

processStartInfo.FileName = "regedit.exe";

if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
{
   processStartInfo.Verb = "runas";
}
else
{
   // No need to prompt to run as admin
}

processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;

try
{
   process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
   if (process != null)
   {
      process.Dispose();
   }
}

//管理者ログインでこれを試してください。まだテストしていません..

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

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

        // Test harness.
        // If you incorporate this code into a DLL, be sure to demand FullTrust.
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        private void button1_Click(object sender, EventArgs e)
        {
            SafeTokenHandle safeTokenHandle;
            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;
            bool returnValue = LogonUser("administrator", "", "password",
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);

            Console.WriteLine("LogonUser called.");

            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                Console.WriteLine("LogonUser failed with error code : {0}", ret);
                throw new System.ComponentModel.Win32Exception(ret);
            }
            using (safeTokenHandle)
            {
                Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);

                // Check the identity.
                Console.WriteLine("Before impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                // Use the token handle returned by LogonUser.
                WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
                {
                    System.Diagnostics.Process process = null;
                    System.Diagnostics.ProcessStartInfo processStartInfo;


                    processStartInfo = new System.Diagnostics.ProcessStartInfo();

                    processStartInfo.FileName = "regedit.exe";

                    //if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
                    //{
                    //    processStartInfo.Verb = "runas";
                    //}
                    //else
                    //{
                    //    // No need to prompt to run as admin
                    //}

                    processStartInfo.Arguments = "";
                    processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                    processStartInfo.UseShellExecute = true;

                    try
                    {
                        process = System.Diagnostics.Process.Start(processStartInfo);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    finally
                    {
                        if (process != null)
                        {
                            process.Dispose();
                        }
                    }

                    // Check the identity.
                    Console.WriteLine("After impersonation: "
                        + WindowsIdentity.GetCurrent().Name);
                }
                // Releasing the context object stops the impersonation
                // Check the identity.
                Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
            }
        }
于 2012-04-12T11:21:35.783 に答える