Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the logged-on user's SID in Windows

Tags:

I need to get the string format SID of the logged-on user. I already have the username and am trying to use LookupAccountName to get the SID. This works partly - I do get a SID but it is only a partial match to the user's actual SID.

I do not want the SID of the process owner as the process may be elevated (impersonating), but rather I want the SID of the user who is logged on where the process is running.

The code needs to work with non-elevated privileges.

This is my code so far

LPCTSTR wszAccName = TEXT("hardcoded username for testing");
LPTSTR wszDomainName = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * 1024);
DWORD cchDomainName = 1024;
SID_NAME_USE eSidType;
SID sid;
DWORD cbSid = 1024;
if (!LookupAccountName(NULL, wszAccName, &sid, &cbSid, wszDomainName, &cchDomainName, &eSidType)) {
    return GetLastError();
}

if (!ConvertSidToStringSid(&sid, &pszSidBuffer)) {
    return GetLastError();
}

This yields a SID like "S-1-5-21-1-1234567890-9-1000" But the user's actual SID is like "S-1-5-21-3214321539-1234567890-2233445522-1000" (as per the process owner and the registry key under HKEY_USERS). Note how the SIDs are the same except for the 5th and 7th components, which are only 1 digit each but should be longer.

How do I get the user's actual/complete SID?

Also, I'm a total C/C++ newbie (and the code above is not production quality at all). And I'm using /NODEFAULTLIB in order to avoid linking VC runtimes. Sorry about that.

like image 252
Blaze Avatar asked Sep 07 '16 09:09

Blaze


People also ask

What is SID in user account?

The SID (Security IDentifier) is a unique ID number that a computer or domain controller uses to identify you. It is a string of alphanumeric characters assigned to each user on a Windows computer, or to each user, group, and computer on a domain-controlled network such as Indiana University's Active Directory.

What is Windows account SID?

In the context of Windows computing and Microsoft Active Directory (AD), a security identifier (SID) is a unique value that is used to identify any security entity that the Windows operating system (OS) can authenticate.

Where are SID stored?

Each account or group, or each process that runs in the security context of the account, has a unique SID that's issued by an authority, such as a Windows domain controller. The SID is stored in a security database.


1 Answers

Your code doesn't provide a properly-sized buffer for the SID returned by LookupAccountName(). This results in stack corruption and undefined behaviour, which might conceivably explain why you're not getting the SID you were expecting. (Although I rather suspect that you're actually passing in the wrong username, or an improperly formatted username.)

Anyway, to fix the most obvious problem, the code should look more like this:

#include <Windows.h>
#include <Sddl.h>

#include <stdio.h>

int main(int argc, char ** argv)
{
    LPCTSTR wszAccName = TEXT("domainname\\username");
    LPTSTR wszDomainName = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * 1024);
    DWORD cchDomainName = 1024;
    SID_NAME_USE eSidType;
    LPTSTR sidstring;
    char sid_buffer[1024];
    DWORD cbSid = 1024;
    SID * sid = (SID *)sid_buffer;

    if (!LookupAccountName(NULL, wszAccName, sid_buffer, &cbSid, wszDomainName, &cchDomainName, &eSidType)) {
        return GetLastError();
    }

    if (!ConvertSidToStringSid(sid, &sidstring)) {
        return GetLastError();
    }

    printf("%ws\n", sidstring);
    return 0;

}

That's still not the correct way to do it, of course; you are supposed to call LookupAccountName() twice, once to determine the buffer length and then a second time to retrieve the actual information. But it demonstrates what you've done wrong, and is good enough for testing purposes.

like image 132
Harry Johnston Avatar answered Oct 11 '22 15:10

Harry Johnston