Search code examples
windowswindows-8desktopuacaccess-token

How can I get the Primary access token in windows 8?


I want to get the primary token so that I can get the access of OpenInputDesktop() and do my necessary things.

I browsed all over the sites for help and found the conclusive code as below but I got an error on calling DuplicateTokenEx() is 998 which means invalid access to memory location.

 HANDLE GetCurrentUserToken()
{
    HANDLE currentToken = 0;
    PHANDLE primaryToken = 0;

    unsigned int winlogonPid = 0;

    int dwSessionId = 0;
    PHANDLE hUserToken = 0;
    PHANDLE hTokenDup = 0;

    PWTS_SESSION_INFO pSessionInfo = 0;
    DWORD dwCount = 0;

    WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, 
                         &pSessionInfo, &dwCount);

    //TestLog("Error on WTSEnumerateSessions(): %d",GetLastError());

    int dataSize = sizeof(WTS_SESSION_INFO);

    for (DWORD i = 0; i < dwCount; ++i)
    {
        WTS_SESSION_INFO si = pSessionInfo[i];
        if (WTSActive == si.State)
        {
            dwSessionId = si.SessionId;
            break;
        }
    }

    WTSFreeMemory(pSessionInfo);

    array<Process^>^localByName = Process::GetProcessesByName( "winlogon" );


    for (int i=0;i<localByName->Length;i++)
    {
        Process ^ p1 = (Process^)(localByName->GetValue(i));

        if ((unsigned int)p1->SessionId == dwSessionId)
        {
            winlogonPid = (unsigned int)p1->Id;
        }
    }

    // obtain a handle to the winlogon process
    HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
    TestLog("Error on OpenProcess():",GetLastError());

    // obtain a handle to the access token of the winlogon process
    if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, &currentToken))
    {
        TestLog("Error on OpenProcessToken():",GetLastError());
        CloseHandle(hProcess);
        return false;
    }

    BOOL bRet ;
    // bRet = DuplicateTokenEx(currentToken,
    //         MAXIMUM_ALLOWED /*TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS*/, 
    //         NULL/*0*/, 
    //         SecurityImpersonation, TokenImpersonation, primaryToken);

    bRet = DuplicateTokenEx(currentToken, 
                            TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 
                            NULL, SecurityImpersonation, 
                            TokenPrimary, primaryToken);

    TestLog("Error on DuplicateTokenEx():",GetLastError());
    TestLog("return value of DuplicateTokenEx()",bRet);

    int errorcode = GetLastError();
    if (bRet == false)
    {
        return 0;
    }

    return primaryToken;
}

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Hello World");

    TestLog("**Start TestLaunchExeOneTime**",0);
    HANDLE hTokenNew = NULL, hTokenDup = NULL;
    HMODULE  hmod = LoadLibrary(L"kernel32.dll");

    hTokenDup = GetCurrentUserToken();

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    memset(&si,0,sizeof(STARTUPINFO));
    si.cb = sizeof( STARTUPINFO );
    si.lpDesktop = L"winsta0\\default";

    LPVOID  pEnv = NULL;
    DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    HMODULE hModule = LoadLibrary(L"Userenv.dll");
    if(hModule )
    {
        if(CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))
        {
            //WriteToLog("CreateEnvironmentBlock Ok");
            dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;    
        }
        else
        {
            TestLog("Error on CreateEnvironmentBlock():",GetLastError());
            pEnv = NULL;
        }
    }

    //

    if ( !CreateProcessAsUser( hTokenDup,
        NULL,
        L"C:\\temp\\DesktopDuplicationmilliseconds.exe",  
        NULL,
        NULL,
        FALSE,
        dwCreationFlag,
        pEnv,
        NULL,
        &si,
        &pi
        ))
    {

    }
    else
    {
        TestLog("Error on CreateProcessAsUser():",GetLastError());
        // printf("error : %d",GetLastError());
    }

    return 0;
}

Solution

  • You haven't allocated any memory for the primary token. The primaryToken variable is a pointer to a handle, but you haven't actually pointed it to anything. (You've also declared GetCurrentUserToken as a function that returns a handle, but are actually returning a pointer to a handle.)

    You need to either explicitly allocate the memory for the handle:

    primaryToken = malloc(sizeof(HANDLE));
    
    [...]
    
    return *primaryToken;
    

    or, more sensibly, define primaryToken as a HANDLE rather than a pointer and pass a reference to it in the appropriate place:

    HANDLE primaryToken;
    
    [...]
    
    bRet = DuplicateTokenEx(currentToken, 
                            TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 
                            NULL, SecurityImpersonation, 
                            TokenPrimary, &primaryToken);