c++winapiwindows-security

How to check if ASLR is enabled for a process?


Say, if I have a process ID PID, is there a WinAPI to find out if ASLR is enabled/disabled for that specific process?


Solution

  • ASLR enabled not per process but for only those executable which have IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE in IMAGE_OPTIONAL_HEADER.DllCharacteristics member. and of course must have relocs.

    for check, are exe file (from which process created) dynamically relocated - we can use NtQueryInformationProcess with ProcessImageInformation - it return SECTION_IMAGE_INFORMATION for exe file. process can be opened with PROCESS_QUERY_LIMITED_INFORMATION (this is enough. and this let us open even protected processes). the ImageDynamicallyRelocated bit is say - are ASLR applied for image.

    ULONG CheckASLR(ULONG dwProcessId, BOOLEAN& bASLR)
    {
        if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId))
        {
            SECTION_IMAGE_INFORMATION sii;
    
            NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessImageInformation, &sii, sizeof(sii), 0);
    
            CloseHandle(hProcess);
    
            if (0 <= status)
            {
                bASLR = sii.ImageDynamicallyRelocated;
    
                return NOERROR;
            }
    
            return RtlNtStatusToDosError(status);
        }
    
        return GetLastError();
    }
    

    if we want query this not only for exe file but for specific module, need first get path of this module (can use GetMappedFileName ), open file, create section for it and query this section for SectionImageInformation. on exit we again got SECTION_IMAGE_INFORMATION

    NTSTATUS CheckASLR(HANDLE hProcess, PVOID hmod, BOOLEAN& bASLR)
    {
        static volatile UCHAR guz = 0;
    
        PVOID stack = alloca(guz);
    
        SIZE_T cb = 0, rcb = MAX_PATH*sizeof(WCHAR);
    
        union {
            PVOID buf;
            PUNICODE_STRING ObjectName;
        };
    
        NTSTATUS status;
        do 
        {
            if (cb < rcb)
            {
                cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
            }
    
            if (0 <= (status = NtQueryVirtualMemory(hProcess, hmod, MemoryMappedFilenameInformation, buf, cb, &rcb)))
            {
                HANDLE hFile, hSection;
                IO_STATUS_BLOCK iosb;
    
                OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, ObjectName };
    
                status = NtOpenFile(&hFile, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
    
                if (0 <= status)
                {
                    status = NtCreateSection(&hSection, SECTION_QUERY, 0, 0, PAGE_READONLY, SEC_IMAGE, hFile);
    
                    NtClose(hFile);
    
                    if (0 <= status)
                    {
                        SECTION_IMAGE_INFORMATION sii;
    
                        status = ZwQuerySection(hSection, SectionImageInformation, &sii, sizeof(sii), 0);
    
                        NtClose(hSection);
    
                        if (0 <= status)
                        {
                            bASLR = sii.ImageDynamicallyRelocated;
                        }
                    }
                }
    
                break;
            }
    
        } while (status == STATUS_BUFFER_OVERFLOW );
    
        return status;
    }