【问题标题】:Access Violation while calculating a pointer计算指针时访问冲突
【发布时间】:2017-01-08 16:25:40
【问题描述】:

我很担心这个问题真的非常简单,但即使你我开始掌握指针的概念,来自有经验的用户的提示缩短了我需要花在理解所有内容上的时间。我有一个简单的例子,稍后我不会详细说明它应该做什么,因为我认为我的错误是非常基本的。我得到:

抛出异常:读取访问冲突。 _First 是 0x815110。

执行此代码时:

#include <Windows.h>
#include <iostream>
#include "Header.h"

#pragma comment(linker, "/SECTION:.data,RWE")

using std::cout;
using std::endl;

int main() {

    DWORD dwProcessID = 0;

    cout << "Looking for game process..." << endl;

    while (dwProcessID == 0) {
        dwProcessID = GetProcessID(L"PathOfExile.exe");
        Sleep(100);
    }

    std::cout << "Game Client found" << std::endl;

    printf("dwProcessID = %p\n", dwProcessID);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
    MODULEENTRY32 module;
    module.dwSize = sizeof(MODULEENTRY32);
    Module32First(snapshot, &module);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);

    HANDLE hToken = NULL;
    if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
        printf("Failed to open access token\n");

    if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
        printf("Failed to set debug privilege\n");


    printf("PoE base address = %p\n", module.modBaseAddr);

    BYTE jmp[] = "\xBA\x00\x00\x80\x3F\x89\x10\x89\x16\xE9\x00\x00\x00\x00";

    BYTE *dwMaphack = (BYTE*)(module.modBaseAddr + 0x4D5110);
    cout << dwMaphack << endl;

    *(DWORD*)&jmp[10] = (DWORD)(dwMaphack - jmp) - 6;

    DWORD dwOldProt;

    VirtualProtectEx(hProcess, (LPVOID)dwMaphack, 8, PAGE_EXECUTE_READWRITE, &dwOldProt);

    // tbc

    while (1) {
    }

    return 0;
}

开放进程方法和其他基本内容在标头中,它们工作正常,但我不明白为什么当我将字节指针 BYTE *dwMaphack 更改为 DWORD *dwMaphack 时,不再出现访问冲突错误?

我正在尝试将我的代码基于不再有效的某人的过时代码,所以我只知道部分执行这些操作的原因,我知道它在编程方面应该做什么,但我不知道还不知道游戏中的效果。无论如何,我认为就我遇到的错误而言,这并不重要。提前感谢您的回答!

【问题讨论】:

  • @RbMm,另一个挑战? :-D
  • 指针运算是基于目标的大小。
  • 计算中指针类型错误会出现访问冲突错误吗?
  • 设置断点并查看调试器中的值,然后尝试查看它们指向的内存。
  • modBaseAddr 地址为 0x00340000,但调试器中的值为“无法读取内存”。那就是 BYTE dwMaphack = (BYTE)(module.modBaseAddr + 0x4D5110);发生此行异常后。

标签: c++ windows memory


【解决方案1】:

BYTEunsigned char 的别名。

std::cout 有一个重载的operator&lt;&lt;,它接受unsigned char* 指针作为输入并将其打印为字符串(如 Harry Johnston 所述,https://stackoverflow.com/a/41538200/7376565)。因此,当它尝试访问它无权访问的内存时,它会崩溃。

std::cout 没有operator&lt;&lt; 重载DWORD*(又名unsigned long*),但它确实有一个void*,因此任何非字符指针都将只打印指针本身的值.将dwMaphack改为DWORD*时,operator&lt;&lt;不会尝试访问dwMaphack指向的内存,所以不会发生访问冲突。

【讨论】:

  • 谢谢伙计们,这有助于我整理脑海中的东西!
  • 我完全不建议改成DWORD *。刚刚描述了使用DWORD *时代码不崩溃的原因。如果需要指针值,我更喜欢将指针转换为 DWORD_PTRULONG_PTR(指针大小的整数)等类型。
  • 啊,我忽略了这部分问题。我的错。
  • 伙计们,还有一件事,如果我只需要 dwMaphack 指针的地址,使用 (DWORD*)dwMaphack 是否正确?
  • 在 C++ 中变量的地址是&amp;Var。在什么情况下你需要地址?
【解决方案2】:

这是你的问题:

cout << dwMaphack << endl;

这是试图打印dwMaphack 指向的值,而不是指针的值。由于指针仅在远程进程中有效,因此尝试取消引用它会导致访问冲突。

这行得通:

cout << (DWORD_PTR)dwMaphack << endl;

【讨论】:

  • 谢谢,确实如此!
猜你喜欢
  • 1970-01-01
  • 2013-11-02
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多