Untitled

 avatar
unknown
plain_text
22 days ago
4.7 kB
3
Indexable
#include <stdio.h>
#include <Windows.h>
#include <sddl.h>

#define MAX_NAME 256

/*
* The API_CHECK_SUCCESS macro helps handling APIs which return FALSE on failure.
* It just catch the case when the function fails, print a message and jumps to
* the Cleanup label at the end of the function where resources are released.
* Enclose API calls with the macro this way:
* API_CHECK_SUCCESS( FunctionToCall(Arg1, Arg2, Arg3, ....) );
*/
#define API_CHECK_SUCCESS(_CALL) \
do { \
    if (FALSE == (_CALL)) { \
        dwRet = GetLastError(); \
        fprintf(stderr, "[%d] - %s failed with 0x%08x\n", __LINE__, #_CALL, dwRet); \
        goto Cleanup; \
    } \
} while (0)




int main()
{
    DWORD           dwRet = 0;          // Error code for our program

	HANDLE          hMyToken;           // Handle to the token
	HANDLE          hThisProcess;       // Handle to the process
    TOKEN_GROUPS*   pTokenGroups;       // TOKEN_GROUPS structure which receives groups list
    DWORD           bufferSize = 0;     // Size to allocate for GetTokenInformation

    WCHAR           wszName[MAX_NAME];      // Temporary buffer to store the name part for the SID
    WCHAR           wszDomain[MAX_NAME];    // Temporary buffer to store the domain part for the SID
    DWORD           dwNameSize = 0;         // Stores the size of the name in wszName
    DWORD           dwDomainSize = 0;       // Stores the size of the domain in wszDomain
    WCHAR*          wszSID = NULL;          // Points to a text representation of the SID
    SID_NAME_USE    sidType;                // SID type enum.


    // 1. Get a handle to the current process
	hThisProcess = GetCurrentProcess();

    // 2. Open the process's token
    API_CHECK_SUCCESS(OpenProcessToken(
        hThisProcess,
        TOKEN_QUERY,
        &hMyToken));

    /*
    * 3. Get the list of groups by calling GetTokenInformation
    * 
    * 3.1 Get required memory size.
    * GetTokenInformation does not allocate memory for us. We need to allocate
    * a buffer.
    * Usual convention in Windows. We first call the API with a NULL argument
    * which is a convention for asking what is the required size for the area
    * which will contain information.
    */
    GetTokenInformation(
        hMyToken,
        TokenGroups,
        nullptr,
        pTokenGroups,
        0,
        &bufferSize);

    // 3.2 Allocate sufficent memory
    pTokenGroups = static_cast<TOKEN_GROUPS *>( malloc(bufferSize) );
    if (nullptr == pTokenGroups)
    {
        fprintf(stderr, "malloc returns NULL\n");
        dwRet = ENOMEM;
        goto Cleanup;
    }

    /*
    * 3.3 Call GetTokenInformation again
    * This time, specifying the memory buffer where to store data.
    */
    
    API_CHECK_SUCCESS(GetTokenInformation(
        hMyToken,
        TokenGroups,
        pTokenGroups,
        bufferSize,
        &bufferSize));

    // 4. Display group information.
    // Print a header in the console and loop over the groups
    wprintf(L"Groups for token %08X:\n", hMyToken);

    for (DWORD i = 0; i < pTokenGroups->GroupCount; ++i)
    {
        // 4.1 Get a text representation of the SID
        ConvertSidToStringSidW(pTokenGroups->Groups[i].Sid, &wszSID);

        // 4.2 Prepare temporary buffers to store the result of SID->name translation
        dwNameSize = MAX_NAME * sizeof(WCHAR);
        ZeroMemory(wszName, dwNameSize);
        
        dwDomainSize = MAX_NAME * sizeof(WCHAR);
        ZeroMemory(wszDomain, dwDomainSize);

        // 4.3 calls LookupAccountSidW to perform SID->name translation
        if (LookupAccountSidW(
            NULL,                    // Local computer
            pTokenGroups->Groups[i].Sid,
            wszName,
            &dwNameSize,
            wszDomain,
            &dwDomainSize,
            &sidType))
        {
            // SID->name translation was successfull

            // 4.3a.1 Display group in the console
            if (wcsnlen_s(wszDomain, dwDomainSize) == 0)
                wprintf(L"[%02d] %s %s\n", i, wszName, wszSID);
            else
                wprintf(L"[%02d] %s\\%s %s\n", i, wszDomain, wszName, wszSID);
        }
        else
        {
            // SID->name translation failed

            // 4.3b.1 Just display the SID in the console
            wprintf(L"[%02d] %s\n", i, wszSID);
        }

        // 4.4 We need to free wszSID here
        LocalFree(wszSID);
    }

Cleanup:

    // 5. Be polite and close the handle we opened to the token.
    CloseHandle(hMyToken);

    return 0;
}
Editor is loading...
Leave a Comment