
前提知识
UNIX系统的可执行文件都采用ELF格式,类型分为目标文件、可执行文件和共享库
ELF格式探析之三:sections
本例基于64位的小端序linux机器
以读取目标文件hello.o为例
#include
void say_hello(char *who) {
printf("hello, %s!\n", who);
}
char *my_name = "wb";
int man() {
say_hello(my_name);
return 0;
}
// 执行gcc -c hello.c生成hello.o
目标文件elf结构主要有:
ELF header,位于文件的0~64字节,存储文件的描述信息,Section header table的起始位置
N个Section
Section header table,每个条目64字节,对应一个Section的信息
Program header table,可执行文件需要,本例的hello.o没有
进一步分析elf结构
首先用readelf命令读取elf信息:readelf -h hello.o。总结如下:
ELF header占用64字节
N个Section占用6488-64-1472=4952字节
Section header table占用23*64=1472字节
readelf -h hello.o
ELF Header:
Class: ELF64
Data: 2's complement, little endian
OS/ABI: UNIX - System V
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Start of program headers: 0 (bytes into file)
Start of section headers: 5016 (bytes into file) //Section header table的起始位置
Size of this header: 64 (bytes) //ELF header的占用大小
Size of program headers: 0 (bytes) //hello.o没有program header table
Number of program headers: 0 //hello.o没有program header table
Size of section headers: 64 (bytes) //Section header table每个条目占用大小
Number of section headers: 23 //Section header table条目个数
Section header string table index: 22 //.shstrtab Section位于Section header table第22个条目
用php读取.shstrtab Section内容
.shstrtab Section其实是存储的所有Section的名字
$fp = fopen("hello.o", "rb");
fseek($fp, 40, SEEK_SET);
$sh_off = fread($fp, 8);
$sh_off = unpack("P", $sh_off);
var_dump("section header offset in file: ". $sh_off[1]);
fseek($fp, 10, SEEK_CUR);
$sh_ent_size = fread($fp, 2);
$sh_ent_size = unpack("v", $sh_ent_size);
var_dump("section header entry size: ". $sh_ent_size[1]);
$sh_num = fread($fp, 2);
$sh_num = unpack("v", $sh_num);
var_dump("section header number: ". $sh_num[1]);
$sh_strtab_index = fread($fp, 2);
$sh_strtab_index = unpack("v", $sh_strtab_index);
var_dump("section header string table index: ". $sh_strtab_index[1]);
fseek($fp, $sh_off[1] + $sh_strtab_index[1] * $sh_ent_size[1], SEEK_SET);
fseek($fp, 24, SEEK_CUR); //sh_name(4) + sh_type(4) + sh_flags(8) + sh_addr(8) = 24
$str_table_off = fread($fp, 8);
$str_table_off = unpack("P", $str_table_off);
var_dump("section name string table offset: ". $str_table_off[1]);
$str_table_size = fread($fp, 8);
$str_table_size = unpack("P", $str_table_size);
var_dump("section name string table size: ". $str_table_size[1]);
fseek($fp, $str_table_off[1], SEEK_SET);
$str = fread($fp, $str_table_size[1]);
print_r(explode("\x00", trim($str, "\x00")));
// 读取所有Section条目信息
for ($i =0;$i < $sh_num[1]; $i ++) {
fseek($fp, $sh_off[1] + $i * $sh_ent_size[1], SEEK_SET);
$sh_name = fread($fp, 4);
$sh_name = unpack("V", $sh_name);
fseek($fp, 20, SEEK_CUR); //sh_type(4) + sh_flags(8) + sh_addr(8) = 20
$sh_offset = fread($fp, 8);
$sh_offset = unpack("P", $sh_offset);
$sh_size = fread($fp, 8);
$sh_size = unpack("P", $sh_size);
printf("section: %2s name: %-24s offset: %12s size: %12s\n", $i, get_section_name($sh_name[1]), $sh_offset[1], $sh_size[1]);
}
function get_section_name($start) {
global $str;
$name = substr($str, $start);
return strstr($name, "\x00", true);
}
以上就是详解php读取elf结构示例教程,希望对你有所帮助。
-
抖音网页版官方入口 抖音网页版在线观看官网 时间:2026-01-08 -
GitLab、Git、Github、Gitee四者的区别 时间:2026-01-08 -
顺磁性和逆磁性的区别 顺磁性和逆磁性的判断方法 时间:2026-01-08 -
顺磁性是什么意思 顺磁性材料有哪些 时间:2026-01-08 -
usim卡是什么意思 usim卡和sim卡的区别 时间:2026-01-08 -
Web前端四大渲染模式SSR、CSR、ISR、SSG的定义和区别 时间:2026-01-08
今日更新
-
云原神b服官方认证纯净版-云原神b服一键登录直链
阅读:18
-
freeok免费追剧app下载安装官方正版-freeok免费追剧最新版本无广告直达入口
阅读:18
-
QQ网页版登录入口-QQ官方网页版登录地址
阅读:18
-
刘备的谐音梗是留备吗?揭秘三国最火谐音梗背后的搞笑故事!
阅读:18
-
jk漫画app旧版4.3.5版本免费下载-jk漫画旧版2024最新下载入口
阅读:18
-
歪歪漫画登录页面入口下载安装包-歪歪漫画登录页下载最新版本教程
阅读:18
-
photoshop手机网页版直达入口-Photoshop在线网页版手机端
阅读:18
-
刘备梗是指网络热传的刘备搞笑段子,揭秘三国名场面背后的爆笑真相!
阅读:18
-
哔咔漫画最新版本下载-哔咔漫画免费入口安卓安装包
阅读:18
-
如何申请yahoo邮箱注册-2026雅虎邮箱注册及使用全指南
阅读:18










