public static extern bool CreateProcessWithTokenW( IntPtr hToken, LogonFlags dwLogonFlags, string lpApplicationName, string lpCommandLine, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESSINFO lpProcessInformation);
public static extern bool CreateProcessAsUserW( 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 PROCESSINFO lpProcessInformation);
public static void RunWithTokenOf( int ProcessID, string ExeToRun, string Arguments, string WorkingDir = "") { plsThrow = true; try { #region Process ExeToRun, Arguments and WorkingDir // If ExeToRun is not absolute path, then let it be ExeToRun = Environment.ExpandEnvironmentVariables(ExeToRun); if (!ExeToRun.Contains("\\")) { foreach (string path in Environment.ExpandEnvironmentVariables("%path%").Split(';')) { string guess = path + "\\" + ExeToRun; if (File.Exists(guess)) { ExeToRun = guess; break; } } } if (!File.Exists(ExeToRun)) { GoComplain(ComplainReason.FileNotFound, ExeToRun); } // If WorkingDir not exist, let it be the dir of ExeToRun // ExeToRun no dir? Impossible, as I would GoComplain() already WorkingDir = Environment.ExpandEnvironmentVariables(WorkingDir); if (!Directory.Exists(WorkingDir)) { WorkingDir = Path.GetDirectoryName(ExeToRun); } // If arguments exist, CmdLine must include ExeToRun as well Arguments = Environment.ExpandEnvironmentVariables(Arguments); string CmdLine = null; if (Arguments != "") { if (ExeToRun.Contains(" ")) { CmdLine = "\"" + ExeToRun + "\" " + Arguments; } else { CmdLine = ExeToRun + " " + Arguments; } } #endregion string obj; Log += "Running as user: "******"SeDebugPrivilege"; obj = "OpenProcessToken"; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, out hToken)) { GoComplain(ComplainReason.APICallFailed, obj); } foreach (string priv in privs.Split(',')) { obj = "LookupPrivilegeValue (" + priv + ")"; LUID Luid; if (!LookupPrivilegeValue("", priv, out Luid)) { GoComplain(ComplainReason.APICallFailed, obj); } obj = "AdjustTokenPrivileges (" + priv + ")"; TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES(); TP.PrivilegeCount = 1; TP.Luid = Luid; TP.Attrs = SE_PRIVILEGE_ENABLED; if (AdjustTokenPrivileges(hToken, false, ref TP, 0, IntPtr.Zero, IntPtr.Zero) & Marshal.GetLastWin32Error() == 0) { Log += obj + ": OK!"; } else { GoComplain(ComplainReason.APICallFailed, obj); } } CloseHandle(hToken); // Open process by PID obj = "OpenProcess (PID: " + ProcessID.ToString() + ")"; hProc = OpenProcess(ProcessAccessFlags.All, false, ProcessID); if (hProc == null) { GoComplain(ComplainReason.APICallFailed, obj); } Log += obj + ": OK!"; // Open process token obj = "OpenProcessToken (TOKEN_DUPLICATE | TOKEN_QUERY)"; if (!OpenProcessToken(hProc, TOKEN_DUPLICATE | TOKEN_QUERY, out hToken)) { GoComplain(ComplainReason.APICallFailed, obj); } Log += obj + ": OK!"; // Duplicate to hDupToken obj = "DuplicateTokenEx (TOKEN_ALL_ACCESS)"; if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, ref dummySA, SecurityImpersonationLevel.SecurityIdentification, TokenType.TokenPrimary, out hDupToken)) { GoComplain(ComplainReason.APICallFailed, obj); } Log += obj + ": OK!"; // Set session ID to make sure it shows in current user desktop // Only possible when SuperCMD running as SYSTEM! if (ForceTokenUseActiveSessionID) { obj = "SetTokenInformation (toActiveSessionID)"; uint SID = WTSGetActiveConsoleSessionId(); if (!SetTokenInformation(hDupToken, TOKEN_INFORMATION_CLASS_TokenSessionId, ref SID, (uint)sizeof(uint))) { GoComplain(ComplainReason.APICallFailed, obj); } Log += obj + ": OK!"; } // Create environment block obj = "CreateEnvironmentBlock"; if (!CreateEnvironmentBlock(out pEnvBlock, hToken, true)) { GoComplain(ComplainReason.APICallFailed, obj); } Log += obj + ": OK!\n"; // Create process with the token we "stole" ^^ uint dwCreationFlags = (NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT); SI = new STARTUPINFO(); SI.cb = Marshal.SizeOf(SI); SI.lpDesktop = "winsta0\\default"; PI = new PROCESSINFO(); // CreateProcessWithTokenW doesn't work in Safe Mode // CreateProcessAsUserW works, but if the Session ID is different, // we need to set it via SetTokenInformation() obj = "CreateProcessWithTokenW"; if (CreateProcessWithTokenW(hDupToken, LogonFlags.WithProfile, ExeToRun, CmdLine, dwCreationFlags, pEnvBlock, WorkingDir, ref SI, out PI)) { Log += "CreateProcessWithTokenW: Done! New process created successfully!"; } else { Log += "CreateProcessWithTokenW: " + WinAPILastErrMsg(); Log += "\nTrying CreateProcessAsUserW instead."; obj = "CreateProcessAsUserW"; if (CreateProcessAsUserW(hDupToken, ExeToRun, CmdLine, ref dummySA, ref dummySA, false, dwCreationFlags, pEnvBlock, WorkingDir, ref SI, out PI)) { Log += obj + ": Done! New process created successfully!"; } else { switch (Marshal.GetLastWin32Error()) { case 3: GoComplain(ComplainReason.FileNotFound, ExeToRun); break; case 193: GoComplain(ComplainReason.FileNotExe, ExeToRun); break; default: GoComplain(ComplainReason.APICallFailed, obj); break; } } } Log += "Process name: " + Path.GetFileName(ExeToRun); Log += "Process ID: " + PI.dwProcessId; CleanUp(); EndLog(); } catch (Exception) {} }