我尝试编写一个C代码,以便执行其二进制a.out
更改a.out
文件本身。
例如,我想写foo.c,如:
% gcc foo.c
% a.out
Hello world!
% a.out
Bus error
%
答案 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程序在取消链接之前打开它们(不关闭),它们可以继续访问未链接的文件。