使用readelf分析so文件
版权归作者所有,如有转发,请注明文章出处: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
然后设置用户账户和密码。
通过 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