存储十六进制地址,误解DWORD_PTR

时间:2019-01-25 21:57:28

标签: c++ winapi

我正在编写一个程序,将值写入具有特定偏移量的多级指针。我将显示的功能需要返回正确的地址。假设我在函数之外具有变量的所有数据类型。

Dim statusRng As String
statusRng = "C" & rowLocation

Dim StaffRng As String
StaffRng = "D" & rowLocation

Dim DateRng As String
DateRng = "G" & rowLocation

OutputSheet.Range(statusRng).Value = CaseStatusBox.Text
OutputSheet.Range(StaffRng).Value = StaffEntryBox.Text
OutputSheet.Range(DateRng).Value = Date

此代码在调用函数时工作正常,并且正确的地址更改了值(其他地方有写函数),只是事先出现了两个相同的警告。

DWORD FindDmaAddy(int PointerLevel, HANDLE HProcHandle, DWORD Offsets[], DWORD BaseAddress) 
{
    DWORD Pointer = BaseAddress;
    DWORD pTemp = NULL;
    DWORD PointerAddR;
    for (int i = 0; i < PointerLevel; i++) {
        if (i == 0) {
            ReadProcessMemory(HProcHandle, (LPCVOID)Pointer, &pTemp, sizeof(pTemp), NULL); 
            std::cout << pTemp<<std::endl;
        }
        std::cout << "pTemp = " << pTemp << std::endl;
        PointerAddR = pTemp + Offsets[i];
        std::cout << "PointerAddR = " <<PointerAddR << std::endl;
        std::cout << "i = " << i<<std::endl;

        ReadProcessMemory(HProcHandle, (LPCVOID)PointerAddR, &pTemp, sizeof(pTemp), NULL); 
    }
    return PointerAddR;

我认为如果将相关变量更改为DWORD_PTR,此问题将得到解决,因此我将其更改为此。

Warning C4312   'type cast': conversion from 'DWORD' to 'LPCVOID' of greater size   

但是当我使用此代码时,它不起作用。我检查了原始文件和更改后的文件的输出,结果是这样的:

DWORD_PTR FindDmaAddy(int PointerLevel, HANDLE HProcHandle, DWORD_PTR Offsets[], DWORD_PTR BaseAddress) 
{
    DWORD_PTR Pointer = BaseAddress;
    DWORD_PTR pTemp = NULL;
    DWORD_PTR PointerAddR;
    for (int i = 0; i < PointerLevel; i++) {
        if (i == 0) {
            ReadProcessMemory(HProcHandle, (LPCVOID)Pointer, &pTemp, sizeof(pTemp), NULL); 
        }
        std::cout << "pTemp = " << pTemp << std::endl;
        PointerAddR = pTemp + Offsets[i];
        std::cout << "PointerAddR = " <<PointerAddR << std::endl;
        std::cout << "i = " << i<<std::endl;

        ReadProcessMemory(HProcHandle, (LPCVOID)PointerAddR, &pTemp, sizeof(pTemp), NULL); 
    }
return PointerAddR;

为此:

pTemp = 44803720
PointerAddR = 44804620
i = 0
pTemp = 44767240
PointerAddR = 44767260
i = 1
pTemp = 44804056
PointerAddR = 44804056
i = 2

有什么作用? ReadProcessMemory在第一次运行时运行良好,而在第二次运行时,它以这种奇怪的形式存储地址。但是它正在读取完全相同的数据类型并被称为完全相同的方式。

2 个答案:

答案 0 :(得分:0)

在32/64位程序中,sizeof(DWORD) = 4; 在32位sizeof(DWORD_PTR) = 4中,但在64位中,值为8; 从内存中的pTemp(8个字节)读取的第一个值是88A6AB0200000000,因此根据字节顺序规则,该值是0x0000000002ABA688(44803720),而8个字节中的第二个值是0818AB02DAF17A,值= 34605865808631816,如果仅读取前4个字节,则为44767240,与32位结果相同。 64位进程不会在另一个进程中更改32位指针的内存。因此,您应该在此处将进程内存作为目标进程的一部分读取。

答案 1 :(得分:0)

正如Drake所说的那样,指针大小是问题,即4字节对8字节。

自从您发布此信息以来,我们已将FindDMAAddy更改为更简洁,现在看起来像这样

uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
    for (unsigned int i = 0; i < offsets.size(); ++i)
    {
        ReadProcessMemory(hProc, (BYTE*)ptr, &ptr, sizeof(ptr), 0);
        ptr += offsets[i];
    }
    return ptr;
}

很少的代码行,只要您的构建类型与目标进程的体系结构匹配,就无需手动定义长度并且与x64兼容。因此,如果您的目标进程是x86,请为x86编译。使用uintptr_t类似于DWORD_PTR,因为它的定义根据构建类型而变化,以适应指针的大小。

那应该可以解决您的问题。