我所知道的是,您在尝试操作的软件中寻找某些变量的某些地址。一旦找到它,您就尝试找到它的“基指针”,这样无论进程在哪里,您仍然可以访问这些变量。我的意思是,当进程重新启动时,变量将具有不同的地址,但您仍然知道他们在哪里 。
现在我不明白的是为什么这可能?
假设我用 C++ 来做这个:
int *x = (int*)malloc(sizeOf(int));
这不是动态的吗? x 不应该被放置在当时免费的“随机”地址中吗? 基本上我要问的是当执行该代码时 x 到底在哪里?
编辑:我的意思是,像健康这样的变量通常存储在像 game.exe + 0000caff 这样的地址中,然后你总是可以在那里找到它们。
最佳答案
以下是从32位x86架构的角度来看的,其他架构可能会有所不同。另外,我假设单行代码位于函数中。
首先记住声明int* x
是什么意思是,宽松地它可以被理解为“变量 x 将包含一个整数的地址”
变量x
是一个本地(或自动变量),这意味着它的位置在编译时确定,并且在激活函数时分配它的存储空间(最有可能在堆栈上)。
x
中包含的值是一个动态地址(可能位于堆上)。
所以你拥有的是变量 x
之间的绑定(bind)以及函数激活框架中的某个位置。原谅糟糕的 ASCII 艺术,比如
这个(地址是象征性的,还要记住堆栈是向下增长的):
~ ~
| |
+------------+
0x04000 | |<---- ebp
+------------+
| |
+------------+
0x03ff8 | x |
+------------+
| |
+------------+
0x03ff0 | |<---- esp
+------------+
现在我们必须注册值ebp(扩展基指针)和esp(扩展堆栈指针),它们定义了激活帧的底部和顶部堆。所以在汇编中,如果你想定位x
在哪里存储是基于距基指针的偏移量。
另一种思考方式是变量名 x
是内存位置 epb-8
的别名。因为,这就是编译器如何布置 x
的内存存储位置。将始终位于距基指针相同的偏移处。
现在,在多次运行期间,基指针的值可能会发生变化,只要我能找到激活帧的基指针,我就能找到 x
的存储位置。并摆弄它。
关于c++ - 内存黑客/内存分配: why does this work and how?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29759878/