【问题标题】:Is it possible to modify a C program which is running?是否可以修改正在运行的 C 程序?
【发布时间】:2018-05-27 03:44:23
【问题描述】:

我想知道是否可以在运行时修改一段 C 程序(或其他二进制文件)?

我写了这个小 C 程序:

#include <stdio.h>
#include <stdint.h>

static uint32_t gcui32_val_A = 0xAABBCCDD;

int main(int argc, char *argv[])  {

    uint32_t ui32_val_B = 0;
    uint32_t ui32_cpt = 0;

    printf("\n\n Program SHOW\n\n");

    while(1) {

        if(gcui32_val_A != ui32_val_B) {
            printf("Value[%d] of A : %x\n",ui32_cpt,gcui32_val_A);
            ui32_val_B = gcui32_val_A;
            ui32_cpt++;
        }
    }

    return 0;
}

使用十六进制编辑器,我可以找到“0xAABBCCDD”并在程序停止时对其进行修改。当我重新启动程序时,修改工作。酷!

我想在程序运行时这样做可以吗?

这是一个简单的例子,可以理解现象并尝试一下,但我真正的项目更大。

  • 我有一个名为 Dangerous Dave 的旧 DOS 游戏。
  • 我可以通过简单地编辑二进制文件来修改图块(感谢http://www.shikadi.net/moddingwiki/Dangerous_Dave
  • 我开发了一个小编辑器,它做得很好并且玩得很开心。
  • 我用DOSBOX启动DOS游戏,好用!

我想在游戏运行时动态执行此操作。有可能吗?

PS : 我在 Debian 64bit 下工作

问候

【问题讨论】:

  • 加载时,代码在大多数系统中驻留在只读段中,但您可以通过附加调试器来更改数据,如果您有符号则可以动态更改数据
  • 是的,原则上是可以的。调试器可以附加到进程,如果您暂停它,甚至允许您修改进程内存(包括可执行页面)。然而,这并非易事。
  • @IporSircer.:似乎上下文错误。但在这里你也基本上改变了模式......从内核到用户。总体而言,答案与 Op 希望在不更改模式(内核与用户模式)的情况下运行用户级程序的想法相矛盾。我将删除答案,因为这显然不是作者的意图。
  • 您可以在您链接的教程中看到调试。这是我想强调的想法。但同样,如果您使用调试器,您基本上是在更改正在调试的代码。而且实际上没有人考虑更改在内核模式下运行的代码(这是不可能的)。 C 语言和任何编译器都不支持它。但是是的,我想我错过了调试器。
  • 你的DOS游戏是开源的吗?您是否考虑过使用一些开源游戏或游戏引擎?你的总体目标是玩那个游戏,还是做一个更好的游戏?你的编程技能是什么?

标签: c linux binary system


【解决方案1】:

我想知道是否可以在运行时修改一段 C 程序(或其他二进制文件)?

不在标准(和便携式)C11 中。阅读n1570 规范进行检查。请注意,在实践中,大多数时候,运行的不是 C source 程序(由几个 translation units 组成),而是一些 compilerlinkerexecutable 结果。


但是,在 Linux(例如 Debian/Sid/x86-64)上,您可以使用以下一些技巧(通常使用函数指针):

我建议玩一下/proc/(请参阅proc(5))并尝试至少在某些终端中运行以下命令

 cat /proc/self/maps
 cat /proc/$$/maps
 ls /proc/$$/fd/

(并阅读足够的内容以了解其输出)以进一步了解process“是”什么。

所以覆盖你的text segment(如果你真的需要这样做)是可能的,但可能比你想象的更棘手!

(您介意工作几周或几个月来改善一些旧游戏体验吗?)


还可以阅读有关homoiconic 编程语言(尝试使用SBCL 的Common Lisp)、有关dynamic software updating、有关persistence、有关application checkpointing 和有关operating systems 的信息(我推荐:Operating Systems: Three Easy Pieces 和@ 987654356@wiki)


我在 Debian 64 位下工作

我想你有编程技能并且知道 C。那么你应该阅读 ALP 或一些较新的 Linux 编程书籍(当然还要查看 intro(2) & syscalls(2) & intro(3) 和其他手册页等。 ..)

顺便说一句,在您的特定情况下,“操作系统”可能是 DOSBOX(充当某些虚拟机)。您可以在 DOSBOX(或其他命令或进程)上使用strace(1),或者研究它的源代码。


您在问题中提到了游戏。如果您想编写一些代码,请考虑像 SDLSFMLQtGTK+ 等库。

【讨论】:

  • 感谢您提供的所有链接,我是软件嵌入式系统工程师,我对 DSP 和裸机(无操作系统)应用程序了解得越多。我知道有关 linux 系统的基础知识,但很乐意学习 ;)
【解决方案2】:

是的,您可以在 C 中运行时修改一段代码。您必须有指向程序内存区域的指针,并编译了您想要更改的代码段。自然地,这被认为是一种危险的做法,有很多限制,并且有很多错误的可能性。不过,这是在过去记忆很宝贵的时候的做法。

【讨论】:

  • 您能否更具体一些或举个例子,因为我所做的所有尝试都以“分段错误”结束 ^^
  • 在实践中,请参阅我的答案的第三个项目符号。您可能需要使用mprotectmmap,并且您实际上不应该尝试更改您的代码段。在细节上,它可能非常棘手且非常脆弱。所以我不建议这样做。
  • 我找到了一个聪明而详尽的描述:shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program
猜你喜欢
  • 2022-11-05
  • 2011-07-16
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多