【发布时间】:2019-01-03 20:53:31
【问题描述】:
我似乎对 Endianess 搞得一团糟。我的机器是配备 Ryzen 3 处理器的 64 位机器。报告为小端。
我正在用 C 编写一个小程序,它遍历进程虚拟内存并解析 MSDOS 标头并检查标头签名中的 MZ。
取自我的代码:
int pid = 10964;
DWORD_PTR addr = 0x7FF7BD730000;
MEMORY_BASIC_INFORMATION64 mbi;
IMAGE_NT_HEADERS header;
HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (pHandle == NULL)
{
printf("Error getting handle for process %i. Failed with error: %i", pid, GetLastError());
return -1;
}
/*
* Retrieve information on virtual address space
*/
BOOL vqeResult = VirtualQueryEx(pHandle, addr, &mbi, sizeof(MEMORY_BASIC_INFORMATION64));
if (!vqeResult)
{
printf("Error querying virtual memory: %i", GetLastError());
return -1;
}
PrintMemoryBasicInformation64(&mbi);
/*
* Read the DOS header
*/
BOOL rpmResult = ReadProcessMemory(pHandle, (LPCVOID)mbi.BaseAddress, (LPVOID)&header, sizeof(header), 0);
if (!rpmResult) {
printf("Error reading memory address: %i. Failed with error: %i", mbi.BaseAddress, GetLastError());
return -1;
}
一切正常,除非我尝试打印签名:
printf("Signature: %x", header.Signature);
它给出了一个不正确的十六进制值,基本上是MZ:
Signature: 0x785a4d
由于我的系统是小端,这是有道理的,但我该如何正确打印呢?
我附上了一张图片来显示存储在headers.Signature 中的值:
【问题讨论】:
-
据我所知,7887437(以 10 为底)是 785a4d(十六进制)。你期待 0xd4a587 吗?
-
@Bob__ 是的,即
xZM。应该是MZ。文档说签名是 4 个字节,其中 2 个是空的 docs.microsoft.com/en-us/windows/desktop/api/winnt/… ...我在某个地方感到困惑。 -
字节顺序关注数字如何存储在内存中,但 C 本身正在处理数字本身,因此无论字节顺序如何,打印、移位等都会以相同的方式发生。现在,如果您将二进制数据直接读入整数类型(大于
char),那么字节序应该匹配,但是由于您是在小端机器上读取小端数据,所以我看不到字节序的相关性. -
@Arkku 如果不是字节序问题并且标题不正确,我们深表歉意。我想我会在发布我的问题之前删除并找出我正在处理的问题。我还带着我的训练轮。关于我可能会出错的地方的任何指示?
-
@Bob__ 抱歉错过了编辑。是的,这就是我所期望的价值。