Windows下一个普通权限的账户,怎么启动一个有管理员权限的进程

我们知道,如果Windows下一个普通权限的账户,直接启动管理员权限的进程,会弹出输入管理员账号密码的提示窗。但是如果我想通过自启动一个管理员权限的进程怎么办呢,既然都自启动了,还要我输入账号密码就说不过去了。

  1. 一开始尝试了任务计划程序中的“运行任务时,请使用下列用户账户”,赋值管理员账户(这个过程必须在管理员身份的账户下操作),然后触发器使用普通账户登录触发。结果普通账户登录时,并没有执行成功。提示权限受限。
  2. 通过CreateProcessWithLogonW指定某个管理员账户进行创建进程
    private void Exec()
    {
        STARTUPINFO startupInfo = new STARTUPINFO();
        PROCESS_INFORMATION processInfo;
    
        bool result = CreateProcessWithLogonW(
            "admin",  // 替换为有效的用户名
            ".",    // 替换为有效的域名,如果是本地用户可以使用"."
            "123",  // 替换为有效的密码
            LogonFlags.LOGON_WITH_PROFILE,
            textBox.Text,  // 替换为有效的应用程序路径
            null,
            CreationFlags.CREATE_UNICODE_ENVIRONMENT,
            IntPtr.Zero,
            null,
            ref startupInfo,
            out processInfo);
    
        if (!result)
        {
            int error = Marshal.GetLastWin32Error();
            Console.WriteLine("CreateProcessWithLogonW failed with error code: {0}", error);
        }
        else
        {
            Console.WriteLine("Process started successfully!");
        }
    }
    
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool CreateProcessWithLogonW(
        string userName,
        string domain,
        string password,
        LogonFlags logonFlags,
        string applicationName,
        string commandLine,
        CreationFlags creationFlags,
        IntPtr environment,
        string currentDirectory,
        ref STARTUPINFO startupInfo,
        out PROCESS_INFORMATION processInformation);
    
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct STARTUPINFO
    {
        public Int32 cb;
        public string reserved;
        public string desktop;
        public string title;
        public UInt32 x;
        public UInt32 y;
        public UInt32 xSize;
        public UInt32 ySize;
        public UInt32 xCountChars;
        public UInt32 yCountChars;
        public UInt32 fillAttribute;
        public StartupInfoFlags flags;
        public UInt16 showWindow;
        public UInt16 reserved2;
        public IntPtr reserved3;
        public IntPtr stdInput;
        public IntPtr stdOutput;
        public IntPtr stdError;
    }
    
    [Flags]
    public enum StartupInfoFlags : uint
    {
        STARTF_USESTDHANDLES = 0x00000100,
        STARTF_USESHOWWINDOW = 0x00000001
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }
    
    [Flags]
    public enum LogonFlags : uint
    {
        LOGON_WITH_PROFILE = 0x00000001,
        LOGON_NETCREDENTIALS_ONLY = 0x00000002
    }
    
    [Flags]
    public enum CreationFlags : uint
    {
        CREATE_NEW_CONSOLE = 0x00000010,
        CREATE_NEW_PROCESS_GROUP = 0x00000200,
        CREATE_UNICODE_ENVIRONMENT = 0x00000400,
        EXTENDED_STARTUPINFO_PRESENT = 0x00080000
    }

    进程P启动后,虽然该进程用户名是管理员账户Admin了,但是在任务管理器那里看“特权”还是否。这时候,只要在进程P中再通过runas启动一个新进程S,这个新进程S的用户名就是“Admin”,特权为“是”。

    // 创建一个ProcessStartInfo对象
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.UseShellExecute = true;
    startInfo.WorkingDirectory = Environment.CurrentDirectory;
    startInfo.FileName = programPath;
    startInfo.Verb = "runas"; // 以管理员权限运行
    
    // 以管理员权限启动应用程序
    try
    {
        Process.Start(startInfo);
    }
    catch (Exception ex)
    {
        // 处理异常
        Console.WriteLine("无法启动应用程序:{0}", ex.Message);
    }

    虽然进程属于Admin账户,但是因为是在普通账户user下创建的,所以在user下也能看到界面。(正常情况下,不同账户的进程在不同账户环境下是不可见的)

  3. 第二种方式还可以替换成创建一个快捷方式,使用这种格式路径 runas /user:机器名\administrator /savecred “应用软件路径”  。输入一个密码之后,就不再需要输入密码了(重启后也不需要输入),然后进程P启动后,虽然该进程用户名是管理员账户Admin了,但是在任务管理器那里看“特权”还是否。这时候,只要在进程P中再通过runas启动一个新进程S,这个新进程S的用户名就是“Admin”,特权为“是”。
  4. 后来尝试了组策略,设置“计算机配置”——“Windows设置”——“安全设置”——“本地策略”——“用户权限分配”,“获取同一会话中另一个用户的模拟令牌”,添加普通账户。发现普通账户启动的进程居然变成了管理员权限。如果普通账户需要做一些杀死其它账户的管理员进程的话,在“调试程序”把普通账户添加进去即可。这个方式的缺陷是在这个账户下启动的所有进程都是管理员权限。确认是否需要重启来生效。(后面验证有时候行有时候不行,得充分验证)

 

posted @ 2024-03-14 11:24  log9527  阅读(172)  评论(0编辑  收藏  举报