public static void CreateLowIntegrityProcess(string commandLine)
{
SafeTokenHandle hToken = null;
SafeTokenHandle hNewToken = null;
IntPtr pIntegritySid = IntPtr.Zero;
IntPtr pTokenInfo = IntPtr.Zero;
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
try
{
// Open the primary access token of the process.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethods.TOKEN_DUPLICATE | NativeMethods.TOKEN_ADJUST_DEFAULT |
NativeMethods.TOKEN_QUERY | NativeMethods.TOKEN_ASSIGN_PRIMARY,
out hToken))
{
throw new Win32Exception();
}
// Duplicate the primary token of the current process.
if (!NativeMethods.DuplicateTokenEx(hToken, 0, IntPtr.Zero,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary, out hNewToken))
{
throw new Win32Exception();
}
// Create the low integrity SID.
if (!NativeMethods.AllocateAndInitializeSid(
ref NativeMethods.SECURITY_MANDATORY_LABEL_AUTHORITY, 1,
NativeMethods.SECURITY_MANDATORY_LOW_RID,
0, 0, 0, 0, 0, 0, 0, out pIntegritySid))
{
throw new Win32Exception();
}
TOKEN_MANDATORY_LABEL tml;
tml.Label.Attributes = NativeMethods.SE_GROUP_INTEGRITY;
tml.Label.Sid = pIntegritySid;
// Marshal the TOKEN_MANDATORY_LABEL struct to the native memory.
int cbTokenInfo = Marshal.SizeOf(tml);
pTokenInfo = Marshal.AllocHGlobal(cbTokenInfo);
Marshal.StructureToPtr(tml, pTokenInfo, false);
// Set the integrity level in the access token to low.
if (!NativeMethods.SetTokenInformation(hNewToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo,
cbTokenInfo + NativeMethods.GetLengthSid(pIntegritySid)))
{
throw new Win32Exception();
}
// Create the new process at the Low integrity level.
si.cb = Marshal.SizeOf(si);
if (!NativeMethods.CreateProcessAsUser(hNewToken, null, commandLine,
IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si,
out pi))
{
throw new Win32Exception();
}
}
finally
{
// Centralized cleanup for all allocated resources.
if (hToken != null)
{
hToken.Close();
}
if (hNewToken != null)
{
hNewToken.Close();
}
if (pIntegritySid != IntPtr.Zero)
{
NativeMethods.FreeSid(pIntegritySid);
}
if (pTokenInfo != IntPtr.Zero)
{
Marshal.FreeHGlobal(pTokenInfo);
}
if (pi.hProcess != IntPtr.Zero)
{
NativeMethods.CloseHandle(pi.hProcess);
pi.hProcess = IntPtr.Zero;
}
if (pi.hThread != IntPtr.Zero)
{
NativeMethods.CloseHandle(pi.hThread);
pi.hThread = IntPtr.Zero;
}
}
}