C# 解析ELF文件 C#如何读取Linux可执行文件的头部和节信息

来源:这里教程网 时间:2026-02-21 17:42:48 作者:

ELF头部读取失败:
BinaryReader
直接读会错位

ELF文件头部前4字节是魔数

\x7fELF
,但C#默认用
BinaryReader
ushort
uint
时,若没设
BitConverter.IsLittleEndian
匹配目标平台字节序,就会把32位/64位ELF的
e_ident
之后字段全读反。Linux ELF一律小端,Windows x64也是小端,看似没问题——但一旦遇到交叉编译生成的ARM64 ELF(仍是小端),或你误用
ReadUInt32()
读64位字段(如
e_entry
在64位ELF中占8字节),立刻越界或解析出0。

实操建议:

不用
BinaryReader.ReadXXX()
自动类型读取,改用
ReadBytes(n)
配合
BitConverter.ToUInt32(bytes, 0)
手动解包,显式指定偏移
先读
e_ident[4]
判断
ELFCLASS32
(1)还是
ELFCLASS64
(2),再决定后续字段长度和偏移
e_ident[5]
是字节序:值为1=小端,2=大端;别硬编码假设小端
头部固定部分长度:32位ELF是52字节,64位ELF是64字节——
e_phoff
e_shoff
等关键偏移都依赖这个基准

节头表(Section Header Table)找不到:
e_shoff
为0或
e_shnum
为0

很多strip过的ELF(如发行版二进制)会删掉节头表,只留程序头表(Program Header Table)。此时

e_shoff == 0
e_shnum == 0
是合法状态,不是你读错了。想查.text/.data节内容?靠节头表不行,得转向程序头表+内存段映射,或者用
readelf -S
确认原始文件是否真有节头。

实操建议:

检查
e_shoff > 0 && e_shnum > 0 && e_shentsize > 0
三者同时成立,才尝试读节头表
节头表本身不存字符串,节名存在
.shstrtab
节里,而
.shstrtab
的索引由
e_shstrndx
给出——这个字段可能为
SHN_UNDEF
(0),意味着无节名字符串表
32位ELF节头单条长40字节,64位是64字节;别用同一结构体硬套两种格式

System.IO.File.ReadAllBytes
加载大ELF文件卡死

一个500MB的调试版ELF,

File.ReadAllBytes
会一次性分配500MB托管内存,GC压力陡增,且后续解析时还得反复
Array.Copy
切片——实际只需读头部几十字节和若干节数据,没必要全载入。

实操建议:

FileStream
+
Seek()
跳转读,例如:
fs.Seek(e_shoff, SeekOrigin.Begin); fs.Read(buffer, 0, e_shentsize * e_shnum)
节内容按需读:拿到
sh_offset
sh_size
后,再
Seek
过去读对应块,避免预分配大数组
如果只是校验或提取符号,优先用
objdump -h
readelf -h
做验证,别在C#里重复造轮子

符号表解析失败:
.symtab
节存在但
st_name
指向乱码

st_name
是符号名在字符串表(如
.strtab
)里的偏移,不是字符串本身。常见错误是直接把
st_name
当ASCII码打印,或者用
Encoding.UTF8.GetString()
去解整个
.strtab
节——但
.strtab
是null分隔的C字符串集合,中间有大量\x00,UTF8解码会截断或报错。

实操建议:

先定位
.strtab
节内容(通过节头表找到其
sh_offset
sh_size
),再用
Array.IndexOf(bytes, (byte)0, st_name)
找下一个\x00位置,然后
Encoding.ASCII.GetString(bytes, st_name, length)
注意:有些ELF用
.dynsym
代替
.symtab
(动态链接库常见),别只盯
.symtab
名字
st_info
低4位是绑定属性(
STB_GLOBAL
等),高4位是类型(
STT_FUNC
等),需用
st_info & 0xf
(st_info >> 4) & 0xf
分别提取

ELF格式本身不复杂,但32/64位混用、大小端隐含假设、节表可选、字符串表分离这些设计,会让C#这种强类型语言容易在边界上栽跟头。最稳的方式是:每读一个字段,立刻用

readelf -h
xxd -l 64
核对原始字节,而不是猜结构体布局。

相关推荐