Share via


What is the correct way to set SeTcbPrivilege?

Question

Wednesday, November 14, 2018 1:01 AM

In LsaLogonUser documentation pointed out that LsaHandle should be retrieved via LsaRegisterLogonProcess. But it also pointed "The caller is required to have SeTcbPrivilege...." 

What is the correct way to set SeTcbPrivilege?

I wrote a simple program (bellow) based on an example I found on the internet.

SetSeTcbPrivilege function code looks valid in terms of documentation. All calls pass successfully except GetLastError returns error.

LsaRegisterLogonProcess also returns error 0xC0000041 (STATUS_PORT_CONNECTION_REFUSED) which is undestandable if SeTcbPrivilege not set.

#define SECURITY_WIN32
#define SEC_SUCCESS(Status) ((Status) >= 0)
#define DLL_NAME TEXT("Secur32.dll")
#define NT4_DLL_NAME TEXT("Security.dll")
#pragma comment(lib, "Secur32.lib")

#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
#include <ntsecapi.h>


BOOL SetSeTcbPrivilege()
{
    TOKEN_PRIVILEGES tp;
    LUID luid;
    HANDLE hProcessToken;

    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES,
        &hProcessToken))
    {
        _tprintf(_T("OpenProcessToken failed with error 0x%.8X\n"), GetLastError());
        return FALSE;
    }

    if (!LookupPrivilegeValue(
        NULL,
        SE_TCB_NAME,
        &luid))
    {
        _tprintf(_T("LookupPrivilegeValue failed with error 0x%.8X\n"), GetLastError());
        CloseHandle(hProcessToken);
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // Enable the privilege
    if (!AdjustTokenPrivileges(
        hProcessToken,
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL,
        (PDWORD)NULL))
    {
        _tprintf(_T("AdjustTokenPrivileges failed with error 0x%.8X\n"), GetLastError());
        CloseHandle(hProcessToken);
        return FALSE;
    }

    CloseHandle(hProcessToken);

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        _tprintf(_T("The token does not have the privilege \"SeTcbPrivilege\". \n"));
        return TRUE;
    }

    return TRUE;
}

void _tmain()
{
    SetSeTcbPrivilege();

    CHAR szProcName[] = "LsaTestLogonProcess";
    LSA_STRING lsaProcName ={ strlen(szProcName), strlen(szProcName) + 1, szProcName };

    LSA_OPERATIONAL_MODE dummy;
    HANDLE hLsaHandle;
    NTSTATUS status;

    status = LsaRegisterLogonProcess(&lsaProcName, &hLsaHandle, &dummy);
}

All replies (2)

Friday, November 16, 2018 12:27 AM | 1 vote

Default Windows configurations don't give Limited users or Administrators the SeTcbPirivilege in their tokens.  This can be changed in the Local Security Policy setting for User Rights Assignment.  See /en-us/windows/security/threat-protection/security-policy-settings/act-as-part-of-the-operating-system


Sunday, November 18, 2018 4:27 PM

Also, the code has a logic error.

The test for

  if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        _tprintf(_T("The token does not have the privilege \"SeTcbPrivilege\". \n"));
        return TRUE;
    }

should take place BEFORE the call to CloseHandle.

But the way to add a privilege to an account programmatically is to use LsaAddAccountRights function