【问题标题】:How to detect at runtime whether symbols are stripped?如何在运行时检测符号是否被剥离?
【发布时间】:2011-07-05 21:36:52
【问题描述】:

在我的 C++ 程序中,如何在运行时以编程方式检测符号是否已通过 Linux 上的“strip”gnu 开发工具剥离?

我想要一个函数定义,如果剥离返回 true,否则返回 false。

在“main()”上使用 dlsym() 是否可以可靠地检测到这一点?

【问题讨论】:

  • 我不清楚为什么您需要知道可执行文件是否已被剥离。但是,无论您在运行时使用什么来处理可执行文件,都应该能够告诉您是否已剥离。
  • 好奇为什么要在运行时检测到这个?
  • @Martin York 在执行应用程序时触发警报消息,以减少无意中将非剥离版本提供给客户的机会。
  • 将这部分作为构建过程的一部分会更合适,这样您就不能将超出范围的应用程序发送给您的客户。
  • @Martin York 这是构建过程的一部分,但有时客户会出于调试或检查修复的临时目的而获得特殊构建。此类构建不适合长期生产使用,我们希望它们以编程方式自我识别。

标签: c++ symbols introspection strip dlsym


【解决方案1】:

我知道file 命令可以区分,因此您可以查看其源代码以了解其使用的机制。

【讨论】:

  • 剥离的ELF 将缺少.symtab 条目。 file 命令遍历所有 ELF 节头,直到找到符号表节。如果找不到,则认为二进制文件被剥离
【解决方案2】:

dlsym 查看 动态 符号,这些符号不会被 strip 触及。静态符号表包含在运行时未加载的节中,因此不会出现在段表中。

一个很好的启发式方法是观察 ELF 标头中是否存在节表,该节表通常映射到您的进程内存,尽管动态链接器接口故意使其难以找出位置。在具有 dl_iterate_phdrs 函数(这是标准的扩展)的典型系统上,您可能能够遍历 PHDRS 并在 vaddr 处检查每个是否存在 ELF 幻数,但那不是方式、形状或形式可移植。

【讨论】:

    【解决方案3】:

    您可以使用 popen() 在目标应用程序上执行nm,然后使用parse the output 来判断它是否被剥离。

    nm: /bin/ls: no symbols
    

    【讨论】:

      【解决方案4】:

      来自another answer留下的评论:

      剥离的ELF 将缺少.symtab 条目。 file 命令遍历所有 ELF 节头,直到找到符号表节。如果找不到,则认为二进制文件已被剥离。


      libelf 库允许程序操作 ELF 目标文件、存档文件和存档成员。 elf(3E) 手册页提供了与使用该库相关的文档。以下代码提供了一个示例,通过查找符号表部分 (.symtab) 的存在来确定可执行文件是否被剥离。

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <fcntl.h>
      
      /* Include for ELF processing */
      #include <libelf.h>
      #include <gelf.h>
      
      int main(int argc, char ** argv)
      {
          int fd;
          const char *file = argv[0];
      
          Elf *elf;       /* ELF pointer for libelf */
          Elf_Scn *scn;   /* section descriptor pointer */
          GElf_Shdr shdr; /* section header */
      
          /* Open ELF file to obtain file descriptor */
          if((fd = open(file, O_RDONLY)) < 0)
          {
              fprintf(stderr, "Error opening file %s\n", file);
              exit(EXIT_FAILURE);
          }
      
          /* Protect program from using an older library */
          if(elf_version(EV_CURRENT) == EV_NONE)
          {
              fprintf(stderr, "WARNING - ELF Library is out of date!\n");
              exit(EXIT_FAILURE);
          }
      
          /* Initialize elf pointer for examining contents of file */
          elf = elf_begin(fd, ELF_C_READ, NULL);
      
          /* Initialize section descriptor pointer so that elf_nextscn()
           * returns a pointer to the section descriptor at index 1. */
          scn = NULL;
      
          /* Iterate through ELF sections */
          while((scn = elf_nextscn(elf, scn)) != NULL)
          {
              /* Retrieve section header */
              gelf_getshdr(scn, &shdr);
      
              /* If a section header holding a symbol table (.symtab)
               * is found, this ELF file has not been stripped. */
              if(shdr.sh_type == SHT_SYMTAB)
              {
                  printf("NOT STRIPPED\n");
                  break;
              }
          }
      
          elf_end(elf);
          close(fd);
          exit(EXIT_SUCCESS);
      }
      

      【讨论】:

        【解决方案5】:

        readelf --sections binary_path | grep debug_info

        一般来说,二进制文件是否被剥离并不是一件容易的事,因为剥离文件有不同的方法。基本上剥离删除了一些与符号和调试相关的部分。但是,如果您将“debug_info”替换为“debug”,您可以看到在 Ubuntu 发行版的标准二进制文件中仍然存在一些与调试相关的部分。

        【讨论】:

          猜你喜欢
          • 2012-11-22
          • 2012-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多