我有两个流程,A
和B
A正在加载DLL,其代码读取一些内存位置,而B尝试使用ReadProcessMemory
读取A内存中的相同内存位置。
我得到相同的值,直到某些时候我没有,这是非常令人费解的。我错过了什么,但我不知道是什么。我希望你能帮我找到它。
(在两个进程代码中,IMPORT_TABLE_OFFSET
为1
,processBaseAdress
是进程内存中A
的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的代码:
(hHandle
是A
)
#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才会一样。
答案 0 :(得分:0)
错误(感觉)是下一行:
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
- 本地副本中的地址 - 在远程进程中没有任何意义。并且DataDirectory
是IMAGE_NT_HEADERS
的一部分 - 在您阅读之后 - 您不需要单独阅读DataDirectory
- 您已在ntHeader
还需要了解IMAGE_NT_HEADERS
- 这是宏,根据您的代码比特扩展为IMAGE_NT_HEADERS32
或IMAGE_NT_HEADERS64
。但是当你读到另一张图片时 - 它可以有另一种图像。因此,您始终需要检查Magic
成员IMAGE_OPTIONAL_HEADER
以确定 - 使用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);
}
}
}