如何在C+;中找到ELF二进制文件所需的动态库+;? 如何获取C++中的ELF二进制文件所需的所有动态库的列表?p>

如何在C+;中找到ELF二进制文件所需的动态库+;? 如何获取C++中的ELF二进制文件所需的所有动态库的列表?p>,c++,linux,binary,elf,decompiling,C++,Linux,Binary,Elf,Decompiling,一旦我成功地从二进制文件中提取了信息(文件名?),我就可以通过搜索路径找到实际的文件,但是我无法找到任何关于从ELF二进制文件中提取未混合信息的信息 想法?您可以调用“readelf-d”程序并解析输出: readelf -d /usr/bin/readelf | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libz.so.1] 0x0000000000000001 (NEEDED)

一旦我成功地从二进制文件中提取了信息(文件名?),我就可以通过搜索
路径
找到实际的文件,但是我无法找到任何关于从ELF二进制文件中提取未混合信息的信息

想法?

您可以调用“readelf-d”程序并解析输出:

readelf -d /usr/bin/readelf | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

所需共享对象的列表存储在所谓的可执行文件列表中。获取必要信息的粗略算法如下:

  • 解析,检查文件是否为动态可执行文件(
    ET_EXEC
    ET_DYN
  • 获取程序头的偏移量和计数(
    e_phoff/e_phnum/e_phentsize
    ),检查它们是否为非零且有效
  • 解析,查找
    PT\u动态
    one。还要记住
    PT\u加载
    段的虚拟地址->文件偏移量映射
  • 找到后,解析。查找所需的
    DT_
    DT_STRTAB
    条目
  • DT_NEEDED
    条目的
    d_val
    字段是
    DT_STRTAB
    字符串表的偏移量,它将是所需库的SONAME。请注意,由于
    DT_STRTAB
    条目是运行时地址,而不是字符串表的偏移量,因此需要使用步骤3中存储的信息将其映射回文件偏移量。

    您可以使用此操作。请注意,
    libelf
    有一个C API

    从他们的教程中,看一看第4.2节(或)中关于如何获取程序头表的示例。找到
    dtu DYNAMIC
    部分,并从字符串表中读取依赖项,如第5.4节(或)中的示例

    --编辑--

    实际上我有机会写代码。以下是我所做的:

    #include <assert.h>
    #include <fcntl.h>
    #include <gelf.h>
    #include <stdio.h>
    #include <unistd.h>
    
    void print_dt_needed(const char *elf_path) {
      assert(elf_version(EV_CURRENT) != EV_NONE);
    
      int fd = open(elf_path, O_RDWR, 0);
      assert(fd >= 0);
    
      Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
      assert(elf != NULL);
      assert(elf_kind(elf) == ELF_K_ELF);
    
      Elf_Scn *scn = NULL;
      while ((scn = elf_nextscn(elf, scn)) != NULL) {
        GElf_Shdr shdr = {};
        assert(gelf_getshdr(scn, &shdr) == &shdr);
    
        if (shdr.sh_type == SHT_DYNAMIC) {
          Elf_Data *data = NULL;
          data = elf_getdata(scn, data);
          assert(data != NULL);
    
          size_t sh_entsize = gelf_fsize(elf, ELF_T_DYN, 1, EV_CURRENT);
    
          for (size_t i = 0; i < shdr.sh_size / sh_entsize; i++) {
            GElf_Dyn dyn = {};
            assert(gelf_getdyn(data, i, &dyn) == &dyn);
    
            if (dyn.d_tag == DT_NEEDED) {
              printf("DT_NEEDED detected: %s\n",
                     elf_strptr(elf, shdr.sh_link, dyn.d_un.d_val));
            }
          }
        }
      }
      assert(elf_end(elf) == 0);
      assert(close(fd) == 0);
    }
    
    int main(int argc, char const *argv[]) {
      print_dt_needed(argv[1]);
      return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    需要无效打印(常量字符*elf路径){
    断言(elf_版本(EV_当前)!=EV_无);
    int fd=打开(elf_路径,O_RDWR,0);
    断言(fd>=0);
    Elf*Elf=Elf_begin(fd,Elf_C_READ,NULL);
    断言(elf!=NULL);
    断言(elf_kind(elf)=elf_K_elf);
    Elf_Scn*Scn=NULL;
    while((scn=elf_nextscn(elf,scn))!=NULL){
    GElf_Shdr Shdr={};
    断言(gelf_getshdr(scn和shdr)=&shdr);
    如果(shdr.sh_类型==SHT_动态){
    Elf_数据*数据=NULL;
    数据=elf_getdata(scn,数据);
    断言(数据!=NULL);
    大小\u t sh\u entsize=gelf\u fsize(elf,elf\u t\u DYN,1,EV\u电流);
    对于(size\u t i=0;i
    如果您使用的是基于RHEL的发行版(rpm是软件包管理的基础),那么您可以尝试解决二进制文件对*.so文件以及提供这些文件的软件包的依赖关系。为什么要问这个问题?您是否关心间接依赖关系(即可执行文件
    foo
    动态链接
    libbar.so
    ,它本身是动态链接
    libgee.so
    ,因此
    ldd foo
    将说明
    libbar.so
    libgee.so
    )?我这样问是因为我使用的是静态分析工具,我需要从目标二进制文件以及它所依赖的任何动态库中提取CFG。直接使用
    readelf-d
    ,间接使用
    ldd
    :可能重复谢谢,我认为这是一个相当常见的问题,从二进制文件访问信息,该二进制文件是。是否有任何库、开源项目或类似项目可以提供此功能而无需我自己实现和维护?大多数人在程序中不需要它,因此他们依赖于
    readelf
    objdump
    ldd
    来编写脚本。对于编程访问,这里有
    libelf
    ,但它没有为这个特定任务提供现成的API—您仍然需要手动解析动态部分。