c - 当无法执行管道时如何在 Linux 上创建自解压可执行文件

标签 c linux pipe exec

我一直在研究一个小技巧来减小可执行文件的文件大小。我知道存在可以正确压缩可执行文件的工具,但这更多的是为了我自己的享受,而不是任何严肃的事情。

我的想法是用 gzip 压缩可执行文件,然后将其作为数组嵌入到另一个称为启动器的 C 程序中。当启动器运行时,它会设置一个管道系统,如下所示:

parent launcher -> fork 1 of launcher -> fork 2 of launcher

fork 1 将自身转换为 gzip,因此它会解压缩父级提供给它的任何内容,并将解压后的版本吐出到 fork 2。

这就是黑客开始发挥作用的地方。Fork 2 尝试执行文件“/dev/fd/n”,其中 n 是从 fork 1 到 fork 2 的管道的文件号。本质上,这意味着 fork 2将尝试执行 gzip 输出的任何二进制文件。

但是,这不起作用(令人惊讶。)我尝试跟踪我的示例实现,并且在“/dev/fd/n”上执行 execv 的行返回 -1 EACCES(权限被拒绝)。但是,如果我打开终端并运行 ls -l/dev/fd/,我会得到类似以下内容的信息:

lrwx------ 1 blackle users 64 Nov 10 05:14 0 -> /dev/pts/0
lrwx------ 1 blackle users 64 Nov 10 05:14 1 -> /dev/pts/0
lrwx------ 1 blackle users 64 Nov 10 05:14 2 -> /dev/pts/0
lr-x------ 1 blackle users 64 Nov 10 05:14 3 -> /proc/17138/fd

所有这些都具有用户(我)的权限+x。这意味着它应该是可执行的,不是吗?或者这只是一个非常奇怪的内核边缘情况,它没有获得权限,但实际上它无法执行,因为它不是一个真正的文件。

近 7 年后更新

随着 Linux“memfd”的出现,现在可以在 Linux 上创建不接触文件系统的自解压可执行文件。请参阅:https://gitlab.com/PoroCYon/vondehi

最佳答案

只有支持mmap的文件才可以执行。不幸的是,由于管道的顺序性质和有限的缓冲区大小,管道不能以这种方式映射(它可能需要再次重新读取早期的代码,这些代码在读取一次后就会消失)。

您会更幸运,而不是使用管道在 ramfs 中创建文件,将其映射到父级内存空间的某个区域,将未压缩的代码复制到 mmap 中,最后让子级执行ramfs 中的文件,最后取消父级中 ramfs 中文件的链接,以便在子级退出时自动释放该文件。

希望对你有帮助,如有不清楚的地方请评论。

关于c - 当无法执行管道时如何在 Linux 上创建自解压可执行文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26841487/

相关文章:

linux - 当输入通过管道或重定向到它时,sort/uniq 命令的内部工作

java - 通过 Java 写入 unix 管道的问题

c - 我该如何修复这个 strtok() 调用

java - 哪个 'cacerts' 应该用于更新 Java 安全文件?

linux - 无法打开设备 : Too many open files Error

php - 在 Laravel 5.6 中找不到类 'SimpleXMLElement'

python - 打开从 os.listdir() 找到的文件并对文件执行任务

c - 给定shell脚本可能的C代码实现思路(与ffmpeg相关)

c - main(int argc, char *argv[]) 损害了我的程序

c - 文字数组或复合的使用