Как получить дескриптор файла для текущего исполняемого файла без представления гонки файловой системы?

Мне нужно прочитать некоторые данные из текущего исполняемого файла (а именно, отладочную информацию).

Это просто сделать, позвонив по телефону QueryFullProcessImageNameзатем, используя возвращенный им путь, откройте файл и прочитайте его.
Тем не менее, этот способ вводит окно между получением пути к файлу C:\my_program.exe и открыв файл с именем C:\my_program.exe, В этом окне исходный файл может быть заменен другим файлом, который я не хочу читать, то есть происходит гонка файловой системы.
У меня есть внешне навязанное требование, чтобы эта гонка не состоялась.

В принципе мне нужно что-то вроде несуществующего QueryFullProcessImageHandle вместо QueryFullProcessImageName так что я мог читать с него, не открывая файл по имени.

Из чтения источников ReactOS я узнал, что такой дескриптор, скорее всего, существует и в Windows и хранится в EPROCESS структура (как часть SectionObject) и это на самом деле используется для реализации QueryFullProcessImageName,

Есть ли способ получить этот дескриптор, используя WinAPI или хотя бы NT API?
(GetModuleHandleEx похоже, возвращает совершенно другую ручку.)

1 ответ

Решение

предупреждение - ничего из этого официально не поддерживается.используются функции без разделов!

существует 100% чистый раствор на основеNtAreMappedFilesTheSame

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

так в общих словах нам нужно сделать дальше

  1. получил адрес File1MappedAsAnImage для exe/dll
  2. с ZwQueryVirtualMemory(,MemoryMappedFilenameInformation) получить имя файла (в собственном формате).нота:MemoryMappedFilenameInformationвсегда возвращать текущее имя файла при вызове - поэтому, если файл уже переименован, мы получаем новое имя
  3. открыть файл по имени
  4. файл карты и получил File2MappedAsFile
  5. вызовите NtAreMappedFilesTheSame(File1MappedAsAnImage, File2MappedAsFile)
  6. если мы получили STATUS_SUCCESS открываем правильный файл - сделано здесь
  7. если мы получили STATUS_NOT_SAME_DEVICE нужно распаковать File2MappedAsFile и перейти к 2
  8. если мы получили другой статус - произошла ошибка

вот полный рабочий пример

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

также вы можете посмотреть эту тему

Другие вопросы по тегам