Maison  >  Article  >  développement back-end  >  Apprenez à lire la structure elfe en utilisant php

Apprenez à lire la structure elfe en utilisant php

藏色散人
藏色散人avant
2020-12-21 09:08:113818parcourir

Recommandé : "Tutoriel vidéo PHP"

Connaissances préalables

  1. Exécutable du système UNIX Les fichiers sont tous au format ELF, et les types sont divisés en fichiers cibles, fichiers exécutables et bibliothèques partagées
  2. Analyse du format ELF trois : sections
  3. Cet exemple est basé sur un petit- Machine Linux endian

Prenons la lecture du fichier cible hello.o comme exemple

#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

La structure elfe du fichier cible comprend principalement :

  1. En-tête ELF, situé entre 0 et 64 octets du fichier, stockant les informations de description du fichier, la position de départ de la table d'en-tête de section
  2. Section N
  3. Table d'en-tête de section, chacune l'entrée est de 64 octets, correspondant à une section. Les informations
  4. La table d'en-tête du programme est requise pour le fichier exécutable. Le hello.o dans cet exemple n'a pas

<.>Analyse plus approfondie de la structure des elfes

    Utilisez d'abord la commande readelf pour lire les informations de l'elfe : readelf -h hello.o. Le résumé est le suivant :
  1. L'en-tête ELF occupe 64 octets
  2. Les sections N occupent 6488-64-1472=4952 octets
  3. La table d'en-tête de section occupe 23*64=1472 mots Section
  4. readelf -h hello.o
    ELF Header:
    Class:                             ELF64
    Data:                              2&#39;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个条目
Utilisez php pour lire le contenu de la section .shstrtab

    .shstrtab La section est en fait le nom de toutes les sections stockées
  1. <?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);
    }

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer