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

And*_*ers 5 windows security winapi uac windows-security

我正在尝试从提升的进程创建中或低完整性进程。我知道还有其他类似的问题,但它们主要关注使用资源管理器或任务计划程序等解决方法,我想坚持使用CreateRestrictedToken()+ CreateProcessAsUser()

我认为一定可以以某种方式执行此操作,因为我相信 UAC 在您登录时会执行此操作,但我无法使令牌中的所有内容看起来像正常的 UAC Medium IL 令牌。

通过创建令牌CreateRestrictedToken(hThisProcessToken, LUA_TOKEN, ...),然后设置TokenOwnerTokenDefaultDacl然后TokenIntegrityLevel调用 之前,您可以获得 80% 的收益CreateProcessAsUser()

剩下的问题是TokenVirtualizationAllowedTokenVirtualizationEnabledTokenElevationTokenElevationTypeTokenMandatoryPolicy其中SetTokenInformation()失败并出现 ERROR_PRIVILEGE_NOT_HELD 或 ERROR_INVALID_PARAMETER。

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

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

的文档没有SetTokenInformation()说明TOKEN_INFORMATION_CLASS可以设置哪些项目以及需要哪些权限(如果有),我不明白为什么不允许您将这些设置为与实际完整性级别()匹配的较低安全TokenIntegrityLevel值令牌。

使用Safer API创建SAFER_LEVELID_NORMALUSER令牌并不能解决任何这些问题,而且还会创建比普通 Medium IL 令牌更受限制的令牌。

我发现有人在 Vista/Longhorn 早期就遇到过类似的问题,从那以后没有任何改变吗?

Ian*_*oyd 2

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;
Run Code Online (Sandbox Code Playgroud)