读取 ELF 部分的内容(以编程方式)

2024-04-10

我正在尝试检索 ELF 二进制文件中附加部分的内容。此时,我使用以下代码来检索每个部分的名称:

#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>

#pragma pack(push,1)
#pragma pack(pop)

#define EI_NIDENT       16

/* 32-bit ELF base types. */
typedef unsigned int Elf32_Addr;
typedef unsigned short Elf32_Half;
typedef unsigned int Elf32_Off;
typedef signed int Elf32_Sword;
typedef unsigned int Elf32_Word;

/* 64-bit ELF base types. */
typedef unsigned long long Elf64_Addr;
typedef unsigned short Elf64_Half;
typedef signed short Elf64_SHalf;
typedef unsigned long long Elf64_Off;
typedef signed int Elf64_Sword;
typedef unsigned int Elf64_Word;
typedef unsigned long long Elf64_Xword;
typedef signed long long Elf64_Sxword;

typedef struct elf32_hdr{
  unsigned char e_ident[EI_NIDENT];
  Elf32_Half    e_type;
  Elf32_Half    e_machine;
  Elf32_Word    e_version;
  Elf32_Addr    e_entry;  /* Entry point */
  Elf32_Off e_phoff;
  Elf32_Off e_shoff;
  Elf32_Word    e_flags;
  Elf32_Half    e_ehsize;
  Elf32_Half    e_phentsize;
  Elf32_Half    e_phnum;
  Elf32_Half    e_shentsize;
  Elf32_Half    e_shnum;
  Elf32_Half    e_shstrndx;
} Elf32_Ehdr;

typedef struct elf32_shdr {
  Elf32_Word    sh_name;
  Elf32_Word    sh_type;
  Elf32_Word    sh_flags;
  Elf32_Addr    sh_addr;
  Elf32_Off sh_offset;
  Elf32_Word    sh_size;
  Elf32_Word    sh_link;
  Elf32_Word    sh_info;
  Elf32_Word    sh_addralign;
  Elf32_Word    sh_entsize;
} Elf32_Shdr;

typedef struct elf64_hdr {
  unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
  Elf64_Half e_type;
  Elf64_Half e_machine;
  Elf64_Word e_version;
  Elf64_Addr e_entry;       /* Entry point virtual address */
  Elf64_Off e_phoff;        /* Program header table file offset */
  Elf64_Off e_shoff;        /* Section header table file offset */
  Elf64_Word e_flags;
  Elf64_Half e_ehsize;
  Elf64_Half e_phentsize;
  Elf64_Half e_phnum;
  Elf64_Half e_shentsize;
  Elf64_Half e_shnum;
  Elf64_Half e_shstrndx;
} Elf64_Ehdr;

typedef struct elf64_shdr {
  Elf64_Word sh_name;       /* Section name, index in string tbl */
  Elf64_Word sh_type;       /* Type of section */
  Elf64_Xword sh_flags;     /* Miscellaneous section attributes */
  Elf64_Addr sh_addr;       /* Section virtual addr at execution */
  Elf64_Off sh_offset;      /* Section file offset */
  Elf64_Xword sh_size;      /* Size of section in bytes */
  Elf64_Word sh_link;       /* Index of another section */
  Elf64_Word sh_info;       /* Additional section information */
  Elf64_Xword sh_addralign; /* Section alignment */
  Elf64_Xword sh_entsize;   /* Entry size if section holds table */
} Elf64_Shdr;



