首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从32位WOW进程中激活64位进程中的模块

如何从32位WOW进程中激活64位进程中的模块
EN

Stack Overflow用户
提问于 2010-09-27 06:24:49
回答 3查看 17K关注 0票数 19

我需要在Windows中的32位WOW进程中检索64位进程的所有模块,如所述,EnumProcessModules将失败:

如果该函数是从运行在WOW64上的32位应用程序调用的,它只能枚举32位进程的模块。如果进程是64位进程,则此函数将失败,最后一个错误代码是ERROR_PARTIAL_COPY (299)。

如EnumProcessModulesEx和CreateToolhelp32Snapshot。

你对如何实现这个目标有什么想法吗?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-27 06:27:25

如果不使用无文档的API,就无法做到这一点。通常,由于地址空间的差异,从32位进程读取64位进程的内存将无法工作。

EnumProcessModulesExLIST_MODULES_32BITLIST_MODULES_64BIT过滤器标志,它可以这样说:

此功能主要用于64位应用程序.如果在WOW64下运行的32位应用程序调用该函数,则忽略dwFilterFlag选项,该函数提供与EnumProcessModules函数相同的结果。

您可以通过将您的程序转换为64位,使用separate 64位COM服务器(特别是使用DLL代理,或者有一个单独的与您通信的进程)来做到这一点。或者,根据进程相对于目标进程的启动时间,您可以使用WMI获取模块加载事件。查看Win32_ModuleLoadTrace事件。

过程资源管理器,一个32位的exe,可以向您展示32位和64位进程的模块,但是它确实是一个烟雾和镜像:32位的exe包含64位版本的自身,它被写到磁盘上并在64位机器上执行。

票数 17
EN

Stack Overflow用户

发布于 2017-06-12 14:37:11

您的请求的解决方案与从x64进程读取x86进程内存任务有一些交叉点。主要是,我们应该了解NtWow64QueryInformationProcess64NtWow64ReadVirtualMemory64函数,它们存在于x86 ntdll.dll中,专门用于从x86 one中获取有关x64进程的信息。

我们还应该了解OS结构之间的一些依赖关系。

PROCESS_BASIC_INFORMATION包含PEB的地址。PEB代表进程环境块。它包含PEB_LDR_DATA结构的地址。它反过来包含LIST_ENTRY链中第一个LIST_ENTRY结构的地址。LDR_DATA_TABLE_ENTRY包含指向以下LDR_DATA_TABLE_ENTRY的链接。

在WinDbg中检查此信息的示例:

代码语言:javascript
运行
复制
0:000> !peb
PEB at 000007fffffdb000
...

0:000> dt ntdll!_peb 000007fffffdb000
...
+0x018 Ldr              : 0x00000000`76fbd640 _PEB_LDR_DATA
...

0:000> dt ntdll!_PEB_LDR_DATA 76fbd640
...
+0x010 InLoadOrderModuleList : _LIST_ENTRY [ 0x00000000`00415bb0 - 0x00000000`070eb9c0 ]
...

0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY 00415bb0
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000000`00415ca0 - 0x00000000`76fbd650 ]
...
+0x030 DllBase          : 0x00000001`3f4d0000 Void
...
+0x058 BaseDllName      : _UNICODE_STRING "procexp64.exe"
...

