2

我需要从当前的可执行文件中读取一些数据(即调试信息)。

这很简单,只需调用QueryFullProcessImageName,然后使用它返回的路径打开文件并从中读取。
但是,这种方式在检索文件路径C:\my_program.exe和打开名为C:\my_program.exe. 在该窗口中,可以将原始文件替换为我不想阅读的其他文件,即发生文件系统竞争。
我有一个外部强加的要求,即不应发生这场比赛。

基本上,我需要类似不存在的东西,QueryFullProcessImageHandle而不是QueryFullProcessImageName这样我就可以在不按名称打开文件的情况下从中读取。

通过阅读 ReactOS 源,我了解到这样的句柄很可能也存在于 Windows 上,并且保持在结构中EPROCESS(作为.SectionObjectQueryFullProcessImageName

有没有办法使用 WinAPI 或至少 NT API 获得这个句柄?
GetModuleHandleEx似乎返回完全不同的句柄。)

4

1 回答 1

1

warning - none of this is officially supported. undocumted functions used!

exist 100% clean solution based on NtAreMappedFilesTheSame

NTSYSAPI
NTSTATUS
NTAPI
NtAreMappedFilesTheSame (
    __in PVOID File1MappedAsAnImage,
    __in PVOID File2MappedAsFile
    );

so in general words we need do next

  1. got File1MappedAsAnImage address for exe/dll
  2. with ZwQueryVirtualMemory(,MemoryMappedFilenameInformation,) get FileName (in native format). note: MemoryMappedFilenameInformation always return current file name at time, when called - so if file already renamed - we got it new name
  3. open file by given name
  4. map file and got File2MappedAsFile
  5. call NtAreMappedFilesTheSame(File1MappedAsAnImage, File2MappedAsFile)
  6. if we got STATUS_SUCCESS we open correct file - done here
  7. if we got STATUS_NOT_SAME_DEVICE need unmap File2MappedAsFile and goto 2
  8. if we got other status - some error occurred

here complete working example

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

also you can look for this topic

于 2016-11-01T22:23:07.943 回答