Today we were having a discussion around Internet Explorer in Protected Mode, and the question came up regarding how to launch an arbitrary process with a low integrity level. This is fairly straightforward to do in code.

First, you duplicate the handle of the medium integrity process (the default) that is launching the application. The OpenProcessToken API will find the existing token, and you can then call DuplicateTokenEx to create a copy.

Next, you use SetTokenInformation to lower the duplicate token to low integrity. The SID for low integrity is S-1-16-4096, and the attributes of the TOKEN_MANDATORY_LABEL's label should be set to SE_GROUP_IDENTITY.

Finally, you call CreateProcessAsUser to launch the process with the new integrity level.

This is described, with sample code, on MSDN. See: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ProtectedMode.asp.

Note that you don't have to use a bootstrapper to do this. Rather, you can call CreateProcessAsUser and re-launch yourself. In fact, this is exactly what iexplore.exe does when it is launching. We can watch this with the debugger by setting a few breakpoints.

First, we'll set a breakpoint on ADVAPI32!OpenProcessToken:

0:000> kp
ChildEBP RetAddr
001ff71c 773a3d59 ADVAPI32!OpenProcessToken
001ff748 773a3d0b iertutil!GetTokenIntegrityLevel+0x46
001ff75c 773a4154 iertutil!GetProcessIntegrityLevel+0x21
001ff76c 773a5fa4 iertutil!IsMICLowProcess+0x11
001ff774 013813b8 iertutil!IsProtectedModeProcess+0x19
001ffbac 0138131a iexplore!wWinMain+0x85
001ffc40 75e03833 iexplore!_initterm_e+0x1b1
001ffc4c 771fa9bd kernel32!BaseThreadInitThunk+0xe
001ffc8c 00000000 ntdll!_RtlUserThreadStart+0x23

Here, we are checking our integrity level - obviously we only want to launch a new process if the current one isn't already running in low IL or we'd be launching new processes forever!

Later, we call SetTokenInformation:

0:000> k
ChildEBP RetAddr
001ff6b8 773a631b ADVAPI32!SetTokenInformation
001ff6f4 773a6066 iertutil!IESetTokenIntegrityLevel+0xb1
001ff714 773a600c iertutil!CreateMICIEProcess+0x4c
001ff72c 01384815 iertutil!LaunchIEInProtectedMode+0x2a
001ff774 01381488 iexplore!LaunchLoRIEModeIE+0x5e
001ffbac 0138131a iexplore!wWinMain+0x253
001ffc40 75e03833 iexplore!_initterm_e+0x1b1
001ffc4c 771fa9bd kernel32!BaseThreadInitThunk+0xe
001ffc8c 00000000 ntdll!_RtlUserThreadStart+0x23

After we have configured the new token, we launch ourselves again, this time with low IL, using CreateProcessAsUser:

0:000> k
ChildEBP RetAddr
001fe3ec 773a61e1 ADVAPI32!CreateProcessAsUserW
001ff6ec 773a6079 iertutil!LaunchProtectedModeIEWithToken+0x163
001ff714 773a600c iertutil!CreateMICIEProcess+0x5f
001ff72c 01384815 iertutil!LaunchIEInProtectedMode+0x2a
001ff774 01381488 iexplore!LaunchLoRIEModeIE+0x5e
001ffbac 0138131a iexplore!wWinMain+0x253
001ffc40 75e03833 iexplore!_initterm_e+0x1b1
001ffc4c 771fa9bd kernel32!BaseThreadInitThunk+0xe
001ffc8c 00000000 ntdll!_RtlUserThreadStart+0x23

After we do this, a new iexplore.exe is launched, and it's running with a restricted token. You can certainly do the same with your code, and may want to consider this if you are looking to implement and secure an Internet-facing application that does not require access to local resources.