版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

readelf

readelf 是一个用于读取和显示 ELF(Executable and Linkable Format)文件信息的工具。虽然 readelf 工具本身是为 Unix-like 操作系统设计的,但你可以在 Windows 上通过 WSL 使用它。

WSL 允许你在 Windows 上运行 Linux 发行版,并且可以在其中使用 readelf 工具。

安装 WSL

打开 PowerShell 以管理员身份运行,并执行以下命令启用 WSL 并安装 Ubuntu 系统

wsl --install -d Ubuntu

然后设置用户账户和密码。 1727612949411.jpg

通过 wsl 命令进入 Ubuntu 系统。

在 wsl 中 /mnt/d 对应的就是 windows 下的 D 盘,其他同理。

使用 readelf

调用 readelf -a 一次性查看文件中的所有信息,包括文件头、程序头、节头、符号表、动态节等。

readelf -a libGameVMP.so

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x2650
  Start of program headers:          64 (bytes into file)
  Start of section headers:          130160 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         7
  Section header string table index: 1

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .shstrtab         STRTAB           000000000001fe30  0001fe30
       0000000000000035  0000000000000000           0     0     0
  [ 2] .dynsym           DYNSYM           0000000000000518  00000518
       0000000000000048  0000000000000018   A       3     1     4
  [ 3] .dynstr           STRTAB           0000000000000ec0  00000ec0
       0000000000000342  0000000000000000   A       0     0     0
  [ 4] .symtab           SYMTAB           000000000001fe65  0001fe65
       0000000000000048  0000000000000018   A       5     1     4
  [ 5] .strtab           STRTAB           000000000001fead  0001fead
       000000000000002b  0000000000000000   A       0     0     1
  [ 6] .dynamic          DYNAMIC          000000000006eae8  0001dae8
       0000000000000240  0000000000000008  AX       3     0     4
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x000000000001cba4 0x000000000001cba4  R E    0x10000
  LOAD           0x000000000001d9e8 0x000000000006e9e8 0x000000000006e9e8
                 0x00000000000021de 0x0000000000002418  RW     0x1000
  DYNAMIC        0x000000000001dae8 0x000000000006eae8 0x000000000006eae8
                 0x0000000000000240 0x0000000000000240  RW     0x8
  NOTE           0x00000000000001c8 0x00000000000001c8 0x00000000000001c8
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_EH_FRAME   0x0000000000015634 0x0000000000056634 0x0000000000056634
                 0x0000000000001afc 0x0000000000001afc  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000001d9e8 0x000000000006e9e8 0x000000000006e9e8
                 0x0000000000000618 0x0000000000000618  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .dynsym .dynstr
   01     .dynamic
   02     .dynamic
   03
   04
   05
   06     .dynamic

Dynamic section at offset 0x1dae8 contains 32 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libandroid.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x000000000000000e (SONAME)             Library soname: [libGameVMP.so]
 0x000000000000000c (INIT)               0x1bd68
 0x0000000000000019 (INIT_ARRAY)         0x6e9e8
 0x000000000000001b (INIT_ARRAYSZ)       216 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x6eac0
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x0000000000000004 (HASH)               0x1f0
 0x0000000000000005 (STRTAB)             0xec0
 0x0000000000000006 (SYMTAB)             0x518
 0x000000000000000a (STRSZ)              834 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x6ed28
 0x0000000000000002 (PLTRELSZ)           1488 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x1c78
 0x0000000000000007 (RELA)               0x1330
 0x0000000000000008 (RELASZ)             2376 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x0000000000000018 (BIND_NOW)
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x000000006ffffffe (VERNEED)            0x12d0
 0x000000006fffffff (VERNEEDNUM)         3
 0x000000006ffffff0 (VERSYM)             0x1202
 0x000000006ffffff9 (RELACOUNT)          76
 0x0000000000000000 (NULL)               0x0

There are no static relocations in this file.
To see the dynamic relocations add --use-dynamic to the command line.

The decoding of unwind sections for machine type AArch64 is not currently supported.

Symbol table '.dynsym' contains 3 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000002650     0 SECTION LOCAL  DEFAULT bad section index[ 10]
readelf: Warning: local symbol 1 found at index >= .dynsym's sh_info value of 1
     2: 000000000006ead0     0 SECTION LOCAL  DEFAULT bad section index[ 16]
readelf: Warning: local symbol 2 found at index >= .dynsym's sh_info value of 1

Symbol table '.symtab' contains 3 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __intel_security[...]

Histogram for bucket list length (total of 97 buckets):
 Length  Number     % of total  Coverage
      0  38         ( 39.2%)
      1  29         ( 29.9%)     29.0%
      2  20         ( 20.6%)     69.0%
      3  9          (  9.3%)     96.0%
      4  1          (  1.0%)    100.0%

No version information found in this file.

Displaying notes found at file offset 0x000001c8 with length 0x00000024:
  Owner                Data size        Description
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 7e55cc28965ecb053c55055043d9f1ed3260a498

自动化脚本

新一个 soinfo.sh,编写一个简单的Shell脚本,调用 readelf -a 命令并将输出保存到同名的 .txt 文件中。

#!/bin/bash

# 检查是否提供了SO文件
if [ -z "$1" ]; then
  echo "Usage: $0 <path_to_so_file>"
  exit 1
fi

# 提取输入文件的文件名
so_file="$1"

# 检查文件是否存在
if [ ! -f "$so_file" ]; then
  echo "Error: File '$so_file' not found!"
  exit 1
fi

# 获取文件名(不含扩展名)
base_name=$(basename "$so_file" .so)

# 创建输出文件名(.txt文件)
output_file="${base_name}.txt"

# 调用 readelf -a 并将结果导出到输出文件
readelf -a "$so_file" > "$output_file"

# 提示用户操作成功
echo "Information exported to $output_file"

创建 scripts 目录,并把 soinfo.sh 放到该目录下。 执行 nano ~/.bashrc 命令,把 scripts 目录添加到环境变量

export PATH=$PATH:/mnt/e/scripts

修改保存后,执行 source ~/.bashrc 使其生效。

之后就可以调用 soinfo.sh <so_path> 将 SO 文件的信息导出到同名的 .txt 文件

soinfo.sh libGameVMP.so

readelf: Warning: local symbol 1 found at index >= .dynsym's sh_info value of 1
readelf: Warning: local symbol 2 found at index >= .dynsym's sh_info value of 1
Information exported to libGameVMP.txt