int main(int argc, char **argv) 
{
  FILE* ElfFile = NULL;
  char* SectNames = NULL;
  Elf64_Ehdr elfHdr;
  Elf64_Shdr sectHdr;
  uint32_t idx;

  if(argc != 2) {
    printf("usage: %s <ELF_FILE>\n", argv[0]);
    exit(1);
  }

  if((ElfFile = fopen(argv[1], "r")) == NULL) {
    perror("[E] Error opening file:");
    exit(1);
  }

  // read ELF header, first thing in the file
  fread(&elfHdr, 1, sizeof(Elf64_Ehdr), ElfFile);

  // read section name string table
  // first, read its header. 
  /* 
   e_shoff         This member holds the section header table's file offset
                   in bytes.  If the file has no section header table, this
                   member holds zero.

   e_shstrndx      This member holds the section header table index of the
               entry associated with the section name string table.  If
           the file has no section name string table, this member
           holds the value SHN_UNDEF.

           If the index of section name string table section is
           larger than or equal to SHN_LORESERVE (0xff00), this
           member holds SHN_XINDEX (0xffff) and the real index of
           the section name string table section is held in the
           sh_link member of the initial entry in section header
           table.  Otherwise, the sh_link member of the initial
           entry in section header table contains the value zero.

           SHN_UNDEF     This value marks an undefined, missing,
                         irrelevant, or otherwise meaningless
                         section reference.  For example, a symbol
                         "defined" relative to section number
                         SHN_UNDEF is an undefined symbol.

           SHN_LORESERVE This value specifies the lower bound of the
                         range of reserved indices.

           SHN_LOPROC    Values greater than or equal to SHN_HIPROC
                         are reserved for processor-specific
                         semantics.

           SHN_HIPROC    Values less than or equal to SHN_LOPROC are
                         reserved for processor-specific semantics.

           SHN_ABS       This value specifies absolute values for
                         the corresponding reference.  For example,
                         symbols defined relative to section number
                         SHN_ABS have absolute values and are not
                         affected by relocation.

           SHN_COMMON    Symbols defined relative to this section
                         are common symbols, such as Fortran COMMON
                         or unallocated C external variables.

           SHN_HIRESERVE This value specifies the upper bound of the
                         range of reserved indices between
                         SHN_LORESERVE and SHN_HIRESERVE, inclusive;
                         the values do not reference the section
                         header table.  That is, the section header
                         table does not contain entries for the
                         reserved indices.
  */
  fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof(sectHdr), SEEK_SET);
  fread(&sectHdr, 1, sizeof(sectHdr), ElfFile);
  /*
   sh_size       This member holds the section's size in bytes.  Unless the
                 section type is SHT_NOBITS, the section occupies sh_size
                 bytes in the file.  A section of type SHT_NOBITS may have a
                 nonzero size, but it occupies no space in the file.

   sh_offset     This member's value holds the byte offset from the
                 beginning of the file to the first byte in the section.
                 One section type, SHT_NOBITS, occupies no space in the
                 file, and its sh_offset member locates the conceptual
                 placement in the file.

   e_shnum       This member holds the number of entries in the section
                 header table.  Thus the product of e_shentsize and
                 e_shnum gives the section header table's size in bytes.
                 If a file has no section header table, e_shnum holds the
                 value of zero.

                 If the number of entries in the section header table is
                 larger than or equal to SHN_LORESERVE (0xff00), e_shnum
                 holds the value zero and the real number of entries in
                 the section header table is held in the sh_size member of
                 the initial entry in section header table.  Otherwise,
                 the sh_size member of the initial entry in the section
                 header table holds the value zero.   

   sh_name       This member specifies the name of the section.  Its value
                 is an index into the section header string table section,
                 giving the location of a null-terminated string.
   */
  // next, read the section, string data
  // printf("sh_size = %llu\n", sectHdr.sh_size);
  SectNames = malloc(sectHdr.sh_size);
  fseek(ElfFile, sectHdr.sh_offset, SEEK_SET);
  fread(SectNames, 1, sectHdr.sh_size, ElfFile);

  // read all section headers
  for (idx = 0; idx < elfHdr.e_shnum; idx++)
  {
    const char* name = "";

    fseek(ElfFile, elfHdr.e_shoff + idx * sizeof(sectHdr), SEEK_SET);
    fread(&sectHdr, 1, sizeof(sectHdr), ElfFile);

    // print section name
    if (sectHdr.sh_name);
      name = SectNames + sectHdr.sh_name;
    printf("%2u %s\n", idx, name);
  }

  return 0;
}

Running readelf“hello world”二进制文件会产生以下输出:

