What does mandatory integrity level value of 0x2010 stand for?
Asked Answered
M

3

5

I'm running the following snippet of code in my user-mode process that starts up when a Windows user account logs in to the workstation. Or, in other words, its path is placed in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key.

The code is supposed to determine the mandatory integrity level of my user process. It goes as such:

DWORD getMIL()
{
    //Try to get integrity level
    //-1                                            Unknown
    //SECURITY_MANDATORY_UNTRUSTED_RID              0x00000000 Untrusted.
    //SECURITY_MANDATORY_LOW_RID                    0x00001000 Low integrity.
    //SECURITY_MANDATORY_MEDIUM_RID                 0x00002000 Medium integrity.
    //SECURITY_MANDATORY_MEDIUM_PLUS_RID            SECURITY_MANDATORY_MEDIUM_RID + 0x100 Medium high integrity.
    //SECURITY_MANDATORY_HIGH_RID                   0X00003000 High integrity.
    //SECURITY_MANDATORY_SYSTEM_RID                 0x00004000 System integrity.
    //SECURITY_MANDATORY_PROTECTED_PROCESS_RID      0x00005000 Protected process.
    DWORD dwIntgtyLvl = -1;

    HANDLE hToken;
    if(OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
    {

        DWORD dwSizeIntgtyLvl = 0;
        if(!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, dwSizeIntgtyLvl, &dwSizeIntgtyLvl) &&
            ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            BYTE* pbIntgtyLvl = new BYTE[dwSizeIntgtyLvl];
            if(pbIntgtyLvl)
            {
                TOKEN_MANDATORY_LABEL* pTML = (TOKEN_MANDATORY_LABEL*)pbIntgtyLvl;
                DWORD dwSizeIntgtyLvl2;
                if(GetTokenInformation(hToken, TokenIntegrityLevel, pTML, dwSizeIntgtyLvl, &dwSizeIntgtyLvl2) &&
                    dwSizeIntgtyLvl2 <= dwSizeIntgtyLvl)
                {
                    dwIntgtyLvl = *GetSidSubAuthority(pTML->Label.Sid,
                        (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTML->Label.Sid)-1));
                }

                //Free mem
                delete[] pbIntgtyLvl;
                pbIntgtyLvl = NULL;
            }
        }

        ::CloseHandle(hToken);
    }

    return dwIntgtyLvl;
}

In a normal flow of events I'd expect to get the value of 0x2000 for SECURITY_MANDATORY_MEDIUM_RID, or 0x3000 for SECURITY_MANDATORY_HIGH_RID, but if I have one Windows user account already logged in, and if I then switch users, and log in with another user account, the method above will get me the value of 0x2010 for the mandatory integrity level.

Does anyone know what that value stands for?

Ming answered 1/7, 2015 at 1:25 Comment(0)
B
4

You are not taking into account that integrity levels use value ranges, where a token/process can be assigned a value within a range of values for its integrity level. You are looking for specific values only.

Untrusted integrity can be any value between SECURITY_MANDATORY_UNTRUSTED_RID (inclusive) and SECURITY_MANDATORY_LOW_RID (non-inclusive).

Low integrity can be any value between SECURITY_MANDATORY_LOW_RID (inclusive) and SECURITY_MANDATORY_MEDIUM_RID (non-inclusive).

Medium integrity can be any value between SECURITY_MANDATORY_MEDIUM_RID (inclusive) and SECURITY_MANDATORY_HIGH_RID (non-inclusive). Which is what you are seeing in your example.

High integrity can be any value between SECURITY_MANDATORY_HIGH_RID (inclusive) and SECURITY_MANDATORY_SYSTEM_RID (non-inclusive).

Any value at or above SECURITY_MANDATORY_SYSTEM_RID is reserved for the system.

There is a table in the documentation showing this:

Windows Integrity Mechanism Design

Table 2   Defined integrity levels and corresponding values

Value   Description             Symbol 

0x0000  Untrusted level         SECURITY_MANDATORY_UNTRUSTED_RID
0x1000  Low integrity level     SECURITY_MANDATORY_LOW_RID
0x2000  Medium integrity level  SECURITY_MANDATORY_MEDIUM_RID
0x3000  High integrity level    SECURITY_MANDATORY_HIGH_RID
0x4000  System integrity level  SECURITY_MANDATORY_SYSTEM_RID
Belew answered 1/7, 2015 at 1:39 Comment(3)
Hmm. Interesting. Thanks. I didn't know that those levels could be any arbitrary value in between. So hypothetically, I can run my user process with MIL of 0x2123, correct?Ming
@Ming That's right. They're just arbitrary values - they only have meaning when they're compared against the IL of other processes.Sfax
@JonathanPotter: Ok. Thank you both. I just learned something new today!Ming
S
6

