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

标签 c++ winapi windows-security

比如说,如果我有一个进程 ID PID,是否有一个 WinAPI 可以查明 ASLR 是否存在?是否为该特定进程启用/禁用?

最佳答案

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

为了检查,exe 文件(从中创建进程)是否动态重新定位 - 我们可以使用 NtQueryInformationProcessProcessImageInformation - 它返回 SECTION_IMAGE_INFORMATION对于exe文件。可以使用 PROCESS_QUERY_LIMITED_INFORMATION 打开进程(这就足够了。这让我们甚至可以打开 protected 进程)。 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;
}

关于c++ - 如何检查进程是否启用了 ASLR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47105480/

相关文章:

c++ - 为什么指针可以避免 warnary-bounds

visual-studio-2008 - 应用程序无法正常启动 0xc00007b

php - 获取上传文件的真实路径

c++ - 是否可以使用 static_cast 避免 vtable 开销?

c++ - 从叶类继承

c++ - conservativeResize() 新值的值为零

c++ - MediaFoundation HEVC H265 编码

c# - 如何让 HttpClient 随请求一起传递凭据?

c++ - 在 Windows 10 上创建缓冲区溢出

windows - 没有网络访问权限的虚拟服务帐户,如 NT AUTHORITY\LocalService