繁体   English   中英

如何让 bash 从标准输入执行 ELF 二进制文件?

[英]How can I make bash execute an ELF binary from stdin?

出于某种晦涩的原因,我编写了一个 bash 脚本,它生成一些源代码,然后编译它,使用

... whatever ... | gcc -x c -o /dev/stdout

现在,我想在编译时执行结果。 我怎样才能做到这一点? 请不要使用文件。

正如 Charles Duffy 所说,要执行一个二进制文件,你必须告诉你的操作系统(它似乎是一个 Unix 变体)加载和执行某些东西——而 Unix 系统只接受文件来直接执行它们。

你可以做的是有一个进程来准备一个包含 ELF 二进制文件的内存区域,fork 并跳转到该区域 - 但即使这也是有问题的,考虑到有 CPU 支持来精确抑制该操作 (R^X)。 基本上,您需要的是一个运行时链接器,而 shell 不(并且:不应该)包含类似的东西。

让我们放弃 Bash 要求(这听起来就像你试图在比我脾气暴躁的更老的应用程序中找到一个明显的漏洞):

通常,需要 ELF(这是一种文件格式)并同时避免文件有点复杂。 GCC 生成机器码。 如果您只想执行已知的机器代码,请将其放入某个缓冲区,构建一个指向它的函数指针并调用它。 就这么简单。 但是,您显然没有执行 ELF 二进制文件或加载共享对象 ( dlopen ) 的过程所具有的所有良好的重定位和动态链接。

如果你想要,我会看看像 LLVM 这样的东西——我知道,事实上,有人在构建“我在运行时编译 C++ 并执行它”,将 LLVM 作为执行实例,将 clang 作为编译器。 最后,你的gcc|something实际上只是 JIT——一种古老的技术:)

如果您的目标是根本不写入文件系统,那么bash或任何其他 UNIX 程序都无法帮助您从管道执行 ELF - execve仅将常规文件的路径作为其filename并且会失败(将errnoEACCES ),如果您向它传递一个特殊文件(设备或命名管道)或目录。

但是,如果您的目标是将可执行文件完全保存在 RAM 中并且不接触硬盘(可能是因为磁盘是只读的),您可以使用tmpfs在您的机器上做一些具有相同效果的事情,它随许多 UNIX-类似系统(并在 Linux 中用于实现信号量)并允许您创建一个完全驻留在 RAM 中的完全权限文件系统:

$ sudo mount -t tmpfs -o size=10M tmpfs /mnt/mytmpfs

然后,您可以将二进制文件写入:

... whatever ... | gcc -x c -o /mnt/mytmpfs/program.out
/mnt/mytmpfs/program.out

bash会为您加载它,就像它在磁盘上一样。

但是请注意,您仍然需要设备上有足够的 RAM 来存储和执行程序 - 尽管由于大多数可执行二进制文件的性质,您无论如何都需要它。

如果您不想将程序留在您的 ramdisk(或普通磁盘,如果可以接受)上供其他人查找,您也可以在开始执行后立即删除该文件:

/mnt/mytmpfs/program.out &
rm /mnt/mytmpfs/program.out

该名称将立即消失,但该进程将在内部保留指向该文件的硬链接,然后在终止时释放该硬链接,从而允许立即从磁盘中删除该文件。 (但是,在程序退出之前,实际上不会释放存储空间,并且程序也无法exec自身)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM