Windows下一个普通权限的账户,怎么启动一个有管理员权限的进程
我们知道,如果Windows下一个普通权限的账户,直接启动管理员权限的进程,会弹出输入管理员账号密码的提示窗。但是如果我想通过自启动一个管理员权限的进程怎么办呢,既然都自启动了,还要我输入账号密码就说不过去了。
- 一开始尝试了任务计划程序中的“运行任务时,请使用下列用户账户”,赋值管理员账户(这个过程必须在管理员身份的账户下操作),然后触发器使用普通账户登录触发。结果普通账户登录时,并没有执行成功。提示权限受限。
- 通过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下也能看到界面。(正常情况下,不同账户的进程在不同账户环境下是不可见的)
- 第二种方式还可以替换成创建一个快捷方式,使用这种格式路径 runas /user:机器名\administrator /savecred “应用软件路径” 。输入一个密码之后,就不再需要输入密码了(重启后也不需要输入),然后进程P启动后,虽然该进程用户名是管理员账户Admin了,但是在任务管理器那里看“特权”还是否。这时候,只要在进程P中再通过runas启动一个新进程S,这个新进程S的用户名就是“Admin”,特权为“是”。
- 后来尝试了组策略,设置“计算机配置”——“Windows设置”——“安全设置”——“本地策略”——“用户权限分配”,“获取同一会话中另一个用户的模拟令牌”,添加普通账户。发现普通账户启动的进程居然变成了管理员权限。如果普通账户需要做一些杀死其它账户的管理员进程的话,在“调试程序”把普通账户添加进去即可。这个方式的缺陷是在这个账户下启动的所有进程都是管理员权限。确认是否需要重启来生效。(后面验证有时候行有时候不行,得充分验证)