C 如何在不引入文件系统竞争的情况下获得当前可执行文件的文件句柄?
我需要从当前可执行文件中读取一些数据(即调试信息) 通过调用C 如何在不引入文件系统竞争的情况下获得当前可执行文件的文件句柄?,c,windows,winapi,nt,C,Windows,Winapi,Nt,我需要从当前可执行文件中读取一些数据(即调试信息) 通过调用QueryFullProcessImageName,然后使用它返回的路径打开文件并从中读取,这是很简单的 但是,这种方法在检索文件路径C:\my\u program.exe和打开名为C:\my\u program.exe的文件之间引入了一个窗口。在该窗口中,原始文件可以替换为我不想读取的其他文件,即发生文件系统争用。 我有一个外部强加的要求,这场比赛不应该发生 基本上,我需要一些不存在的QueryFullProcessImageHand
QueryFullProcessImageName
,然后使用它返回的路径打开文件并从中读取,这是很简单的
但是,这种方法在检索文件路径C:\my\u program.exe
和打开名为C:\my\u program.exe
的文件之间引入了一个窗口。在该窗口中,原始文件可以替换为我不想读取的其他文件,即发生文件系统争用。我有一个外部强加的要求,这场比赛不应该发生 基本上,我需要一些不存在的
QueryFullProcessImageHandle
而不是QueryFullProcessImageName
,这样我就可以在不按名称打开文件的情况下读取它
通过阅读ReactOS源代码,我了解到这种句柄很可能也存在于Windows上,并且保存在EPROCESS
结构中(作为SectionObject
的一部分),它实际上用于实现QueryFullProcessImageName
是否有任何方法可以使用WinAPI或至少NT API获取此句柄?(
GetModuleHandleEx
似乎返回完全不同的句柄。)警告-官方不支持这一切。使用未记录的函数强>
存在100%清洁溶液,基于
所以一般来说,我们下一步需要做什么
内存外观文件名信息
,)
获取文件名(本机格式)。注意:MemoryMappedFilenameInformation
在调用时始终返回当前文件名-因此,如果文件已重命名,我们将获得新名称状态\u SUCCESS
我们将打开正确的文件-完成状态\u不相同\u设备
需要取消映射文件2Mappedasfile和
转到2NTSTATUS 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);
}
}
NTSTATUS映射模块(void*File1MappedAsAnImage,void**pFile2MappedAsFile)
{
静态挥发性UCHAR-guz;
PVOID stack=alloca(guz);
联合{
pvoidbuf;
PUNICODE_字符串文件名;
};
大小\u T cb=0,rcb=256,视图大小;
NTSTATUS status,s=状态\未成功;
布尔布萨姆;
做
{
bSame=TRUE;
做
{
如果(cb 如果(0@Jean-Françoisfare-这不是真的。文件可以在运行时重命名。@RbMm:你说得对。在Windows 10上可以这样做。我确信相反,但在Windows 10上似乎是可能的!!@Jean-Françoisfare-在什么问题上?运行任何exe,然后在资源管理器或任何文件浏览器中重命名。测试并查看结果。文件可以重新保存.删除的罐头not@Jean-FrançoisFabre-不仅在win10上,甚至在xp上。在任何windows中。打开文件部分仅防止删除,但不防止重命名操作我尝试过(刚刚在windows 8.1上确认),它们可以重命名,也可以创建同名文件。很有趣!我曾考虑过在factum之后检查打开的文件,但也没有找到一种不使用种族的方法。(在接受答案之前,我需要更详细地测试和理解这一点。)@user2665887-是,打开了文件事后事实检查循环-如果不是相同的文件-再次启动循环。这可能是因为MemoryMappedFilenameInformation在调用时总是返回当前文件名。而NTAREMAppedFileName在建议使用未记录的函数时,总是显式声明他的解决方案正在处理未记录的实现细节,可能不支持未公开的操作系统或配置集,并且可能随时停止工作。@IInspectable-一如既往,您是否对解决方案有一些具体的技术说明?说它不正确,因为*。或者您可以提出更好或更“记录”的建议解决方案?此解决方案即使在win2000和最新的10.1607中也能工作-超过16年,但有时会停止工作“您对解决方案有一些具体的技术说明吗?”-是的。技术说明是:请指出,所有这些都没有得到官方支持。即使您没有得到官方支持,专业软件开发人员也会希望了解这方面的信息。
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);
}
}