推荐:《PHP教程》
前提知识
以读取目标文件hello.o为例
#include <stdio.h> 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的名字
<?PHP $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); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。