0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY 00415ca0
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000000`00416020 - 0x00000000`00415bb0 ]
...
+0x030 DllBase          : 0x00000000`76e90000 Void
...
+0x058 BaseDllName      : _UNICODE_STRING "ntdll.dll"
...

在代码中要采取的步骤如下:

  1. 通过通常对OpenProcess函数的调用获得进程句柄。
  2. 通过调用PROCESS_BASIC_INFORMATION来读取NtWow64QueryInformationProcess64结构。
  3. 获取存在于PEB结构中的PROCESS_BASIC_INFORMATION地址。
  4. 通过调用PEB来读取NtWow64ReadVirtualMemory64结构。
  5. 获取PEB_LDR_DATA结构的地址。
  6. 读取PEB_LDR_DATA结构并获取第一个LDR_DATA_TABLE_ENTRY元素的地址。
  7. 继续读取LDR_DATA_TABLE_ENTRY元素的内存,而下一个元素的地址不等于第一个元素的地址。

在步骤7中,我们还读取了UNICODE_STRING (驻留在LDR_DATA_TABLE_ENTRY中)的缓冲区以获得当前的模块名。

代码如下所示。它由两个文件组成,main.cppos_structs.hpp

main.cpp

代码语言:javascript
运行
复制
#include "os_structs.hpp"

#include <algorithm>
#include <codecvt>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

#ifndef WIN32
#   error "This application must be built as an x86 executable"
#endif

#define GET_FUNC_ADDR(name) _##name name = (_##name)::GetProcAddress(::GetModuleHandleA("ntdll.dll"), #name)

#define IS_TRUE(clause, msg) if (!(clause)) { throw std::runtime_error(msg); }

namespace
{

struct close_on_exit
{
    close_on_exit(HANDLE ptr)
        : ptr_(ptr)
    { };

    ~close_on_exit()
    {
        if (ptr_)
        {
            ::CloseHandle(ptr_);
            ptr_ = nullptr;
        }
    }

private:
    HANDLE ptr_;
};

// Names of modules 
std::string convert_unicode_to_utf8(std::vector<uint8_t> &raw_bytes)
{
    std::vector<uint16_t> unicode(raw_bytes.size() >> 1, 0);
    memcpy(unicode.data(), raw_bytes.data(), raw_bytes.size());

    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;

    const std::wstring wide_string(unicode.begin(), unicode.end());
    const std::string utf8_string = converter.to_bytes(wide_string);

    return utf8_string;
}

void *get_handle(uint32_t id)
{
    HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);

    std::cout << "Opening target process...";

    IS_TRUE(NULL != handle, "OpenProcess failed");

    std::cout << " ok" << std::endl;

    return handle;
}

void check_if_process_is_x64(HANDLE handle)
{
    BOOL is_wow64_process = TRUE;
    IS_TRUE(::IsWow64Process(handle, &is_wow64_process), "IsWow64Process failed");
    IS_TRUE(FALSE == is_wow64_process, "Target process is not x64 one");
}

std::vector<uint8_t> read_mem(HANDLE handle, uint64_t address, uint32_t length)
{
    IS_TRUE(handle, "No process handle obtained");

    std::vector<uint8_t> data(length, 0);

    GET_FUNC_ADDR(NtWow64ReadVirtualMemory64);

    NTSTATUS status = NtWow64ReadVirtualMemory64(handle, address, data.data(), data.size(), FALSE);

    IS_TRUE(NT_SUCCESS(status), "NtWow64ReadVirtualMemory64 failed");

    return data;
}

void read_pbi(HANDLE handle, sys::PROCESS_BASIC_INFORMATION64 &pbi)
{
    IS_TRUE(handle, "No process handle obtained");

    GET_FUNC_ADDR(NtWow64QueryInformationProcess64);

    NTSTATUS status = NtWow64QueryInformationProcess64(handle, sys::ProcessBasicInformation, &pbi, sizeof(pbi), NULL);

    IS_TRUE(NT_SUCCESS(status), "NtQueryInformationProcess failed");
}

std::vector<uint8_t> read_peb_data(HANDLE handle)
{
    sys::PROCESS_BASIC_INFORMATION64 pbi = { 0 };
    read_pbi(handle, pbi);

    return read_mem(handle, pbi.PebBaseAddress, sizeof(sys::PEB64));
}

bool get_modules_load_order_via_peb(HANDLE handle)
{
    std::cout << "Getting module load order...\n" << std::endl;

    std::vector<uint8_t> read_peb = read_peb_data(handle);
    sys::PEB64 *peb = (sys::PEB64 *)read_peb.data();

    // ------------------------------------------------------------------------
    // Read memory from pointer to loader data structures.
    // ------------------------------------------------------------------------
    std::vector<uint8_t> read_peb_ldr_data = read_mem(handle, (uintptr_t)peb->LoaderData, sizeof(sys::PEB_LDR_DATA64));
    sys::PEB_LDR_DATA64 *peb_ldr_data = (sys::PEB_LDR_DATA64 *)read_peb_ldr_data.data();
    sys::PEB_LDR_DATA64 *loader_data = (sys::PEB_LDR_DATA64 *)peb->LoaderData;

    const uintptr_t addr_of_ptr_to_first_ldr_module = (uintptr_t)loader_data
        + ((uintptr_t)&loader_data->InLoadOrderModuleList - (uintptr_t)&loader_data->Length);

    ULONGLONG address = peb_ldr_data->InLoadOrderModuleList.Flink;

    uint32_t counter = 1;

    // ------------------------------------------------------------------------
    // Traversing loader data structures.
    // ------------------------------------------------------------------------
    do
    {
        std::vector<uint8_t> read_ldr_table_entry = read_mem(handle, address, sizeof(sys::LDR_DATA_TABLE_ENTRY64));

        sys::LDR_DATA_TABLE_ENTRY64 *ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data();

        std::vector<uint8_t> unicode_name = read_mem(handle, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.MaximumLength);
        std::string name = convert_unicode_to_utf8(unicode_name);

        std::cout << "Module: " << name << std::endl;
        std::cout << "  Image base: 0x" << std::hex << ldr_table_entry->BaseAddress << std::endl;

        ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data();
        address = (uintptr_t)ldr_table_entry->InLoadOrderModuleList.Flink;
    } while (addr_of_ptr_to_first_ldr_module != address);

    std::cout << "\nEnumeration finished" << std::endl;

    return true;
}

}  // namespace

int main()
{
    try
    {
        HANDLE handle = get_handle(16944);
        close_on_exit auto_close_handle(handle);

        check_if_process_is_x64(handle);
        get_modules_load_order_via_peb(handle);
    }
    catch (const std::runtime_error &e)
    {
        std::cerr << "\n----------------------------------------------------\n";
        std::cerr << "Exception occurred: " << e.what();
        std::cerr << "\n----------------------------------------------------\n";
    }

    return 0;
}

os_structs.hpp

代码语言:javascript
运行
复制
#pragma once

#include <windows.h>

#define NT_SUCCESS(x) ((x) >= 0)

// Namespace is present Not to collide with "winbase.h"
// definition of PROCESS_INFORMATION_CLASS and others.
namespace sys
{

typedef enum _PROCESS_INFORMATION_CLASS {
    ProcessBasicInformation,
    ProcessQuotaLimits,
    ProcessIoCounters,
    ProcessVmCounters,
    ProcessTimes,
    ProcessBasePriority,
    ProcessRaisePriority,
    ProcessDebugPort,
    ProcessExceptionPort,
    ProcessAccessToken,
    ProcessLdtInformation,
    ProcessLdtSize,
    ProcessDefaultHardErrorMode,
    ProcessIoPortHandlers,
    ProcessPooledUsageAndLimits,
    ProcessWorkingSetWatch,
    ProcessUserModeIOPL,
    ProcessEnableAlignmentFaultFixup,
    ProcessPriorityClass,
    ProcessWx86Information,
    ProcessHandleCount,
    ProcessAffinityMask,
    ProcessPriorityBoost,
    MaxProcessInfoClass
} PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS;

// ------------------------------------------------------------------------
// Structs.
// ------------------------------------------------------------------------

typedef struct _PROCESS_BASIC_INFORMATION64 {
    ULONGLONG Reserved1;
    ULONGLONG PebBaseAddress;
    ULONGLONG Reserved2[2];
    ULONGLONG UniqueProcessId;
    ULONGLONG Reserved3;
} PROCESS_BASIC_INFORMATION64;

typedef struct _PEB_LDR_DATA64 {
    ULONG Length;
    BOOLEAN Initialized;
    ULONGLONG SsHandle;
    LIST_ENTRY64 InLoadOrderModuleList;
    LIST_ENTRY64 InMemoryOrderModuleList;
    LIST_ENTRY64 InInitializationOrderModuleList;
} PEB_LDR_DATA64, *PPEB_LDR_DATA64;

// Structure is cut down to ProcessHeap.
typedef struct _PEB64 {
    BOOLEAN InheritedAddressSpace;
    BOOLEAN ReadImageFileExecOptions;
    BOOLEAN BeingDebugged;
    BOOLEAN Spare;
    ULONGLONG Mutant;
    ULONGLONG ImageBaseAddress;
    ULONGLONG LoaderData;
    ULONGLONG ProcessParameters;
    ULONGLONG SubSystemData;
    ULONGLONG ProcessHeap;
} PEB64;

typedef struct _UNICODE_STRING64 {
    USHORT Length;
    USHORT MaximumLength;
    ULONGLONG Buffer;
} UNICODE_STRING64;

typedef struct _LDR_DATA_TABLE_ENTRY64 {
    LIST_ENTRY64 InLoadOrderModuleList;
    LIST_ENTRY64 InMemoryOrderModuleList;
    LIST_ENTRY64 InInitializationOrderModuleList;
    ULONGLONG BaseAddress;
    ULONGLONG EntryPoint;
    DWORD64 SizeOfImage;
    UNICODE_STRING64 FullDllName;
    UNICODE_STRING64 BaseDllName;
    ULONG Flags;
    SHORT LoadCount;
    SHORT TlsIndex;
    LIST_ENTRY64 HashTableEntry;
    ULONGLONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;

}  // namespace sys

// ------------------------------------------------------------------------
// Function prototypes.
// ------------------------------------------------------------------------

typedef NTSTATUS(NTAPI *_NtWow64QueryInformationProcess64)(
    IN HANDLE ProcessHandle,
    ULONG ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength OPTIONAL);

typedef NTSTATUS(NTAPI *_NtWow64ReadVirtualMemory64)(
    IN HANDLE ProcessHandle,
    IN DWORD64 BaseAddress,
    OUT PVOID Buffer,
    IN ULONG64 Size,
    OUT PDWORD64 NumberOfBytesRead);

如果您对初始结构定义感兴趣--我想出的最好方法是下载WinDbg的符号,然后在这个调试器中查看结构的布局。你可以在上面的文章中看到样品。

票数 5
EN

Stack Overflow用户

发布于 2016-02-04 10:30:56

使用Windows管理工具(WMI)。示例(Delphi):

代码语言:javascript
运行
复制
function GetProcessCount(const aFileName: string): Integer;
var
  lValue: LongWord;
  lWMIService: OleVariant;
  lWMIItems: OleVariant;
  lWMIItem: OleVariant;
  lWMIEnum: IEnumVariant;
begin
  Result := -1;
  lWMIService := GetWMIObject('winmgmts:\\.\root\CIMV2'); { Do not localize. }
  if (TVarData(lWMIService).VType = varDispatch) and (TVarData(lWMIService).VDispatch <> nil) then
  begin
    Result := 0;
    lWMIItems := lWMIService.ExecQuery(Format('SELECT * FROM Win32_Process WHERE Name=''%s''', [ExtractFileName(aFileName)])); { Do not localize. }
    lWMIEnum := IUnknown(lWMIItems._NewEnum) as IEnumVariant;
    while lWMIEnum.Next(1, lWMIItem, lValue) = 0 do
    begin
      Inc(Result);
    end;
  end;
end;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3801517

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档