如何检查进程是否启用了 ASLR?

How to check if ASLR is enabled for a process?

比如说,如果我有一个进程 ID PID,是否有 WinAPI 可以查明该特定进程的 ASLR 是否为 enabled/disabled?

ASLR 不是针对每个进程启用的,而是仅针对那些在 IMAGE_OPTIONAL_HEADER.DllCharacteristics 成员中具有 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 的可执行文件。当然必须有 relocs。

用于检查,exe 文件(从中创建进程)是否动态重定位 - 我们可以使用 NtQueryInformationProcessProcessImageInformation - 它 return SECTION_IMAGE_INFORMATION 用于 exe 文件。可以使用 PROCESS_QUERY_LIMITED_INFORMATION 打开进程(这就足够了。这让我们甚至可以打开受保护的进程)。 ImageDynamicallyRelocated 位表示 - 是否将 ASLR 应用于图像。

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();
}

如果我们不仅要查询 exe 文件而且要查询特定模块,首先需要获取该模块的路径(可以使用 GetMappedFileName ),打开文件,为其创建部分并查询该部分以获取 SectionImageInformation。在退出时我们再次得到 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;
}