前提知识

  1. UNIX系统的可执行文件都采用ELF格式,类型分为目标文件、可执行文件和共享库
  2. ELF格式探析之三:sections
  3. 本例基于64位的小端序linux机器

以读取目标文件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结构主要有:

  1. ELF header,位于文件的0~64字节,存储文件的描述信息,Section header table的起始位置
  2. N个Section
  3. Section header table,每个条目64字节,对应一个Section的信息
  4. Program header table,可执行文件需要,本例的hello.o没有

进一步分析elf结构

  1. 首先用readelf命令读取elf信息:readelf -h hello.o。总结如下:
  2. ELF header占用64字节
  3. N个Section占用6488-64-1472=4952字节
  4. Section header table占用23*64=1472字节
readelf -h hello.oELF Header:Class:                             ELF64Data:                              2's complement, little endianOS/ABI:                            UNIX - System VType:                              REL (Relocatable file)Machine:                           Advanced Micro Devices X86-64Start 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 tableNumber of program headers:         0          //hello.o没有program header tableSize 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内容

  1. .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);}

更多相关文章

  1. PHP字节码缓存和内置服务器
  2. 2021各公司春招求职上岸大礼包! 春招一次上岸,阿里/字节/华为/腾
  3. 年末最新整理:阿里、腾讯、字节、华为、百度等大厂Android岗面经
  4. 和字节跳动面试官学长聊了聊人生~
  5. 值得收藏的正则表达式(匹配中文字符、匹配双字节字符、匹配HTML标
  6. 我可以在运行PHP的64位系统上将PHP_INT_SIZE定义为4个字节吗?
  7. PHP字节单位转换
  8. 使用PHP显示所有列条目

随机推荐

  1. python 爬取西刺免费代理ip 并使用telnet
  2. 搭建Python3+PyQt5+eric6平台开发基于Pyt
  3. 【python】通过代理安装包
  4. “全局变量是坏的”是什么意思?
  5. Python Django对接企业微信第三方服务回
  6. python 中的排序大法
  7. Python Flask WTForms:如何在视图中动态禁
  8. 从另一个Python脚本调用Python脚本的最佳
  9. python3如何打印进度条
  10. 基于fastai的分类网络