我需要从当前可执行文件中读取一些数据(即调试信息)。
通过调用QueryFullProcessImageName
,然后使用它返回的路径打开文件并从中读取,这很简单。
但是,这种方式会在检索文件路径C:\my_program.exe
和打开名为C:\my_program.exe
的文件之间引入一个窗口。在该窗口期间,原始文件可以替换为我不想阅读的其他文件,即文件系统竞争发生。
我有一个外部强制要求,这场比赛不应该发生。
基本上,我需要一些不存在的QueryFullProcessImageHandle
而不是QueryFullProcessImageName
,所以我可以在不按名称打开文件的情况下从中读取。
通过阅读ReactOS来源,我了解到这样的句柄很可能也存在于Windows上并保存在EPROCESS
结构中(作为SectionObject
的一部分)并且它实际上用于实现QueryFullProcessImageName
。
有没有办法使用WinAPI或至少NT API获取此句柄?
(GetModuleHandleEx
似乎返回完全不同的句柄。)
答案 0 :(得分:1)
警告 - 这些都不是官方支持的。使用了未经处理的函数!
存在100%清洁解决方案NTSYSAPI
NTSTATUS
NTAPI
NtAreMappedFilesTheSame (
__in PVOID File1MappedAsAnImage,
__in PVOID File2MappedAsFile
);
所以一般来说我们需要做下一步
ZwQueryVirtualMemory
(,MemoryMappedFilenameInformation
,)
获取FileName(以原生格式)。 注意:MemoryMappedFilenameInformation
总是在调用时返回当前文件名 - 所以如果文件已经重命名 - 我们得到了新名称 STATUS_SUCCESS
我们打开了正确的文件 - 在这里完成STATUS_NOT_SAME_DEVICE
需要取消映射File2MappedAsFile和
转到2 这里有完整的工作示例
NTSTATUS MapModule(void* File1MappedAsAnImage, void** pFile2MappedAsFile)
{
static volatile UCHAR guz;
PVOID stack = alloca(guz);
union {
PVOID buf;
PUNICODE_STRING FileName;
};
SIZE_T cb = 0, rcb = 256, ViewSize;
NTSTATUS status, s = STATUS_UNSUCCESSFUL;
BOOL bSame;
do
{
bSame = TRUE;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQueryVirtualMemory(NtCurrentProcess(), File1MappedAsAnImage, MemoryMappedFilenameInformation, buf, cb, &rcb)))
{
DbgPrint("%wZ\n", FileName);
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, FileName, OBJ_CASE_INSENSITIVE };
HANDLE hFile, hSection;
IO_STATUS_BLOCK iosb;
if (0 <= (s = NtOpenFile(&hFile, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT)))
{
s = ZwCreateSection(&hSection, SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, hFile);
NtClose(hFile);
if (0 <= s)
{
*pFile2MappedAsFile = 0;
s = ZwMapViewOfSection(hSection, NtCurrentProcess(), pFile2MappedAsFile, 0, 0, 0, &(ViewSize = 0), ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= s)
{
switch (s = NtAreMappedFilesTheSame(File1MappedAsAnImage, *pFile2MappedAsFile))
{
case STATUS_SUCCESS:
DbgPrint("opened original file!");
return STATUS_SUCCESS;
case STATUS_NOT_SAME_DEVICE:
DbgPrint("opened another file!");
bSame = FALSE;
break;
default:
DbgPrint("status = %x\n", s);
}
ZwUnmapViewOfSection(NtCurrentProcess(), *pFile2MappedAsFile);
}
}
}
}
} while (status == STATUS_BUFFER_OVERFLOW);
} while (!bSame);
return status < 0 ? status : s;
}
void Demo()
{
PVOID BaseAddress;
if (0 <= MapModule(GetModuleHandle(0), &BaseAddress))
{
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
您也可以查找此topic