Creating a Process in Protected Mode on Windows Vista


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.

Comments (13)

  1. SR says:

    Chris:

    Can i raise a process(A) integrity level to medium from a low integrity process(B). Is it a good practice?

  2. cjacks says:

    You can launch a medium or high integrity process from a low integrity process. IE does this if you are trying to follow a known path. If you want to use, for example, input type=file, it has to launch ieuser.exe, which runs with medium integrity and can actually see user files. If you want to install an ActiveX control, then it has to launch ieinstal.exe. But you can’t elevate "in place" if that is what you mean.

  3. SR says:

    Chris:

    Thanks for your response. What i meant is i want to convert a process from low integrity level to medium integrity level.

    I wanted to do the oppposite as the function "CreateLowProcess()" from the below URL

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ProtectedMode.asp

    -SR

  4. cjacks says:

    I haven’t tried this specifically. The SID for Mandatory LabelMedium Mandatory Level is S-1-16-8192.

  5. cjacks says:

    Update to my earlier response: iexplore isn’t doing anything to create a new process in medium IL from low IL – it’s invoking into an existing ieuser.exe to handle that. So, you’d want to have a broker process set up and already running for your process to go the other direction, having the broker process invoked to spin up the new process at higher IL. If we didn’t do this, then there would be a clear path for elevation of privilege.

  6. Ganesh says:

    It creates the low integrity process but it doesnt launch it on the desktop. Any way around this?

  7. cjacks says:

    Hi Ganesh,

    I’m not sure what you mean. What is the "it" to which you are referring?

    Thanks,

    Chris

  8. Ganesh says:

    Chris,

    Thanks for your response.

    I duplicate the handle of my medium integrity process, set its token information to low integrity and run notepad using CreateProcessAsUser.

    Notepad process was created but it was not launched on the desktop.

    Ganesh

  9. cjacks says:

    Hi Ganesh,

    There’s nothing wrong with Notepad running in Low IL – you can test that out by using psexec -l notepad.exe and it launches with Low IL just fine. So, there must be an issue with the particular implementation. Have a code snippet?

    Chris

  10. Ganesh says:

    Hi Chris,

    I just created a console app that start starts notepad with low IL. Here is the code snippet. Its almost same as the one in the site.

    {

       BOOL                  fRet;

       HANDLE                hToken        = NULL;

       HANDLE                hNewToken     = NULL;

    HWND h;

       PSID                  pIntegritySid = NULL;

       TOKEN_MANDATORY_LABEL TIL           = {0};

       PROCESS_INFORMATION   ProcInfo      = {0};

       STARTUPINFO           StartupInfo   = {0};

    LPSTR wszProcessName = "C:\Windows\Notepad.exe";

    LPSTR wszIntegritySid = "S-1-16-1024";

    pIntegritySid = NULL;

       fRet = OpenProcessToken(GetCurrentProcess(),

                               TOKEN_DUPLICATE |

                                 TOKEN_ADJUST_DEFAULT |

                                 TOKEN_QUERY |

                                 TOKEN_ASSIGN_PRIMARY,

                               &hToken);

       if (!fRet)

       {

       printf("Open process failedn");

               goto CleanExit;

       }

    else

       printf("Open process succeededn");

       fRet = DuplicateTokenEx(hToken,

                               0,

                               NULL,

                               SecurityImpersonation,

                               TokenPrimary,

                               &hNewToken);

       if (!fRet)

       {

    printf("duplicate token creation failedn");

                   goto CleanExit;

       }

    else

    printf("duplicate token donen");

       fRet = ConvertStringSidToSid(wszIntegritySid, &pIntegritySid);

       if (!fRet)

       {

    printf("Conversion failedn");

                   goto CleanExit;

       }

    else

    printf("convert donen");

       TIL.Label.Attributes = SE_GROUP_INTEGRITY|SE_GROUP_INTEGRITY_ENABLED;

       TIL.Label.Sid        = pIntegritySid;

       //

       // Set the process integrity level

       //

       fRet = SetTokenInformation(hNewToken,

                                  TokenIntegrityLevel,

                                  &TIL,

                                  sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid));

       if (!fRet)

       {

    printf("Setting token info failedn");

           goto CleanExit;

       }

    else

    printf("setting token donen");

       //

       // Create the new process at Low integrity

       //

       StartupInfo.cb= sizeof(STARTUPINFO);

       fRet  = CreateProcessAsUser(hNewToken,

                                   wszProcessName,

                                   0,

                                   NULL,

                                   NULL,

                                   FALSE,

                                   0,

                                   NULL,

                                   NULL,

                                   &StartupInfo,

                                   &ProcInfo);

    if(!fRet)

    printf("Process not createdn");

    else{

    printf("Process createdn");

       }

    CleanExit:

       if (ProcInfo.hProcess != NULL)

       {

           CloseHandle(ProcInfo.hProcess);

       }

       if (ProcInfo.hThread != NULL)

       {

           CloseHandle(ProcInfo.hThread);

       }

       LocalFree(pIntegritySid);

       if (hNewToken != NULL)

       {

           CloseHandle(hNewToken);

       }

       if (hToken != NULL)

       {

           CloseHandle(hToken);

       }

      // return fRet;

    return 0;

    }

    The output is

    Open process succeeded

    duplicate token done

    convert done

    setting token done

    Process created

    But opening notepad has failed with error code 0xc0000022. Message box is displayed as

    "The application failed to initialize properly(0xc0000022). Click OK to terminate the application."

    Looks like that error has again got to do with privileges. And my UAC is ON.

    Thanks,

    Ganesh.

  11. Ganesh says:

    Hi Chris,

    Well I managed to solve that low integrity problem. But having an other problem in Vista.

    I need to selectively delete certain items from the I.E. cache.

    When I iterate through the I.E. cache on Windows Vista, only the entries in Visited container are enumerated.

    Has anything changed in Windows Vista to break the FindFirstUrlCacheEntry /

    FindNextUrlCacheEntry method of iterating through the cache?

    Thanks,

    Ganesh

  12. Duane P. Kisshauer says:

    I wasn’t looking for your advanced info.; just thought my Protected Mode should be "On".

    <duanekisshauer@comcast.net>

  13. cjacks says:

    Hi Duane,

    Is there a question? Is it not turned on? Not sure how you want me to help…?

    Chris

Skip to main content