$ readelf -S helloworld
There are 30 section headers, starting at offset 0x1170:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000400254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000400274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400298  00000298
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           00000000004002b8  000002b8
       0000000000000060  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000400318  00000318
       000000000000003d  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           0000000000400356  00000356
       0000000000000008  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000400360  00000360
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400380  00000380
       0000000000000018  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000400398  00000398
       0000000000000048  0000000000000018   A       5    12     8
  [11] .init             PROGBITS         00000000004003e0  000003e0
       000000000000001a  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000400400  00000400
       0000000000000040  0000000000000010  AX       0     0     16
  [13] .text             PROGBITS         0000000000400440  00000440
       0000000000000182  0000000000000000  AX       0     0     16
  [14] .fini             PROGBITS         00000000004005c4  000005c4
       0000000000000009  0000000000000000  AX       0     0     4
  [15] .rodata           PROGBITS         00000000004005d0  000005d0
       0000000000000013  0000000000000000   A       0     0     4
  [16] .eh_frame_hdr     PROGBITS         00000000004005e4  000005e4
       0000000000000034  0000000000000000   A       0     0     4
  [17] .eh_frame         PROGBITS         0000000000400618  00000618
       00000000000000f4  0000000000000000   A       0     0     8
  [18] .init_array       INIT_ARRAY       0000000000600e10  00000e10
       0000000000000008  0000000000000000  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       0000000000600e18  00000e18
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .jcr              PROGBITS         0000000000600e20  00000e20
       0000000000000008  0000000000000000  WA       0     0     8
  [21] .dynamic          DYNAMIC          0000000000600e28  00000e28
       00000000000001d0  0000000000000010  WA       6     0     8
  [22] .got              PROGBITS         0000000000600ff8  00000ff8
       0000000000000008  0000000000000008  WA       0     0     8
  [23] .got.plt          PROGBITS         0000000000601000  00001000
       0000000000000030  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000601030  00001030
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000601040  00001040
       0000000000000008  0000000000000000  WA       0     0     1
  [26] .comment          PROGBITS         0000000000000000  00001040
       0000000000000024  0000000000000001  MS       0     0     1
  [27] .shstrtab         STRTAB           0000000000000000  00001064
       0000000000000108  0000000000000000           0     0     1
  [28] .symtab           SYMTAB           0000000000000000  000018f0
       0000000000000618  0000000000000018          29    45     8
  [29] .strtab           STRTAB           0000000000000000  00001f08
       000000000000023c  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

检查以下条目:

[13] .text             PROGBITS         0000000000400440  00000440
           0000000000000182  0000000000000000  AX       0     0     16

为了检索.text完全来自二进制文件的部分是否足以从文件中的地址 0x400440 + 0x440 读取 0x182 字节?其中 0x182 是节大小,0x400440 是地址,0x440 是偏移量?另外,这里的alignment(0x16)有什么作用?


提取.text您需要复制 0x182 部分(Size) 从 0x440 开始的字节 (Offset) 二进制文件中的地址。

忽略 0x400440 (Address)值,它与文件地址无关,它是 RAM 内存中的地址,您的.text部分将被复制loader https://en.wikipedia.org/wiki/Loader_%28computing%29. From ELF格式规范 http://www.skyfree.org/linux/references/ELF_Format.pdf:

sh_addr:如果该部分将出现在进程的内存映像中,则该成员给出 该部分的第一个字节应驻留的地址。否则,该成员包含 0。

Align值实际上是十进制,而不是十六进制。所以是 16,而不是 0x16。对齐意味着节地址必须是 16(字节)的倍数。


您可以亲自探索二进制文件来验证这一切。首先,观察二进制文件的反汇编:

$ objdump -D your-file | less

查找地点.text开始然后看看.text截面数据。现在就做个傻子吧hexdump手术:

$ hexdump -C your-file | less

现在找到Offset地址并查看从此地址开始的字节。你会发现它们与反汇编的字节相同.text部分。

结论: 你需要使用Offset值(来自readelf输出)在处理您的文件时,而不是Address value.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读取 ELF 部分的内容(以编程方式) 的相关文章

