代码之家  ›  专栏  ›  技术社区  ›  AK87

从windows 10上的64位进程获取32位进程上的ModuleFileNameEx

  •  4
  • AK87  · 技术社区  · 8 年前

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

    该代码在Windows 7中按预期工作,部分结果如下:

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

    在Windows 10中,上述代码返回完整路径,但使用System32而不是SysWOW64。例如,

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

    深入查找原因,我注意到GetModuleFileNameEx读取远程进程PEB和LDR\u TABLE\u条目,并且从Windows 10开始,LDR\u TABLE\u条目包含System32的完整路径,而不是SysWOW64-也适用于32位应用程序。

    我想知道是否还有其他简单的方法来提取完整的syswow64路径。

    1 回复  |  直到 8 年前
        1
  •  3
  •   RbMm    8 年前

    为了从文件nt路径获取有效的win32文件路径-最简单的方法-添加 L"\\\\?\\globalroot" \\?\globalroot CreateFileW \??\ 目录和 globalroot 符号链接是否在 \??\ 让as跳转到nt命名空间的根。

    例如- \Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll \\?\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll 是的有效win32路径 创建文件W -此api转换众所周知的前缀 \\?\ \??\ \??\globalroot\Device\HarddiskVolume9\Windows\SysWOW64\ntdll.dll 到内核。在分析此名称后处理符号链接时 全局根 \设备\硬盘卷9\Windows\SysWOW64\ntdll。dll

    因此,如果我们需要在中使用有效的win32路径 创建文件W -只需将此前缀附加到nt路径。但是,一些shell32 api不接受此表单路径。在用户界面上看起来也不太好。如果我们想要得到DOS驱动器号形式的路径(这是有效win32路径的子集),我们可以使用 IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH MOUNTDEV_NAME mountmgr。h )输出缓冲区为 MOUNTMGR_VOLUME_PATHS MOUNTDEV_名称 \设备\硬盘卷9\Windows\SysWOW64\ntdll。dll

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

    GetFileInformationByHandleEx 具有 FileNameInfo -我们在输出中获得了文件系统路径。有了这个,我们可以使用 wcsstr 用于单独的设备路径。此外,如果我们打开文件句柄,我们可以在调用中使用它 GetFinalPathNameByHandleW VOLUME_NAME_DOS IOCTL\u MOUNTMGR\u QUERY\u DOS\u VOLUME\u路径 . + 打开/关闭装载管理器。

    但通常nt文件路径从 \Device\HarddiskVolumeX

    因此,首先我们需要open mount manager:

    #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