0
votes

I have a task based on an algorithm to receive the access rights for a certain file or folder and I've tried to implement it but some parts don't seem to be clear. What I've been asked for:

1) Use the function GetNamedSecurityInfo(), for example: GetNamedSecurityInfo(path,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL, NULL,&a,NULL, &pSD)

2) Futher, use an SID to receive the rights: Use these functions to receive the SID: GetAclInformation(), then GetAce().

3) Now you can use the LookupAccountSid() function and if is was successfull, compare pACE->Mask with all the constants, for example "GENERIC_ALL, GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE for files etc." displaying the access rights.

And how I tried to implement this algorithm: // First getting process SID

PSID g_pSID;
BOOL GetCurrentProcessSID()
{
    DWORD dwSize = 0, dwError, dwResult = 0;
    HANDLE hToken;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    {
        printf("OpenProcessToken Error %u\n", GetLastError());
        return FALSE;
    }

    // Call GetTokenInformation to get the buffer size.
    TOKEN_USER tU;
    if (!GetTokenInformation(hToken, TokenUser, &tU, 0, &dwSize))
    {
        dwError = GetLastError();
        if (dwError != ERROR_INSUFFICIENT_BUFFER)
        {
            std::cout << "GetTokenInformation failed, error " << dwError;
            CloseHandle(hToken);
            return 0;
        }
    }

    PTOKEN_OWNER to = (PTOKEN_OWNER)LocalAlloc(LPTR, dwSize);
    if (!to)
    {
        dwError = GetLastError();
        std::cout << "LocalAlloc failed, error " << dwError;
        CloseHandle(hToken);
        return 0;
    }

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

    g_pSID = to->Owner;
    return TRUE;
}

//Then I used the iteration through the ACL list:

std::stringstream g_TestSecurityResult;
void TestSecurity( wchar_t* path )
{
    g_TestSecurityResult = std::stringstream();
    GetCurrentProcessSID();
    PACL pDacl; 
    PSECURITY_DESCRIPTOR pSD;
    GetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD);

    ACL_SIZE_INFORMATION aclSizeInfo = { sizeof(ACL) };

    BOOL fResult = GetAclInformation( pDacl, &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), ACL_INFORMATION_CLASS::AclSizeInformation );

    if (fResult)
    {
        for (DWORD dwIndex = 0; dwIndex < aclSizeInfo.AceCount; ++dwIndex)
        {
            LPVOID pTempAce = nullptr;

            fResult = ::GetAce(pDacl, dwIndex, &pTempAce);
            if (fResult)
            {
                PSID pSid = &((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart;

                if (EqualSid(pSid, &g_pSID))
                {
                    g_TestSecurityResult << "User: " << userNameFromSid(&g_pSID) << std::endl;
                    g_TestSecurityResult << "\tAccess mode: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessMode << "\n";
                    g_TestSecurityResult << "\tAccess permissions: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessPermissions << "\n";
                    g_TestSecurityResult << "\tInheritance: " << ((EXPLICIT_ACCESS*)pTempAce)->grfInheritance << "\n";
                    g_TestSecurityResult << std::endl;
                }
            }
            else
            {
                g_TestSecurityResult << "GetAce() failed." << GetLastError();
                break;
            }
        }
    } else {
        g_TestSecurityResult << "Error in GetAclInformation(): " << GetLastError();
    }
}

std::string userNameFromSid(PSID userSid)
{
    char buffName[MAX_BUFF_SIZE];
    DWORD buffNameSize = MAX_BUFF_SIZE;
    char buffDomain[MAX_BUFF_SIZE];
    DWORD buffDomainSize = MAX_BUFF_SIZE;
    SID_NAME_USE SidType;

    if (LookupAccountSid(NULL, userSid, buffName, &buffNameSize, buffDomain, &buffDomainSize, &SidType)) {
        return buffName;
    } else {
        DWORD dwResult = GetLastError();
        printf("GetTokenInformation Error %u\n", dwResult);
    }

    /*Here some code to print error in a Message box*/
    return "";
}

The problem: The code is working but at the line if (EqualSid(pSid, &g_pSID)) debugger goes through and skips the SID that I've received from my process. In other words, I can't get any information from the ACL list, even though I'm running the process and Visual Studio under Administrator account (not using the "Run as Administrator", and I'll try it but still... The received SID is valid and I can get the name of the process owner using the above function. What could be something that I'm doing wrong here?

Code sources: https://gist.github.com/m4x1m1l14n/37f39c5d25855c2b1d3a6334851f7549 How to get the logged-on user's SID in Windows GetTokenInformation, TOKEN_OWNER, и LookupAccountSidA

1
why you not use AccessCheck ?RbMm
@RbMm because I'm implementing an algorithm that was given by a university course so that it says "use this, and use that, and so on" as you can see, I'm now trying to observe AccessCheck() but still the original task was not about AccessCheck()Ivan Silkin
FYI, this assignment should be updated for at least UAC in Vista (2006). Access to a file may be limited by its LABEL_SECURITY_INFORMATION in combination with the integrity level of the current security context (TokenIntegrityLevel) and its mandatory policy (TokenMandatoryPolicy). Also, the kernel AccessCheck (i.e. SeAccessCheck) in Windows 8+ supports Authz conditional ACEs (e.g. used extensively for UWP apps in "%ProgramFiles%\WindowsApps"), for which we may need a file's ATTRIBUTE_SECURITY_INFORMATION and SCOPE_SECURITY_INFORMATION.Eryk Sun
Is this a typo, &g_pSID? Use EqualSid(pSid, g_pSID) instead of EqualSid(pSid, &g_pSID).Rita Han
@Rita Han - MSFT , thank you, I'm probably just forgotten to remove the ampersand from the previous version of my code where I tried to use SID variable instead of pSID pointer... And everything is working for now :DIvan Silkin

1 Answers

0
votes

Thanks to @(Rita Han - MSFT) comment, I've forgotten to remove the ampersand mark from the pSID comparison

EqualSid(pSid, g_pSID);

instead of

EqualSid(pSid, &g_pSID);

And It's properly working for now