随机推荐

  • 如何为缩略图悬停添加标题 - Bootstrap?

    我正在尝试使用这个缩略图悬停标题插件进行引导 http sevenx de demo bootstrap thumbnail hover caption html http sevenx de demo bootstrap thumbnai
  • CIImage 的 PNG/JPEG 表示形式始终返回 nil

    我目前正在制作一个照片编辑应用程序 当用户选择照片时 会使用以下代码自动将其转换为黑白 func blackWhiteImage image UIImage gt Data print Starting black white let or
  • 从信号处理程序返回而不进入内核+用户空间中断

    这是我的旧问题的后续 通过 setcontext 从信号处理程序返回 https stackoverflow com questions 69237910 returning from a signal handler via setcon
  • Web API 2 会话

    我无法从 web api 2 中获取会话数据 我已经验证 cookie 是在 fiddler 中发送的 我知道 Web api 2 的最佳实践是无状态 但由于项目的要求 现在有必要是全状态的 我已经尝试过这个链接 WebAPI 2 属性路由
  • Javascript:相当于 PHP 的 hash_hmac() 与原始二进制输出?

    我正在连接到亚马逊产品广告 API 要签署我的请求 我需要对原始二进制文件HMAC SHA256 哈希的输出 In hash hmac 的 PHP 文档 http php net manual en function hash hmac p
  • 将数据库返回的浮点值舍入为“正确”值

    我有一个数据库列 其中包含 由于某种原因在一段时间内丢失 浮点值 因此 有人用一些小值 比如 0 00025 填充数据库表 当我运行报告时 我实际上得到了 0 000249999999 或者类似的值 因为无法表示输入的值 有没有可靠的方法来
  • R Plotly - 更改悬停信息的字体和不透明度

    我正在尝试更改绘图图中悬停信息框的字体和不透明度 使用 R 我使用了以下代码 但无法弄清楚如何更改悬停框的字体或不透明度 如果这可能的话 plotC lt plot ly tg x FINPERCH y JourneyTime type s
  • 如何自动创建 AWS EB 实例到 VPC 的经典链接

    我在 EB 上有一个经典应用程序 需要连接到 VPC 中的 RDS 我可以通过进入 EC2 实例 操作 ClassicLink 链接到 VPC 来手动配置 EB 实例以允许经典链接到 VPC 一旦我这样做了 一切都很好 但是如果没有手动干预
  • Netbeans 7.1.1 中的增强

    尝试运行以下命令 include
  • 检查 PHP 日期时间戳是否正确?

    有没有办法检查 PHP 中的日期时间戳是否正确 我目前正在使用yyyy mm dd hh mm ss在 MySQL 中 并希望确保当用户以与正确格式匹配的形式提供日期 时间戳时 直到有人提供了良好的 无错误 有效的 checkdate 示例
  • 按顺序对要上传的文件列表进行排序

    我的目标是让 python 使用 telegram upload 按升序将文件从设置的目录上传到 telegram 我的脚本似乎无法按顺序上传 它以随机顺序上传文件 我用过sorted功能无济于事 查看我的脚本 您可以看到我尝试过的一些事情
  • XercesDOMParser 和 XInclusion

    我试图让 xincludes 在现有系统中工作 该系统使用 xercesc 中的 XercesDOMParser 来解析来自客户端的传入 xml 我正在使用 Apache Xercesc v3 0 1 从输入流读取的传入 XML 是
  • JQuery 自动完成,结果是链接

    我正在尝试创建一个 JQuery 自动完成框 其中建议自动完成的单词是链接 类似于 Facebook 或 Quora 上发生的情况 基本上 我希望自动完成结果下拉 并且我希望人们能够单击它们并导航到不同的页面 这是我当前使用的代码
  • cURL 中的“c”代表什么?

    我知道 cURL 是一个命令行实用程序 可让您发送 HTTP 请求 但 c 代表什么 从他们的网站 cURL 是项目的名称 这个名字是 Client for URLs 最初 URL 拼写为大写 以使其显而易见 处理 URL 事实上它也可以发
  • 更高级别的 Python GUI 工具包,例如为 TreeView/Grid 传递字典

    使用 PyGTK 启动了我的第一个 Python pet 项目 虽然它是一个非常强大的 GUI 工具包并且看起来很棒 但我还是有一些烦恼 所以我考虑转向其他东西 因为它还不太广泛 环顾四周SO https stackoverflow com
  • 使用 openat 重新打开目录

    看起来 可以使用openat to re打开一个已经打开的目录 例如 在我的 Linux 系统上我可以执行以下操作 define GNU SOURCE include
  • 服务器和本地之间的 Mercurial?

    我正在进行一个门户开发工作 我有时会遇到一些麻烦 例如丢失 覆盖错误的文件等 所以我决定使用 Mercurial 来进行此开发 我第一次使用源代码管理的经历 我在这个项目的服务器 bluehost 上工作 有什么办法可以在本地保存更新备份吗
  • 跨线程Winforms控件编辑[重复]

    这个问题在这里已经有答案了 如果编辑文本的代码 属于 与包含 Windows 窗体的线程不同的线程 如何编辑 Windows 窗体元素中的文本 我得到了例外 跨线程操作无效 控制 textBox1 是从创建它的线程以外的线程访问的 谢谢 您
  • Python 求和 excel 文件

    我有一个包含 3 列的 Excel 文件 请举例如下 Name Produce Number Adam oranges 6 bob Apples 5 Adam Apples 4 steve Peppers 7 bob Peppers 16
  • 读取 ELF 部分的内容(以编程方式)

    我正在尝试检索 ELF 二进制文件中附加部分的内容 此时 我使用以下代码来检索每个部分的名称 include