使用它在C++中的内存中的起始地址编辑字符串

haz*_*aze 5 c++ string edit inject memory-address

我真的希望以前没有问过这个,但我的谷歌搜索没有提出任何内容,所以我想我会问.

我正在处理一个小脚本,我将DLL注入游戏并编辑特定字符串,以便在特定事件发生时显示.我已经找到了这个字符串驻留在内存中的位置,并编写了一个基本的sigscanning函数,以便在运行时找到它.我现在的问题是,给定起始地址,我如何/可以用我自己的特定字符串替换此字符串?

例如,字符串是"我喜欢煎饼",我想用"煎饼很可怕,华夫饼最好!"来取而代之.怎么会这样做呢?

谢谢!

哦是的,如果重要的话,源代码中的字符串是一个const char.我很确定它没有,但添加该信息并没有伤害!

Mik*_*wan 1

正如您所指出的,引用字符串的汇编指令通常如下所示:

push offset aString
Run Code Online (Sandbox Code Playgroud)

组装和链接后,将其解析为实际地址:

push 0x00ABCDEF
Run Code Online (Sandbox Code Playgroud)

这给你两个选择:

  • 写数据:修改 的内容aString(即 指向的内存0x00ABCDEF
  • 编写代码:修改引用aString

写入数据

当编译涉及标准 C 字符串文字(内存中不可变的字符数组)的源代码时,在运行时该字符串通常会与所有其他只读数据一起映射到某个只读页。这些数据通常是连续打包的,以减少程序的内存占用。这是您尝试编写更大的字符串时遇到的问题。您将覆盖下一条数据,并且对此覆盖数据的任何引用现在都将指向大字符串的中间。

通过更改数据写入更长的字符串并非易事,因为为了不丢失原始功能行为,您必须向前移动字符串后面的所有数据。之后,您必须更新对移位数据的所有引用(其中一些可以使用指针算术动态计算)。正如我所说,这个过程并不简单 - 您正在尝试在没有完整(如果有)符号信息的情况下在重定位方面重现链接器的任务。

编写代码

简单的方法是将新字符串写入任意位置。这可能是未使用的,但已在进程中保留内存(通常称为“代码洞穴”),或者它可能是您在注入 DLL 时映射的字符串文字。或者,您可以在注入后在运行时动态分配它。

下一步是找到所有引用aString并将其替换为引用新字符串。

奖金方法:)

由于您正在研究这个级别的逆向工程,因此您可能已经遇到过绕行/拦截/检测的概念。此处可以应用类似的方法来拦截所有引用并在运行时重定向它们。与上面概述的“编写代码”方法相比,这会对性能造成更大的影响,但会保证所有访问都被捕获并重定向。

访问时的硬件断点设置为字符串指向的数据。当断点被触发时,一些寄存器将保存字符串的地址。在汇编中,这可能看起来像这样:

mov esi, 0x00ABCDEF
...
Run Code Online (Sandbox Code Playgroud)

如果访问第一个字符,代码可能会执行以下操作:

mov al, byte ptr ds:[esi]
Run Code Online (Sandbox Code Playgroud)

当断点被命中时,您可以设置线程上下文(SetThreadContext在 Windows 上)来修改 的值esi以指向新字符串。