1

I am trying to use these features to get the username running the process. Here is the code:

#include <windows.h>
#include <psapi.h>

using namespace std;

int main()    
{
    HANDLE hProcess = GetCurrentProcess();
    HANDLE hToken;
    OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
    DWORD len = 0;
    GetTokenInformation(hToken, TokenOwner, NULL, 0, &len);
    PTOKEN_OWNER to = (PTOKEN_OWNER)LocalAlloc(LPTR, len);
    GetTokenInformation(hToken, TokenOwner, (LPVOID)&to, len, &len);
    char nameUser[50];
    DWORD nameUserSize = sizeof(nameUser);
    SID_NAME_USE snu;
    cout << "work";
    LookupAccountSidA(NULL, to->Owner, nameUser, &nameUserSize, NULL, NULL, &snu);
    cout << "not work";
    cout << nameUser << endl;
    LocalFree(to);
    CloseHandle(hToken);
    CloseHandle(hProcess);
    return 0;
}

I have all the breaks at the moment where LookupAccountSidA() is called. But I suspect the problem is due to the fact that I was wrong with the arguments to this function, or I am wrong to create a structure TOKEN_OWNER. The second option is more likely, since I do not understand how memory is allocated here.

I took an example from MSDN and rewrote it to my needs, but nothing works. Here are some examples from MSDN:

Getting the Logon SID in C++

Searching for a SID in an Access Token in C++

P.S. For russian-speaking:

https://ru.stackoverflow.com/questions/519602/

Paul
  • 6,061
  • 6
  • 39
  • 70
  • Note that you probably want `TokenUser` rather than `TokenOwner`. If you're running elevated, I think `TokenOwner` will usually be the Administrators group. – Harry Johnston May 03 '16 at 23:09
  • Ok. You are right. But why? I don't understand different. –  May 08 '16 at 17:42
  • The `TokenOwner` isn't the person who owns the token. It is the part of the token that determines the default owner of objects created by a process or thread running in the token's security context. The `TokenUser` is the user that the token represents. – Harry Johnston May 08 '16 at 21:12

1 Answers1

3

Your second call to GetTokenInformation() is passing the wrong memory address in the 3rd parameter. You are passing the memory address of the to variable itself, so you are asking GetTokenInformation() to write into surrounding stack space. You need to pass the memory address that the variable is pointing at instead (the allocated TOKEN_OWNER structure), so get rid of the & operator (and the type-cast, which is not necessary):

GetTokenInformation(hToken, TokenOwner, to, len, &len);

You are also not doing any error handling at all, so you don't know if memory is being allocated successfully, or if any API function are failing.

Try this instead:

#include <windows.h>
#include <psapi.h>

using namespace std;

int main()    
{
    DWORD dwError;

    HANDLE hToken;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    {
        dwError = GetLastError();
        cerr << "OpenProcessToken failed, error " << dwError;
        return 0;
    }

    DWORD len = 0;
    if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &len))
    {
        dwError = GetLastError();
        if (dwError != ERROR_INSUFFICIENT_BUFFER) 
        {
            cerr << "GetTokenInformation failed, error " << dwError;
            CloseHandle(hToken);
            return 0;
        }
    }

    PTOKEN_OWNER to = (PTOKEN_OWNER) LocalAlloc(LPTR, len);
    if (!to)
    {
        dwError = GetLastError();
        cerr << "LocalAlloc failed, error " << dwError;
        CloseHandle(hToken);
        return 0;
    }

    if (!GetTokenInformation(hToken, TokenOwner, to, len, &len))
    {
        dwError = GetLastError();
        cerr << "GetTokenInformation failed, error " << dwError;
        LocalFree(to);
        CloseHandle(hToken);
        return 0;
    }

    char nameUser[256] = {0};
    char domainName[256] = {0};
    DWORD nameUserLen = 256;
    DWORD domainNameLen = 256;
    SID_NAME_USE snu;

    if (!LookupAccountSidA(NULL, to->Owner, nameUser, &nameUserLen, domainName, &domainNameLen, &snu))
    {
        dwError = GetLastError();
        cerr << "LookupAccountSid failed, error " << dwError;
        LocalFree(to);
        CloseHandle(hToken);
        return 0;
    }

    cout << domainName << '/' << nameUser << endl;

    LocalFree(to);
    CloseHandle(hToken);

    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • OK. You are right about "get rid of the & operator". But its code also didn't work. –  May 06 '16 at 18:27
  • @van9petryk in what way? What is the output? – Remy Lebeau May 06 '16 at 18:29
  • LookupAccountSidA(NULL, to->Owner, nameUser, &nameUserLen, NULL, NULL, &snu) Argument #6. It mandatory parametr –  May 06 '16 at 18:36
  • Probably, in function LookupAccountSid we have null-pointer dereference, and this leads to crash –  May 06 '16 at 18:38
  • Yes. Now it work. Thank you. But can you explain, what happens at this line: "PTOKEN_OWNER to = (PTOKEN_OWNER) LocalAlloc(LPTR, len);"??? As I understood, we allocate memory and pointer, that returned, we cast to the PTOKEN_OWNER pointer. I never saw this way to allocate memory in C++ with operator new[]. But how memory allocates to PSID, that is pointer to SID in TOKEN_OWNER structure? –  May 06 '16 at 18:52
  • The function writes both the `TOKEN_OWNER` structure *and* the SID into the buffer you provide. – Harry Johnston May 08 '16 at 21:07
  • Right. There is only one memory buffer, containing both the `TOKEN_OWNER` and the `SID`, where the `TOKEN_OWNER` is pointing at the `SID` portion of the buffer. The first call calculates the total buffer size, then the buffer is allocated, then the second call fills the buffer and sets up the pointers to the various sections of the buffer. – Remy Lebeau May 08 '16 at 21:15