如何检查进程是否启用了 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 文件(从中创建进程)是否动态重定位 - 我们可以使用 NtQueryInformationProcess
和 ProcessImageInformation
- 它 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;
}
比如说,如果我有一个进程 ID PID
,是否有 WinAPI 可以查明该特定进程的 ASLR 是否为 enabled/disabled?
ASLR 不是针对每个进程启用的,而是仅针对那些在 IMAGE_OPTIONAL_HEADER
.DllCharacteristics
成员中具有 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
的可执行文件。当然必须有 relocs。
用于检查,exe 文件(从中创建进程)是否动态重定位 - 我们可以使用 NtQueryInformationProcess
和 ProcessImageInformation
- 它 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;
}