Home > database >  Privilege Escalation and Access Token Rights Modification
Privilege Escalation and Access Token Rights Modification

Time:04-19

I have started to learn more and more about Windows access token and privilege adjustment but as I progress, I am getting confused. I ask some questions here to better understand this security mechanism of Windows.

In windows, when I run whoami /priv command for non-administrator users, it gives me the following result:

C:\Users\light>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                          State
============================= ==================================== ========
SeShutdownPrivilege           Shut down the system                 Disabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeUndockPrivilege             Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
SeTimeZonePrivilege           Change the time zone                 Disabled

But when I run this command with administrator account it gives me a long list of privilege names which most of them are disabled. Now my first question is: Why some of these privileges are disabled? When a privilege disabled, it means user couldn't take the right to use that privilege?

My second question: How should I exactly modify an access token to get Se_Debug privilege? I do the following steps, but my application has not modify the token:

  1. Call OpenProcessToken to open a process for access token query.
  2. Initialized TOKEN_PRIVILEGES for querying access token.
  3. Call LookupPrivilegeValue to check privilege
  4. Call AdjustTokenPrivileges to adjust that privilege

My source code:

#include <Windows.h>
#include <iostream>

#pragma comment(lib, "advapi32.lib")

class privilege
{
private:
    BOOL m_ok;
    LUID m_luid;
    LUID m_privilege_id;
    HANDLE m_handle_token;
    BOOL m_has_priviliege;
    PRIVILEGE_SET m_privilege_set;
    TOKEN_PRIVILEGES m_token_privilege;

public:
    BOOL check(LPCWSTR arg_privilege)
    {
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &m_handle_token))
            m_ok = LookupPrivilegeValue(NULL, arg_privilege, &m_privilege_id);

        if (m_ok) 
        {
            m_privilege_set.PrivilegeCount = 1;
            m_privilege_set.Control = PRIVILEGE_SET_ALL_NECESSARY;
            m_privilege_set.Privilege[0].Luid = m_privilege_id;
            m_privilege_set.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
            m_ok = PrivilegeCheck(m_handle_token, &m_privilege_set, &m_has_priviliege);
        }

        if (m_ok && !m_has_priviliege) 
            return FALSE;
        else 
            return TRUE;
    }

    BOOL set(HANDLE arg_token, LPCTSTR arg_privilege, BOOL arg_enable_privilege)
    {
        if (!LookupPrivilegeValue(NULL, arg_privilege, &m_luid))
        {
            printf("LookupPrivilegeValue error: %u\n", GetLastError());
            return FALSE;
        }

        m_token_privilege.PrivilegeCount = 1;
        m_token_privilege.Privileges[0].Luid = m_luid;
        
        if (arg_enable_privilege)
            m_token_privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        else
            m_token_privilege.Privileges[0].Attributes = 0;

        // Enable the privilege or disable all privileges.
        if (!AdjustTokenPrivileges(arg_token, FALSE, &m_token_privilege, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
        {
            printf("AdjustTokenPrivileges error: %u\n", GetLastError());
            return FALSE;
        }

        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
            printf("The token does not have the specified privilege. \n");
            return FALSE;
        }

        return TRUE;
    }
};

int main(int argc, wchar_t* argv)
{
    HANDLE      process_handle;
    PHANDLE     token_handle = NULL;
    privilege   o_privilege;

    BOOL open_token_status = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token_handle);
    if (open_token_status != NULL)
    {
        std::wcout << L"OpenProcessToken has been failed." << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        std::wcout << L"Process has Backup privilege: " << std::boolalpha << o_privilege.check(L"SE_BACKUP_NAME") << std::endl;
        BOOL privilege_adjust_status = o_privilege.set(token_handle, L"SeBackupPrivilege", TRUE);
        std::wcout << L"Process has Backup privilege: " << std::boolalpha << o_privilege.check(L"SE_BACKUP_NAME") << std::endl;
        return privilege_adjust_status;
    }

    return 0;
}

But this program couldn't set backup privilege for the process. Somebody could explain token enumeration and adjustment in Windows OS with a step by step approach?

Also I have a real problem with impersonation concept. Why we need such thing in Windows OS?

CodePudding user response:

How should I exactly modify an access token to get Se_Debug privilege?

According to Changing Privileges in a Token,

You can change the privileges in either a primary or an impersonation token in two ways:

  • Enable or disable privileges by using the AdjustTokenPrivileges function.
  • Restrict or remove privileges by using the CreateRestrictedToken function.

To assign privileges to a user account, according to Assigning Privileges to an Account

You can assign privileges to accounts either by using the Local Security Policy Microsoft Management Console (MMC) snap-in (Secpol.msc) or by calling the LsaAddAccountRights function.

  • Related