AssignProcessToJobObject返回ACCESS_DENIED(CreateProcessWithTokenW启动进程场景)
问题:管理员上下文控制台应用启动当前用户进程后无法分配到JobObject(ACCESS_DENIED)
我有一个运行在管理员上下文的控制台应用,需要以当前用户上下文启动子进程,为此编写了启动进程的代码;同时为了实现控制台退出时自动终止子进程,编写了基于JobObject的进程跟踪代码。
已修正原代码中CreateProcessWithTokenW调用语法错误及AddProcessHandle参数错误,但调用AssignProcessToJobObject时仍返回false并触发ACCESS_DENIED错误,无法完成进程跟踪。
预期效果:进程句柄成功分配给JobObject,控制台应用退出时该子进程自动终止。
启动当前用户进程的代码
private static bool RunAsCurrentUser(string fileName, string arguments) { var hProcessToken = IntPtr.Zero; try { var process = GetCurrentProcess(); if (!OpenProcessToken(process, 0x0020, ref hProcessToken)) return false; var tkp = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Privileges = new LUID_AND_ATTRIBUTES[1] }; if (!LookupPrivilegeValue(null, "SeIncreaseQuotaPrivilege", ref tkp.Privileges[0].Luid)) return false; tkp.Privileges[0].Attributes = 0x00000002; if (!AdjustTokenPrivileges(hProcessToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero)) return false; } finally { CloseHandle(hProcessToken); } var hwnd = NativeMethods.GetShellWindow(); if (hwnd == IntPtr.Zero) return false; var hShellProcess = IntPtr.Zero; var hShellProcessToken = IntPtr.Zero; var hPrimaryToken = IntPtr.Zero; try { // Get the PID of the desktop shell process. uint dwPID; if (GetWindowThreadProcessId(hwnd, out dwPID) == 0) return false; // Open the desktop shell process in order to query it (get the token) hShellProcess = OpenProcess(NativeMethods.ProcessAccessFlags.QueryInformation, false, dwPID); if (hShellProcess == IntPtr.Zero) return false; // Get the process token of the desktop shell. if (!OpenProcessToken(hShellProcess, 0x0002, ref hShellProcessToken)) return false; var dwTokenRights = 395U; // CreateProcessWithTokenW (contrary to current documentation). if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, IntPtr.Zero, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, NativeMethods.TOKEN_TYPE.TokenPrimary, out hPrimaryToken)) return false; int STARTF_USESHOWWINDOW = 0x00000001; short SW_SHOW = 5; // Start the target process with the new token. var si = new STARTUPINFO(); var pi = new PROCESS_INFORMATION(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; string finalArgs = $"\"{fileName}\" {arguments}"; if (!CreateProcessWithTokenW(hPrimaryToken, 0, fileName, finalArgs, 0, IntPtr.Zero, Path.GetDirectoryName(fileName), ref si, out pi)) return false; ChildProcessTracker.AddProcessHandle(pi.hProcess); return true; } catch (Exception) { return false; } finally { NativeMethods.CloseHandle(hShellProcessToken); NativeMethods.CloseHandle(hPrimaryToken); NativeMethods.CloseHandle(hShellProcess); } }
进程跟踪(JobObject)代码
public static void AddProcessHandle(IntPtr handle) { if (s_jobHandle != IntPtr.Zero) { bool success = AssignProcessToJobObject(s_jobHandle, handle); if (!success) throw new Win32Exception(); } } static ChildProcessTracker() { string jobName = "MyProcess" + Process.GetCurrentProcess().Id; s_jobHandle = CreateJobObject(IntPtr.Zero, jobName); var info = new JobobjectBasicLimitInformation(); info.LimitFlags = JOBOBJECTLIMITS.KillOnJobClose; var extendedInfo = new JobObjectExtendedLimitInformation(); extendedInfo.BasicLimitInformation = info; int length = Marshal.SizeOf(typeof(JobObjectExtendedLimitInformation)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); try { Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); SetInformationJobObject(s_jobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length); } finally { Marshal.FreeHGlobal(extendedInfoPtr); } }
内容的提问来源于stack exchange,提问作者manikanta vh
相关产品推荐
相关产品推荐

