【问题标题】:What is wrong with my use of ReadProcessMemory?我使用 ReadProcessMemory 有什么问题?
【发布时间】:2018-10-13 20:41:48
【问题描述】:

我有两个进程,AB
A 正在使用读取某些内存位置的代码加载 DLL,而 B 尝试使用 ReadProcessMemory 读取 A 内存上的相同内存位置。

我得到相同的值,直到某些时候我没有,这很令人费解。我错过了一些东西,但我不知道是什么。我希望你能帮我找到它。

(在两个进程代码中,IMPORT_TABLE_OFFSET1processBaseAdressA 的MZ 头在进程内存中的起始地址。

A 的 DLL 代码:

printf("processBaseAddress: %p\n", processBaseAddress);
PIMAGE_DOS_HEADER dosHeaderP = processBaseAddress;
printf("ntHeaderP = %p\n", (PBYTE)dosHeaderP + dosHeaderP->e_lfanew);
PIMAGE_NT_HEADERS ntHeader = ((PBYTE)dosHeaderP + dosHeaderP->e_lfanew);
printf("optHeaderP = %p\n", &ntHeader->OptionalHeader);
IMAGE_OPTIONAL_HEADER optionalHeader = (ntHeader->OptionalHeader);
printf("oh.aoep = %p\n", optionalHeader.AddressOfEntryPoint);
printf("oh.cs = %x\n", optionalHeader.CheckSum);
printf("DataDirectory: %p\n", optionalHeader.DataDirectory);
IMAGE_DATA_DIRECTORY dataDirectory = (optionalHeader.DataDirectory[IMPORT_TABLE_OFFSET]);

B 的代码: (hHandleA 的句柄)

#define VERIFY_RPM(CALL_ID, RPM_CALL) {
    if(RPM_CALL==0){
        printf("Error! ReadProcessMemory(): %d. Call id: %d.\n",GetLastError(),CALL_ID);
        exit(1);
    }
}
SIZE_T bytesRead;
printf("processBaseAddress: %p\n", processBaseAddress);
VERIFY_RPM(0, ReadProcessMemory(hProcess, processBaseAddress, &dosHeader, sizeof(dosHeader), &bytesRead));
PIMAGE_NT_HEADERS ntHeaderP = processBaseAddress + dosHeader.e_lfanew;
printf("ntHeaderP = %p\n", ntHeaderP);
VERIFY_RPM(1, ReadProcessMemory(hProcess, ntHeaderP, &ntHeader, sizeof(ntHeader), &bytesRead));
IMAGE_OPTIONAL_HEADER optionalHeader = ntHeader.OptionalHeader;
printf("oh.aoep = %p\n", optionalHeader.AddressOfEntryPoint);
printf("oh.cs = %x\n", optionalHeader.CheckSum);
printf("DataDirectory: %p\n", optionalHeader.DataDirectory);
VERIFY_RPM(2, ReadProcessMemory(hProcess, optionalHeader.DataDirectory + IMPORT_TABLE_OFFSET, &dataDirectory, sizeof(dataDirectory), &bytesRead));

A 的输出:

processBaseAddress: 1C530000
ntHeaderP = 1C5300F0
optHeaderP = 1C530108
oh.aoep = 00001327
oh.cs = d6c7
DataDirectory: 0322F8E8

B的输出:

processBaseAddress: 1C530000
ntHeaderP = 1C5300F0
oh.aoep = 00001327
oh.cs = d6c7
DataDirectory: 001AEE3C
Error! ReadProcessMemory(): 299. Call id: 2.

在 DataDirectory 之前都是一样的。

【问题讨论】:

  • 但是您制作了IMAGE_OPTIONAL_HEADER - IMAGE_OPTIONAL_HEADER optionalHeader = (ntHeader->OptionalHeader);DataDirectory副本 指向此副本。你需要使用IMAGE_OPTIONAL_HEADER* optionalHeader = &ntHeader->OptionalHeader;

标签: c++ windows winapi memory readprocessmemory


【解决方案1】:

错误(按感觉)是下一行:

IMAGE_OPTIONAL_HEADER optionalHeader = (ntHeader->OptionalHeader);

您可以复制 IMAGE_OPTIONAL_HEADER。结果:

optionalHeader.DataDirectory

是此副本中的地址,但不是原始IMAGE_OPTIONAL_HEADER 内部图像中的地址。你需要使用

PIMAGE_OPTIONAL_HEADER poptionalHeader = &ntHeader->OptionalHeader;
PIMAGE_DATA_DIRECTORY dataDirectory = 
    &poptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

和线

ReadProcessMemory(hProcess, optionalHeader.DataDirectory + ..))

当然错误,因为optionalHeader.DataDirectory - 本地副本中的地址 - 在远程进程中没有意义。并且DataDirectoryIMAGE_NT_HEADERS 的一部分 - 在你阅读之后 - 你不需要单独阅读DataDirectory - 你已经在ntHeader 中有这些数据

还需要了解IMAGE_NT_HEADERS - 这是宏,根据您的代码位数扩展为IMAGE_NT_HEADERS32IMAGE_NT_HEADERS64。但是当您阅读另一张图片时-它可能会有另一张图片。所以你总是需要检查IMAGE_OPTIONAL_HEADERMagic 成员以确定 - 使用 32 位或 64 位结构。

读取此遥控器的正确代码如下所示:

union {
    IMAGE_DOS_HEADER dosHeader;
    IMAGE_NT_HEADERS ntHeader;
    IMAGE_NT_HEADERS32 ntHeader32;
    IMAGE_NT_HEADERS64 ntHeader64;
};

if (ReadProcessMemory(hProcess, ImageBase, &dosHeader, sizeof(dosHeader), 0) &&
    dosHeader.e_magic == IMAGE_DOS_SIGNATURE)
{
    if (ReadProcessMemory(hProcess, (PBYTE)ImageBase + dosHeader.e_lfanew, 
        &ntHeader64, sizeof(ntHeader64), 0) &&
        ntHeader.Signature == IMAGE_NT_SIGNATURE)
    {
        PIMAGE_DATA_DIRECTORY dataDirectory = 0;

        switch (ntHeader.OptionalHeader.Magic)
        {
        case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
            dataDirectory = ntHeader32.OptionalHeader.DataDirectory;
            break;
        case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
            dataDirectory = ntHeader64.OptionalHeader.DataDirectory;
            break;
        }

        if (dataDirectory)
        {
            PIMAGE_DATA_DIRECTORY ImpDataDirectory = &dataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
            DbgPrint("[%x, %x]\n", ImpDataDirectory->Size, ImpDataDirectory->VirtualAddress);
        }
    }
}

【讨论】:

  • 我不明白。我希望副本具有相同的价值,无论它在哪里。
  • @Neo - 如果你不理解你的错误,这已经只是你的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多