Search code examples
cwindowsipcshared-memoryprivileges

Sharedmemory between different sessions


I have two applications:

first one: running with SYSTEM Privileges started by a service and the second one: running still as SYSTEM but with lower privileges (SE_GROUP_INTEGRITY = "S-1-16-4096")

I want both applications to communicate over sharedmemory. Both need to read and write.

In my first application i create the filemapping with specific SECURITY_ATTRIBUTES i learned from this post: How to share memory between services and user processes?

SECURITY_ATTRIBUTES attributes;
ZeroMemory(&attributes, sizeof(attributes));
attributes.nLength = sizeof(attributes);
ConvertStringSecurityDescriptorToSecurityDescriptor(
    L"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWR;;;IU)",
    SDDL_REVISION_1,
    &attributes.lpSecurityDescriptor,
    NULL);
HANDLE test = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, "Global\\Test");

Everything works as expected, but if i then try to open the file mapping in my second application, it crashes with an access violation at OpenFileMapping.

HANDLE test = OpenFileMapping(FILE_ALL_ACCESS, FALSE, 1024, "Global\\Test");

Solution

  • if you want allow access to object for Low Integrity code you need add Low mandatory level (SDDL_ML_LOW) Integrity label (SDDL_MANDATORY_LABEL) to security descriptor. for example

    "D:PNO_ACCESS_CONTROLS:(ML;;NW;;;LW)"
    

    so in general code is next:

    ULONG CreateSectionWithLowAccess(PHANDLE SectionHandle, ULONG dwMaximumSize, PCWSTR lpName)
    {
        SECURITY_ATTRIBUTES sa = { sizeof(sa) };
    
        if (ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:PNO_ACCESS_CONTROLS:(ML;;NW;;;LW)", 
            SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL))
        {
            *SectionHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, dwMaximumSize, lpName);
    
            LocalFree(sa.lpSecurityDescriptor);
    
            return *SectionHandle ? NOERROR : GetLastError();
        }
    
        return GetLastError();
    }