在C++中访问直接内存地址并获取值

17

我想知道是否能够使用C/C++访问内存的直接块并获取值。例如:

int i = 15;
int *p = &i;
cout << &i;
如果我在这里获取打印值,那么将会给我变量i的地址,它包含值15。对于这个示例,我只会说它打印出0x0ff9c1。如果我有一个单独的程序声明了一个指针,就像这样...
int *p = 0x0ff9c1;
cout << *p;
能否打印出另一应用程序放在内存块0x0ff9c1中的那个15?我知道我的指针声明与内存地址有误,但我不确定该如何改正。我尝试使用 memcopy ,但始终无法使其工作。我知道这是可能的,因为我有一个名为Cheat Engine的程序,可以修改游戏内存地址值以获得不公平的优势。通过Cheat Engine,我已成功将打印的内存位置和获取值(15)放置到了该处。我的目标是使用C ++实现这一点。 如果这太令人困惑了,基本上我想访问另一个应用程序使用其内存地址存储的变量并打印出该值。我正在使用Windows 7 x64和MinGW编译器。谢谢! PS:我会发布Cheat Engine的图片以更好地说明。 enter image description here

8
这样的实验值得点赞。 - Nawaz
3
读一本关于虚拟内存的书。另外需要注意的是,Linux和一些新版本的Windows采用堆栈随机化技术,因此程序执行时局部变量的地址会有所不同。 - unkulunkulu
是的,通过实验我发现了这一点。我正在考虑通过执行参数将地址导出到第二个程序中。我会研究虚拟内存,感谢您的提示。 - llk
你能解决这个问题吗?我也在尝试做类似的事情。我使用类似 Cheat Engine 的系统内存读取器成功地从另一个程序中读取了一个内存位置。我想要从我创建的程序中读取这个内存位置,并且我也想知道如何预测它在未来应用程序重新启动时的位置。 - Jeff82
在Linux中有一个名为ptrace()的系统调用可以实现这一功能,但不确定Windows是否也有类似的功能。 - aditya
5个回答

5
这两个进程拥有独立的地址空间。除非明确共享内存,否则一个进程不能访问另一个进程的内存。

1
在Windows下,可以使用ReadProcessMemory()WriteProcessMemory() - trojanfoe
2
感谢您的点赞。像调试器这样的工具会连接到进程,因此可以访问该进程的所有内存。@paul - 我认为有人应该阅读一下页面、虚拟内存、分段和进程地址空间的相关知识。 - Ed Heal
1
@Shadowalker,每个体面的操作系统都有调试器支持来简化这些任务(请注意,调试器不仅可以访问外部内存,还可以在另一个进程的上下文中设置断点甚至查看寄存器)。 - unkulunkulu
1
@EdHeal:在问题被提出几秒钟后回答时,你的膝反应式回答否定了OP的经验,即这个程序存在(我不会因为认为它是由于糟糕的原因而被投票支持而打负分)。对于你的评论给予+1,但在我看来,在你的回答中修复它会更好。无论哪种情况,都欢迎你。 - HostileFork says dont trust SE
2
@Paul: 放松点。我只是说我认为这不是一个好答案,虽然答案正在通过许多评论被传播出去,但我们会根据答案本身的内容进行投票。如果它被重构以便答案能够给出完整的故事,我就会点赞,但在此之前,我对一个“不可能”的答案文本被接受感到相当沮丧。我的习惯是不会对零回答进行点踩的,这是一个单独的问题,更多的是因为我觉得对于那些试图提供帮助但表现不好的人来说,我看不出网络声望惩罚的意义。 - HostileFork says dont trust SE
显示剩余11条评论

5

在C++中,你无法以跨平台的方式完成此操作。虽然我没有特别使用过这个“作弊引擎”,但它几乎肯定是使用与调试器相同的特殊API。代码将特定于Windows,并且您需要在运行进程上具有一定的特权级别。

(例如,如果您正在使用Visual Studio并以调试模式执行程序,则Visual Studio可以查看和修改该程序中的值。)

我已经很久没有编写调试器了,所以我不知道开始Debug API的好地方在哪里,但您可以在网络上搜索类似这篇文章的内容:

http://www.woodmann.com/fravia/iceman1.htm


注意:正如其他人指出的那样,调试器API并不是特定平台可以提供用于探测其他进程的唯一特权API。(事实上,一些嵌入式系统根本不需要单独的地址空间,仍然允许您编译C和C++源代码,因此您的“天真”示例实际上可能在这些非常基本的平台上起作用。)我只是猜测Debug API是它所使用的——而不是SpyXX使用的钩子或其他东西。 - HostileFork says dont trust SE

3
如果你想改变另一个进程使用的内存,一种方法是将你的代码注入到另一个进程中。从那时起,你可以像操作自己的内存一样对其他程序的内存进行任何操作。
搜索远程线程创建hooking。这里有很多关于它的问题(以及这里)。

1
通常情况下,一个程序无法修改另一个程序的内存。系统会尽最大努力确保这一点。如果没有这样做,那么没有一个程序是安全的。在我所使用的所有Unix变体中,特别是在所有专有操作系统中,这一点尤其正确。
请注意,这些规则都不适用于内核...
还有一种编程范式叫做共享内存,但你必须明确设置它。
简短回答:通常情况下你不能这样做。我相信你提到了Windows。我对Windows一无所知,所以你的结果可能会有所不同。

答案的重点有些错误,严格来说并不完全正确,因为操作系统提供了进程修改彼此内存的方法。答案应该着重于记忆空间是不同的这一事实,因此具有相等值的指针在不同进程中引用不同的物理内存位置。 - unkulunkulu
我认为没有必要进行完整的虚拟内存课程,尽管可能需要。 - Lee-Man

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接