我所知道的是,您正在寻找您试图操纵的软件中某些变量的地址。一旦找到它,你就会尝试找到"基指针"因为无论过程在哪里,你仍然可以访问这些变量。我的意思是当重新启动过程时,变量会有不同的地址,但你仍然知道它们在哪里。
现在我不明白为什么这可能?
让我说我在C ++中这样做:
int *x = (int*)malloc(sizeOf(int));
不是那么有活力吗?并且不应该放在"随机"当时免费的地址? 基本上我要问的是当代码执行时x是真的在哪里?
编辑:我的意思是像健康这样的变量通常存储在像game.exe + 0000caff这样的地址中,然后你总能在那里找到它们。
答案 0 :(得分:4)
x
是一个包含整数地址的变量。
malloc
在堆上分配内存,但x
仍位于堆栈上(如果在函数中声明它)。
然而,你的程序有不同的内存部分,一个用于全局变量和常量,一个用于源代码,一些用于资源,一个用于动态内容(堆)和其他一些。
让我们假设您的x
位于全局变量的部分并指向堆。然后x
有一个静态地址。
此地址可以在汇编程序指令(如mov eax , [0x123]
)的源代码部分中找到。
该汇编指令还具有与指令所在模块相关的地址。这些模块可以动态加载(例如通过LoadLibrary),但模块基址到指令的偏移量是固定的。
获取x
指向的数据:
base = getModuleBaseAddress("modulename")
addressOfX = base + offset
valueOfX = *addressOfX
大多数对象不在堆栈中,可以通过模块地址引用,固定偏移量可以跳转到使用对象指针的指令,还有一些偏移可以使对象变化。
要在内存中查找对象,您还可以使用模式扫描来扫描内存。
答案 1 :(得分:4)
以下是从32位x86架构的角度来看,其他架构可能会以不同的方式做事。另外,我假设单行代码在一个函数中。
首先要记住声明int* x
的含义,松散地它可以被解读为“变量x将包含整数的地址”
变量x
是一个本地(或自动变量),这意味着它的位置是在编译时确定的,并且在激活该函数时(很可能在堆栈上)分配它的存储空间。
x
中包含的值是动态地址(可能位于堆上)。
所以你拥有的是变量x
和函数激活框架中某个位置之间的绑定。删除可怜的ASCII艺术,类似于
这(地址是名义上的,还要记住堆栈增长):
~ ~
| |
+------------+
0x04000 | |<---- ebp
+------------+
| |
+------------+
0x03ff8 | x |
+------------+
| |
+------------+
0x03ff0 | |<---- esp
+------------+
现在我们必须注册值 ebp (扩展基指针)和 esp (扩展堆栈指针),它们定义了激活帧的底部和顶部。堆。因此,在汇编中,如果要查找存储x
的位置,则基于与基指针的偏移量。
另一种思考方式是变量名x
是内存位置epb-8
的别名。因为,这就是编译器布局内存的方式,x
的存储位置始终位于与基指针相同的偏移处。
现在,在多次运行期间,基指针的值可能会改变,只要我能找到激活帧的基本指针,我就可以找到x
的存储位置并摆弄它。
答案 2 :(得分:0)
“并且不应该将x放在当时免费的”随机“地址中?”
如果在操作系统中运行进程,实际使用的指针值可能会解决特定storage duration categories可用的虚拟地址空间类型,这些虚拟地址空间与具有RAM和ROM的具体区域的进程相关联地址,以及由操作系统管理的地址。
因此,如果顺序具有相同的动态存储持续时间de / /分配,则每次运行程序时这些地址都可能会收到相同的(虚拟)地址。
这个级别没有随机。