访问附加到 ELF 二进制文件的数据

发布于 2024-11-01 09:45:40 字数 375 浏览 5 评论 0原文

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

$ cat mydata.zip >> mybinary

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

在过去,我使用了附加数据然后附加数据长度的技巧,这样我所要做的就是打开二进制文件,读取流的最后一个 int,倒带该长度然后开始解压缩,但是由于各种原因,这在这里不起作用(例如,我不能保证当需要 zip 文件时该文件仍然在光盘上)。

如果该解决方案适用于 OS X 和 MinGW,那么全方位的超级额外加倍加分。

I have a static ELF binary which reads data from a zipfile. In order to simplify distribution, I want to append the zipfile to the binary, like so:

$ cat mydata.zip >> mybinary

I know that doing so won't damage mybinary, but I don't know how to access the contents of mydata.zip having done so. Is it possible? If so, how?

In the past, I've used the trick of appending the data then appending the length of the data, so that all I have to do is open the binary, read the last int of the stream, rewind that length then start unzipping, but that won't work here for various reasons (for instance, I can't guarantee that the file will still be on disc when the zipfile comes to be needed).

Super-extra-doubleplus-points all round if the solution works across OS X and MinGW.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱殇璃 2024-11-08 09:45:41

如果您连接 ELF 文件和 zip 文件,则生成的文件两者 (AFAIU) 都是有效的 ELF 文件和有效的 zip 文件。

演示:

$ 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 可以做到这一点:

#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\n", filename_inzip);    
  return 0;
}

给出:

$ ./unzipme2
foo.txt

If you concatenate an ELF file and a zip file, the resulting file is both (AFAIU) a valid ELF file and a valid zip file.

Demo:

$ 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

Many libraries (zlib, zzip) (erronously?) do not recognize such a file as a valid zip file but libminizip can do it:

#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\n", filename_inzip);    
  return 0;
}

Gives:

$ ./unzipme2
foo.txt
梦言归人 2024-11-08 09:45:40

假设在应用程序执行开始时您可以访问该文件,那么打开该文件的句柄应该可以防止操作系统删除磁盘上的文件,直到对该文件的最后一个引用被关闭。这将允许您在文件中查找您想要的内容,使用该文件句柄而无需担心。

创建全局变量:

int app_fd;

大多数过程都是相同的,在主例程中,只需发出:

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

在执行开始时。当执行过程中需要访问 zip 文件时,只需使用文件描述符,而不是文件名。

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

要完成将 zip 文件映射到内存中,您需要遵循不同的策略。您需要将 .zip 嵌入到二进制文件的 ELF(linux)/COFF(Windows)/Mach-O(Mac OS X) 部分,该部分具有设置的属性,以便保证映射到应用程序中(这需要应用程序中有很多前期工作,处理过程中有很多后期工作)。这并不简单,可能需要相当多的编码才能使其适合每个平台。

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

On the assumption at the start of the execution of the application you have access to the file, then opening a handle to it should prevent the operating system from obliterating the file on-disk until the last reference to the file has been closed. This would allow you to seek through the file to you heart's content, using that file handle without worry.

Create a global variable:

int app_fd;

The process for most of these is the same, in the main routine, simply issue:

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

at the start of execution. When it comes to the point in the execution that you need to access the zip file, then simply use the file descriptor, rather than the filename.

At run-time, if you don't have some form of handle to the original contents of the application, then you will probably not be able to access the content of the zip file. This is due to the loader only mapping in the sections of the file that are expected. The content at the end of the binary would be considered garbage and not mapped in.

To accomplish the mapping of the zip file into memory, you would need to follow a different tack. You would need to embed the .zip into an ELF(linux)/COFF(Windows)/Mach-O(Mac OS X) section of the binary that has properties set such that it is guaranteed to be mapped into the application (this requires a lot of pre-work in the app, and a lot more post-work in the processing). It's not trivial, and probably involves quite a bit of coding to get it right for each of the platforms.

As an aside, it is not trivial to delete an application from a windows system while that application is running (I think you can move it if it resides on NTFS though).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文