C程序可以修改其可执行文件吗?

Joe*_*oel 22 c metaprogramming self-modifying

我手上有点太多时间,开始想知道我是否可以写一个自修改程序.为此,我在C中编写了一个"Hello World",然后使用十六进制编辑器在已编译的可执行文件中查找"Hello World"字符串的位置.是否可以修改此程序以打开自身并覆盖"Hello World"字符串?

char* str = "Hello World\n";

int main(int argc, char* argv) {

  printf(str);

  FILE * file = fopen(argv, "r+");

  fseek(file, 0x1000, SEEK_SET);
  fputs("Goodbyewrld\n", file);      
  fclose(file);    

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,我假设有一些东西阻止它打开自己,因为我可以将它分成两个单独的程序(一个"Hello World"和一些修改它),它工作正常.

编辑:我的理解是,当程序运行时,它被完全加载到ram中.因此,对于所有意图和目的,硬盘驱动器上的可执行文件是一个副本.为什么修改自己会有问题?

有解决方法吗?

谢谢

Gre*_*ill 32

在Windows上,运行程序时,使用Windows中的内存映射文件功能将整个*.exe文件映射到内存.这意味着文件不一定全部被加载,而是在访问文件的页面时按需加载.

以这种方式映射文件时,另一个应用程序(包括其自身)无法写入同一文件以在其运行时更改它.(另外,在Windows上,运行的可执行文件也不能重命名,但它可以在Linux和其他具有基于inode的文件系统的Unix系统上).

可以更改映射到内存中的位,但是如果执行此操作,则操作系统使用"写时复制"语义来执行此操作,这意味着底层文件不会在磁盘上更改,而是页面的副本( s)在内存中进行修改.在被允许这样做之前,你通常必须在有问题的存储器上摆弄保护位(例如VirtualProtect).

曾经有一段时间,在非常有限的内存环境中使用自修改代码的低级汇编程序常见.但是,没有人这样做了,因为我们不是在相同的受约束环境中运行,而现代处理器有很长的流水线,如果你开始从它们下面改变代码就会非常沮丧.


小智 6

如果您使用的是Windows,则可以执行以下操作:

分步示例:

  1. 通过保护调用VirtualProtect()要修改的代码页PAGE_WRITECOPY.
  2. 修改代码页.
  3. VirtualProtect()通过PAGE_EXECUTE保护调用修改后的代码页.
  4. 打电话FlushInstructionCache().

有关更多信息,请参阅如何修改内存中的可执行代码(已存档:2010年8月)