GetModuleFileNameEx for a 32-bit process from a 64-bit process on windows 10

I am trying to list 32-bit process module names from a 64-bit application using the following code:

if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL))
{
    for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
    {
       TCHAR szModName[MAX_PATH] = { 0 };

        if (GetModuleFileNameEx(hProcess, hMods[i], szModName,
            sizeof(szModName) / sizeof(TCHAR)))
        {
            printf("module name is: %S", szModName);
        }
    }
}

The code works as expected in Windows 7, as part of the results:

...

C:\Windows\**SysWOW64**\ntdll.dll

...

On Windows 10, the above code returns the full path, but with System32 instead of SysWOW64. eg,

...

C:\Windows\**System32**\ntdll.dll

...

Looking deeper into this, I notice that GetModuleFileNameEx reads the remote PEB process and LDR_TABLE_ENTRY, and starting with Windows 10 LDR_TABLE_ENTRY contains the full path with System32, and not SysWOW64 - also for 32-bit applications.

I also tried using GetMappedFileName, but not directly and efficiently translating the path from dos path (\ device \ harddiskvolume) to the standard (c: \) path.

I wonder if there is another easy way to extract the full syswow64 path.

+4
1

win32 nt-path - - L"\\\\?\\globalroot" (\\?\globalroot). , CreateFileW \??\ globalroot ​​\??\, nt.

- \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll - nt. \\?\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll - win32 CreateFileW - api \\?\ nt \??\ \??\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll . - globalroot, - \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll - nt.

, win32 CreateFileW - nt. shell32 api . . DOS ( win32) - IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, . ioctl MOUNTDEV_NAME ( mountmgr.h), - MOUNTMGR_VOLUME_PATHS. MOUNTDEV_NAME , . , nt . , \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll:

  • \Device\HarddiskVolume9 -
  • \Windows\SysWOW64\ntdll.dll -

GetFileInformationByHandleEx FileNameInfo - . wcsstr . , - GetFinalPathNameByHandleW VOLUME_NAME_DOS. api , - , IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH. + / .

nt \Device\HarddiskVolumeX. - .

:

#include <mountmgr.h>
HANDLE hMountManager = CreateFile(MOUNTMGR_DOS_DEVICE_NAME, 
    0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

:

void dumpModules(HANDLE hMountManager, HANDLE hProcess)
{
    ULONG cb = 0, cbNeeded = 16;

    volatile static UCHAR guz;
    PVOID stack = alloca(guz);
    HMODULE *hMods, hmod;

__continue:

    // cumulative allocate memory in stack, not need free it
    cb = RtlPointerToOffset(hMods = (HMODULE*)alloca(cbNeeded - cb), stack);

    if (EnumProcessModulesEx(hProcess, hMods, cb, &cbNeeded, LIST_MODULES_32BIT))
    {
        if (cb < cbNeeded)
        {
            goto __continue;
        }

        if (cbNeeded /= sizeof(HMODULE))
        {
            //i use hard coded size buffers, for reduce code and show main idea
#define FILE_NAME_INFO_buffer_size  FIELD_OFFSET(FILE_NAME_INFO, FileName[MAX_PATH])
#define MOUNTDEV_NAME_buffer_size  FIELD_OFFSET(MOUNTDEV_NAME, Name[MAX_PATH])
#define MOUNTMGR_VOLUME_PATHS_buffer_size  FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz[64])

            // + space for 0 at the end
            PFILE_NAME_INFO pfni = (PFILE_NAME_INFO)alloca(FILE_NAME_INFO_buffer_size + sizeof(WCHAR));

            PMOUNTMGR_VOLUME_PATHS pmvp = (PMOUNTMGR_VOLUME_PATHS)alloca(MOUNTMGR_VOLUME_PATHS_buffer_size);
            PMOUNTDEV_NAME pmdn = (PMOUNTDEV_NAME)alloca(MOUNTDEV_NAME_buffer_size);

            static WCHAR globalroot[] = L"\\\\.\\globalroot";

            alloca(sizeof(globalroot));
            PWSTR win32Path = pmdn->Name - RTL_NUMBER_OF(globalroot) + 1;

            memcpy(win32Path, globalroot, sizeof(globalroot));
            USHORT NameLength = pmdn->NameLength;

            do 
            {
                hmod = *hMods++;

                if (GetMappedFileNameW(hProcess, hmod, pmdn->Name, MAX_PATH))
                {
                    DbgPrint("%p %S\n",hmod, pmdn->Name);

                    PWSTR c = 0;

                    static const WCHAR HarddiskVolume[] = L"\\Device\\HarddiskVolume";

                    // fast way
                    if (!memcmp(pmdn->Name, HarddiskVolume, sizeof(HarddiskVolume) - sizeof(WCHAR)))
                    {
                        c = wcschr(pmdn->Name + RTL_NUMBER_OF(HarddiskVolume) - 1, '\\');
                    }
                    // else - for demo
                    {
                        pmdn->NameLength = NameLength;

                        HANDLE hFile = CreateFile(win32Path, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

                        if (hFile != INVALID_HANDLE_VALUE)
                        {
                            //++ just for demo
                            WCHAR DosPath[MAX_PATH];
                            if (GetFinalPathNameByHandleW(hFile, DosPath, RTL_NUMBER_OF(DosPath), VOLUME_NAME_DOS))
                            {
                                DbgPrint("%S\n", DosPath);
                            }
                            RtlGetLastNtStatus();
                            //-- just for demo

                            BOOL fOk = GetFileInformationByHandleEx(hFile, FileNameInfo, pfni, FILE_NAME_INFO_buffer_size);

                            CloseHandle(hFile);

                            if (fOk)
                            {
                                // FileName not 0 terminated
                                pfni->FileName[pfni->FileNameLength/sizeof(WCHAR)] = 0;

                                c = wcsstr(pmdn->Name, pfni->FileName);
                            }
                        }

                    }

                    if (c)
                    {
                        pmdn->NameLength = (USHORT)RtlPointerToOffset(pmdn->Name, c);

                        if (DeviceIoControl(hMountManager, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
                            pmdn, MOUNTDEV_NAME_buffer_size, 
                            pmvp, MOUNTMGR_VOLUME_PATHS_buffer_size, &cb, NULL))
                        {
                            DbgPrint("%S%S\n", pmvp->MultiSz, c);
                        }
                    }
                }

            } while (--cbNeeded);
        }
    }
}

:

0000000000170000 \Device\HarddiskVolume9\Windows\SysWOW64\notepad.exe
\\?\C:\Windows\SysWOW64\notepad.exe
C:\Windows\SysWOW64\notepad.exe
0000000077A90000 \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll
\\?\C:\Windows\SysWOW64\ntdll.dll
0000000075460000 \Device\HarddiskVolume9\Windows\SysWOW64\kernel32.dll
\\?\C:\Windows\SysWOW64\kernel32.dll
C:\Windows\SysWOW64\kernel32.dll
0000000074A30000 \Device\HarddiskVolume9\Windows\SysWOW64\KernelBase.dll
\\?\C:\Windows\SysWOW64\KernelBase.dll
C:\Windows\SysWOW64\KernelBase.dll
00000000749B0000 \Device\HarddiskVolume9\Windows\SysWOW64\advapi32.dll
\\?\C:\Windows\SysWOW64\advapi32.dll
+3

Source: https://habr.com/ru/post/1686339/


All Articles