Enabling privileges for a process

Recently I tried to escalate the privilege of a program and enable SeDebugPrivilege on it but I tried several times and failed. Here is the code I wrote to get the privilege:


int set_token_privilege(char *priv_name){
    long int err_code;
    LUID debug_luid ;
    if(!LookupPrivilegeValue(NULL,priv_name,&debug_luid)){
        err_code = GetLastError();
        printf("LookupPrivilegeValue Error: %ld\n",err_code);
    }else{
        HANDLE new_token_handle ;
        if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&new_token_handle)){
            err_code = GetLastError();
            printf("OpenProcessToken Error: %ld\n",err_code);
        }else{
            TOKEN_PRIVILEGES token_p;
            token_p.PrivilegeCount =1;
            token_p.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            token_p.Privileges[0].Luid = debug_luid;
            if(!AdjustTokenPrivileges(new_token_handle,FALSE,&token_p,0,NULL,NULL)){
                err_code = GetLastError();
                printf("AdjustTokenPrivileges Error (%s): %ld\n",priv_name,err_code);
            }else{
                err_code = GetLastError();
                if(err_code==ERROR_SUCCESS){
                    printf("privileg (%s) set\n",priv_name);
                }else if(err_code == ERROR_NOT_ALL_ASSIGNED){
                    printf("AdjustTokenPrivileges Error (%s): %ld\n",priv_name,err_code);
                }

            }
        }
    }
    return 0;
}

The problem was when I tried to call the function like set_token_privilege("SeDebugPrivilege"), everything was fine and the return value of AdjustTokenPrivileges was a non-zero value which means success. But when I call GetLastError the result is not ERROR_SUCCESS and instead, it is ERROR_NOT_ALL_ASSIGNED (1300) which means that we failed to enable the privileges.

But where is the problem? The problem is that we don't have this privilege in our access token and since it is not present there, we cannot enable and disable it. According to MSDN, we cannot add new privileges to a token and we can only enable/disable the privileges that already exists in a token.

But I noticed that I am the member of administrators group which means I have administrator's rights but still don't have this privilege. Let's see if I am in admin group:

 


int if_we_are_admin(){
    /*
        return value -1=Error, 0=Not Admin, 1=Admin
    */
    DWORD buff_size = 100;
    BOOL is_admin = FALSE;
    TCHAR username[buff_size];
    DWORD sid_size=0,user_domain_size=0;
    SID_NAME_USE sidnameuse;
    char * user_domain_name,*sid_buffer;
    long int err_code = 0;
    if(GetUserName(username,&buff_size)){
        printf("Username is: %s\n",username);
    }
    LookupAccountName(NULL,username,NULL,&sid_size,NULL,&user_domain_size,&sidnameuse);
    if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER){
        printf("LookupAccountName Error: %ld\n",GetLastError());
        return -1;
    }
    user_domain_name = (char *)malloc(user_domain_size);
    sid_buffer = (unsigned char *) malloc(sid_size);
    if(!LookupAccountName(NULL,username,sid_buffer,&sid_size,user_domain_name,&user_domain_size,&sidnameuse)){
            err_code = GetLastError();
            printf("LookupAccountName Error: %ld\n",err_code);
            return -1;
    }
    printf("Domain/computer name is: %s\n",user_domain_name);
    //printf("Sid Type is: %d (%s)\n",sidnameuse,get_sid_type(sidnameuse));
    //now covert sid to string
    char * sid_str;
    if(ConvertSidToStringSid(sid_buffer,&sid_str)){
        printf("Sid string is: %s\n",sid_str);
        LocalFree(sid_str);
    }
    PSID admin_sid;
    sid_size = MAX_SID_SIZE;
    admin_sid = (PSID) malloc(sid_size);
    if(!CreateWellKnownSid(WinBuiltinAdministratorsSid,NULL,admin_sid,&sid_size)){
        printf("Error getting admin SID: %ld\n",GetLastError());
        return -1;
    }
    //Print admin SID
    if(ConvertSidToStringSid(admin_sid,&sid_str)){
        printf("Admin SID is: %s\n",sid_str);
        LocalFree(sid_str);
    }
    if(!CheckTokenMembership(NULL,admin_sid,&is_admin)){
        printf("Error CheckTokenMembership: %ld",GetLastError());
        return -1;
    }
    if(is_admin){
        printf("Token belong to Admin group\n");
        return 1;
    }else{
        //now we have to check for vista version and above
        OSVERSIONINFO os_ver;
        os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if(!GetVersionEx(&os_ver)){
            printf("GetVersionEx Error: %ld",GetLastError());
            return -1;
        }
        if(os_ver.dwMajorVersion<6){ //winxp
            return 0;
        }else{
            HANDLE linked_token;
            HANDLE token_handle;
            DWORD return_len;
            if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&token_handle)){
                err_code = GetLastError();
                printf("OpenProcessToken Error: %ld\n",err_code);
                return -1;
            }
            if(!GetTokenInformation(token_handle,TokenLinkedToken, (VOID*)&linked_token,sizeof(linked_token),&return_len)){
                err_code = GetLastError();
                printf("GetTokenInformation Error: %ld\n",err_code);
                return 0;
            }
            if (!CheckTokenMembership(linked_token,admin_sid,&is_admin)){
                err_code = GetLastError();
                printf("CheckTokenMembership Error: %ld\n",err_code);
                return -1;
            }
            if(is_admin){
                return 1;
            }else{return 0;}
        }
    }
    return -1;
}

 When I executed this code, it returned 1 which means I am in admin group and also I used net user myusername command which showed that I am in administrators group but still no success to enable privileges.

