是否可以自我修改文件级代码?

时间:2014-02-06 10:29:31

标签: c

我尝试编写一个C代码,以便执行其二进制a.out更改a.out文件本身。

例如,我想写foo.c,如:

% gcc foo.c
% a.out
Hello world!
% a.out
Bus error
% 

3 个答案:

答案 0 :(得分:2)

这是不可能以可移植的方式进行的(可执行文件的结构在每个系统上都会有所不同 - ELF vs .exe,amb64 vs ARM),但你可以将libgcc或libclang这样的东西与输出文件捆绑在一起这应该允许代码生成+编译。

查看clang可执行文件here的代码,它可以为您提供一些好主意。

你可以做什么(伪代码):

string myNewCode("#include <stdio.h>\nint main(int argc, char *argv[]){ printf(\"Bus error\\n\");return 1; }");
var compiler = new Compiler();
var temp_file = new tempFile();
compiler->compile(myNewCode, temp_file);
move_file(temp_file, argv[0]);

(二级编辑:考虑到这一点,这是完全可行的,可以用libclang移植)

答案 1 :(得分:1)

不便携,没有。

在许多版本的Windows中,您无法修改正在运行的程序的可执行文件。这通常非常令人讨厌,即使做的事情比你提议的更“理智”。

在Linux中我觉得没问题,只需打开argv[0]并修改它。当然,如果您的进程是从路径加载的,那么migth在找到正确的文件时会出现问题,但是应该有一些/sys条目或者可以引导您(向下)到绝对路径的东西。

答案 2 :(得分:0)

我继续尝试了。以下示例适用于Linux,根据您的规范(注意,这是hacky,非动态代码!)

#include <stdio.h>

const char str1[]="Hello world!"; //12 chars + \0
//        echo -n "Bus error"| wc -c  # 9 + \0 -- need to pad by 3

int main(int argc, char const * const argv[]){
  puts(str1);
  system("sed 's/Hello world!/Bus error\\x0\\x0\\x0/' a.out -i~\n"
         "rm a.out~\n");
  return 0;
}

你不能写到那个文件(除非你想把应用程序带到嘈杂的崩溃)。使用-i~不会写入,而是将原始文件移动到a.out~,同时创建名为a.out的修改后的副本。 (无论名称如何更改,操作系统都会继续读取相同的文件。删除/取消链接也没关系 - 如果Linux程序在取消链接之前打开它们(不关闭),它们可以继续访问未链接的文件。