关于linux:访问附加到ELF二进制文件的数据

Accessing data appended to an ELF binary

我有一个静态ELF二进制文件,可从zip文件读取数据。为了简化分发,我想将zipfile附加到二进制文件中,如下所示:

1
$ cat mydata.zip >> mybinary

我知道这样做不会损坏mybinary,但是这样做后我不知道如何访问mydata.zip的内容。是否可以?如果是这样,怎么办?

过去,我曾使用过技巧:先添加数据,然后再添加数据的长度,这样我要做的就是打开二进制文件,读取流的最后一个int,倒回该长度然后开始解压缩,但是由于各种原因在这里无法正常工作(例如,当需要使用zipfile时,我不能保证文件仍在光盘上)。

如果该解决方案可在OS X和MinGW上正常运行,则可以全面获得超级加倍点。


假设在应用程序开始执行时您有权访问文件,然后打开该文件的句柄应防止操作系统在磁盘上最后一个引用关闭之前清除磁盘上的文件。 。这样一来,您就可以使用该文件句柄在文件中查找您内心深处的内容。

创建一个全局变量:

1
int app_fd;

在主例程中,执行以下大多数操作的过程是相同的,只需发出:

1
app_fd = open(argv[0], O_RDONLY);

在执行开始时。当您需要执行zip文件时,只需使用文件描述符而不是文件名即可。

在运行时,如果您对应用程序的原始内容没有某种形式的处理,那么您可能将无法访问zip文件的内容。这是由于加载程序仅在预期的文件部分中进行了映射。二进制末尾的内容将被视为垃圾内容,不会被映射到其中。

要完成zip文件到内存的映射,您需要遵循不同的方针。您需要将.zip嵌入到二进制文件的ELF(linux)/ COFF(Windows)/ Mach-O(Mac OS X)节中,该节的属性已设置为可以确保将其映射到应用程序中(这要求应用中的大量前工作,以及处理中的大量后工作)。这并非微不足道,并且可能涉及大量编码才能使其在每种平台上都正确无误。

顺便说一句,在该应用程序运行时从Windows系统中删除该应用程序并不是一件容易的事(我认为如果它驻留在NTFS上,您可以将其移动)。


如果串联ELF文件和zip文件,则生成的文件既(AFAIU)是有效的ELF文件又是有效的zip文件。

演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ gcc hello.c -o hello
$ ./hello
Hello
$ (cat hello ; test.zip) > hello2
$ chmod u+x hello2
$ ./hello2
Hello
$ unzip ./hello2
Archive:  ./hello2
warning [./hello2]:  6704 extra bytes at beginning or within zipfile
(attempting to process anyway)
  Length      Date    Time    Name
---------  ---------- -----   ----
   119458  1999-11-24 13:08   hello.txt

许多库(zlib,zzip)(错误吗?)无法将此类文件识别为有效的zip文件,但libminizip可以做到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <errno.h>
#include <minizip/unzip.h>

int main(int argc, char** argv)
{
  unzFile uf = unzOpen(argv[0]);
  unzGoToFirstFile(uf);
  char filename_inzip[256] = {0};
  unz_file_info64 file_info = {0};
  const char *string_method = NULL;
  unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
  printf("%s\
", filename_inzip);    
  return 0;
}

赠品:

1
2
$ ./unzipme2
foo.txt