It's described right at the bottom of the MSDN page on Windows Integrity Mechanism Design:

The RIDs are separated by intervals of 0x1000 to allow for definition of additional levels in the future. The separation also allows assigning an integrity level to a process that is slightly higher than medium: for example, to meet specific system design goals.

...

Applications that are launched with UIAccess rights for a standard user are assigned a slightly higher integrity level value in the access token. The access token integrity level for the UIAccess application for a standard user is the value of medium integrity level, plus an increment of 0x10. The higher integrity level for UIAccess applications prevents other processes on the same desktop at the medium integrity level from opening the UIAccess process object

Sfax answered 1/7, 2015 at 1:38 Comment(1)
Oh, I see. Appreciate it. I guess I missed that part.Ming
B
4

You are not taking into account that integrity levels use value ranges, where a token/process can be assigned a value within a range of values for its integrity level. You are looking for specific values only.

Untrusted integrity can be any value between SECURITY_MANDATORY_UNTRUSTED_RID (inclusive) and SECURITY_MANDATORY_LOW_RID (non-inclusive).

Low integrity can be any value between SECURITY_MANDATORY_LOW_RID (inclusive) and SECURITY_MANDATORY_MEDIUM_RID (non-inclusive).

Medium integrity can be any value between SECURITY_MANDATORY_MEDIUM_RID (inclusive) and SECURITY_MANDATORY_HIGH_RID (non-inclusive). Which is what you are seeing in your example.

High integrity can be any value between SECURITY_MANDATORY_HIGH_RID (inclusive) and SECURITY_MANDATORY_SYSTEM_RID (non-inclusive).

Any value at or above SECURITY_MANDATORY_SYSTEM_RID is reserved for the system.

There is a table in the documentation showing this:

Windows Integrity Mechanism Design

Table 2   Defined integrity levels and corresponding values

Value   Description             Symbol 

0x0000  Untrusted level         SECURITY_MANDATORY_UNTRUSTED_RID
0x1000  Low integrity level     SECURITY_MANDATORY_LOW_RID
0x2000  Medium integrity level  SECURITY_MANDATORY_MEDIUM_RID
0x3000  High integrity level    SECURITY_MANDATORY_HIGH_RID
0x4000  System integrity level  SECURITY_MANDATORY_SYSTEM_RID
Belew answered 1/7, 2015 at 1:39 Comment(3)
Hmm. Interesting. Thanks. I didn't know that those levels could be any arbitrary value in between. So hypothetically, I can run my user process with MIL of 0x2123, correct?Ming
@Ming That's right. They're just arbitrary values - they only have meaning when they're compared against the IL of other processes.Sfax
@JonathanPotter: Ok. Thank you both. I just learned something new today!Ming
L
1

Here is a named list: Well-known SIDs

| SID           | Name                                  | DEC       | HEX   |             BIN   |
|-------------- |-----------------------------------    |-------    |------ |----------------:  |
| S-1-16-0      | Untrusted Mandatory Level             | 0         | 0000  |               0   |
| S-1-16-4096   | Low Mandatory Level                   | 512       | 0200  |      1000000000   |
| S-1-16-8192   | Medium Mandatory Level                | 8192      | 2000  |  10000000000000   |
| S-1-16-8448   | Medium Plus Mandatory Level           | 8448      | 2100  |  10000100000000   |
| S-1-16-12288  | High Mandatory Level                  | 12288     | 3000  |  11000000000000   |
| S-1-16-16384  | System Mandatory Level                | 16384     | 4000  | 100000000000000   |
| S-1-16-20480  | Protected Process Mandatory Level     | 20480     | 5000  | 101000000000000   |
| S-1-16-28672  | Secure Process Mandatory Level        | 28672     | 7000  | 111000000000000   |

But, as said in other answers, values between two listed items are valid and if you must name them, you should opt for the lower value name, (for example 511 should be named untrusted plus not Low Mandatory).

Processes can only interact with system objects with same or lower integrity level.

Leandroleaning answered 13/2, 2020 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.