Lets use whoami command with /ALL switch to see the list of privileges that I have in my access token:


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

So these are the privileges I have in access token. So it is perfectly clear why I can't enable SeDebugPrivilege (I don't have it in access token and it is impossible to add or enable it). When I run a command line as administrator (Right click-> Run as administrator) and again use whoami /ALL, this is the result:


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

Privilege Name                  Description                               State
=============================== ========================================= ========
SeIncreaseQuotaPrivilege        Adjust memory quotas for a process        Disabled
SeSecurityPrivilege             Manage auditing and security log          Disabled
SeTakeOwnershipPrivilege        Take ownership of files or other objects  Disabled
SeLoadDriverPrivilege           Load and unload device drivers            Disabled
SeSystemProfilePrivilege        Profile system performance                Disabled
SeSystemtimePrivilege           Change the system time                    Disabled
SeProfileSingleProcessPrivilege Profile single process                    Disabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority              Disabled
SeCreatePagefilePrivilege       Create a pagefile                         Disabled
SeBackupPrivilege               Back up files and directories             Disabled
SeRestorePrivilege              Restore files and directories             Disabled
SeShutdownPrivilege             Shut down the system                      Disabled
SeDebugPrivilege                Debug programs                            Disabled
SeSystemEnvironmentPrivilege    Modify firmware environment values        Disabled
SeChangeNotifyPrivilege         Bypass traverse checking                  Enabled
SeRemoteShutdownPrivilege       Force shutdown from a remote system       Disabled
SeUndockPrivilege               Remove computer from docking station      Disabled
SeManageVolumePrivilege         Perform volume maintenance tasks          Disabled
SeImpersonatePrivilege          Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege         Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege   Increase a process working set            Disabled
SeTimeZonePrivilege             Change the time zone                      Disabled
SeCreateSymbolicLinkPrivilege   Create symbolic links                     Disabled
 

This probably means that the real built-in administrator has a lot more privileges than my user (which is in administrators group). Actually I couldn't understand why this is happening and I searched a lot until I found this registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

key = EnableLUA, value = 1 (MSDN reference)

This is actually what causes me these problems. This probably means Limited User Account and by disabling this value and restarting the computer, you will disable User Account Control system and then you can run any app with admin privileges. But remember, This is like a suicide because all the apps running on the system now have unlimited power to do whatever they want to.

EDIT: After reading this paper, I found out that even users in administrators group have less rights than the built-in administrator and that is why I can not enable SeDebugPrivilege privilege. To enable these kinds of privileges, we have two options: run program as an administrator or didable LUA using that registry key mentioned above. (there is one other way which is using some known exploit and try to get admin privilege which is not an appropriate way).