使用CreateRestrictedToken(LUA_TOKEN)从提升的进程创建低/中进程

时间:2016-04-20 18:27:38

标签: windows security winapi uac windows-security

我尝试从提升的流程创建中等或低完整性流程。我知道还有其他这样的问题,但是他们主要关注使用资源管理器或任务计划程序等变通方法,我想坚持使用CreateRestrictedToken() + CreateProcessAsUser()

我认为必须有可能以某种方式执行此操作,因为我相信UAC在您登录时执行此操作但我无法将令牌中的所有内容看作普通的UAC中IL令牌。

通过使用CreateRestrictedToken(hThisProcessToken, LUA_TOKEN, ...)创建令牌,然后在调用TokenOwner之前设置TokenDefaultDaclTokenIntegrityLevelCreateProcessAsUser(),您可以获得80%。

其余问题包括TokenVirtualizationAllowedTokenVirtualizationEnabledTokenElevationTokenElevationTypeTokenMandatoryPolicy,其中SetTokenInformation()因ERROR_PRIVILEGE_NOT_HELD或ERROR_INVALID_PARAMETER而失败。

如果我以SYSTEM @ SECURITY_MANDATORY_SYSTEM_RID运行并启用了所有权限而不是Administrator @ SECURITY_MANDATORY_HIGH_RID,那么我可以设置TokenMandatoryPolicyTokenVirtualization*但设置TokenElevation*仍然失败! (目前仅在Windows 8上测试过)

令牌中没有正确的TokenElevation*值是一个大问题,因为Internet Explorer无法以保护模式启动,因为它认为令牌已提升。

SetTokenInformation()的{​​{3}}没有说明可以设置哪些TOKEN_INFORMATION_CLASS项目以及需要哪些特权,我不明白你为什么会这样做不允许将这些设置为降低与令牌的实际完整性级别(TokenIntegrityLevel)匹配的安全值。

使用documentation创建SAFER_LEVELID_NORMALUSER令牌不能解决任何这些问题,还会创建比正常的中型IL令牌更受限制的令牌。

我从早期的Vista / Longhorn时代找到了Safer API的人,从那以后没有任何改变?

1 个答案:

答案 0 :(得分:0)

function CreateLowProcess(szProcessName: WideString; const IntegritySid: UnicodeString=''): Boolean;
var
    hToken: THandle;
    hNewToken: THandle;
    szIntegritySid: WideString;
    pIntegritySid: PSID;
    TIL: TOKEN_MANDATORY_LABEL;
    ProcInfo: PROCESS_INFORMATION;
    startupInfo: TStartupInfo;
const
    SE_GROUP_INTEGRITY = $00000020;
    TokenIntegrityLevel = 25;
    SLowIntegritySid:    UnicodeString = 'S-1-16-4096';
    SMediumIntegritySid: UnicodeString = 'S-1-16-8192';
    SHighIntegritySid:   UnicodeString = 'S-1-16-12288';
    SSystemIntegritySid: UnicodeString = 'S-1-16-16384';
begin
    {
        Designing Applications to Run at a Low Integrity Level
        http://msdn.microsoft.com/en-us/library/bb625960.aspx

        To start a low-integrity process:

        - Duplicate the handle of the current process, which is at medium integrity level.
        - Use SetTokenInformation to set the integrity level in the access token to Low.
        - Use CreateProcessAsUser to create a new process using the handle to the low integrity access token.

        CreateProcessAsUser updates the security descriptor in the new child process and the security descriptor
        for the access token to match the integrity level of the low-integrity access token.
    }

    // Low integrity SID
    if IntegritySid <> '' then
        szIntegritySid := IntegritySid
    else
        szIntegritySid := SLowIntegritySid;
//  szIntegritySid  := 'S-1-5-32-545'; //BUILTIN\USERS

    ZeroMemory(@startupInfo, sizeof(startupInfo));

    if (not OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE or TOKEN_ADJUST_DEFAULT or TOKEN_QUERY or TOKEN_ASSIGN_PRIMARY,
                {var}hToken)) then
        RaiseLastOSError;
    try
        if (not DuplicateTokenEx(hToken, 0, nil, SecurityImpersonation, TokenPrimary, {var}hNewToken)) then
            RaiseLastOSError;
        try
            pIntegritySid := StringToSid(szIntegritySid); //free with LocalFree
            try
                TIL._Label.Attributes := SE_GROUP_INTEGRITY;
                TIL._Label.Sid := pIntegritySid;

                // Set the process integrity level
                if (not SetTokenInformation(hNewToken, TTokenInformationClass(TokenIntegrityLevel), @TIL,
                        sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid))) then
                    RaiseLastOSError;

                //Create the new process at Low integrity
                Result := CreateProcessAsUserW(
                        hNewToken,
                        nil,
                        PWideChar(szProcessName),
                        nil, //ProcessAttributes
                        nil, //ThreadAttributes
                        False, //bInheritHandles
                        0, //dwCreationFlags
                        nil, //lpEnvironment
                        nil, //lpCurrentDirectory
                        startupInfo,
                        ProcInfo);
            finally
                LocalFree(HLOCAL(pIntegritySid));
            end;
        finally
            CloseHandle(hNewToken);
        end;
    finally
        CloseHandle(hToken);
    end;
end;