diff options
Diffstat (limited to 'plugins/elf')
| -rw-r--r-- | plugins/elf/dynamic.c | 8 | ||||
| -rw-r--r-- | plugins/elf/symbols.c | 590 | 
2 files changed, 317 insertions, 281 deletions
| diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c index c6fce14..13292ec 100644 --- a/plugins/elf/dynamic.c +++ b/plugins/elf/dynamic.c @@ -333,15 +333,15 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)      result = false;      if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic)) -        goto rpug_exit; +        goto exit;      if (!_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &pltgot)) -        goto rpug_exit; +        goto exit;      got_virt = ELF_DYN(format, pltgot, d_un.d_ptr);      if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), got_virt, &got_addr)) -        goto rpug_exit; +        goto exit;      content = G_BIN_FORMAT(format)->content; @@ -377,7 +377,7 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)      } - rpug_exit: + exit:      return result; diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c index 854d724..d24b6d6 100644 --- a/plugins/elf/symbols.c +++ b/plugins/elf/symbols.c @@ -52,12 +52,6 @@  /* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */ -/* Enregistre un point d'entrée au sein d'un binaire ELF. */ -static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *); - -/* Enumère tous les points d'entrée principaux d'un binaire ELF. */ -static bool load_all_elf_basic_entry_points(GElfFormat *); -  /* Assure le chargement des symboles internes ELF en différé. */  static bool do_elf_symbol_loading(GElfLoading *, GElfFormat *, bool, phys_t *, GBinSymbol **); @@ -108,6 +102,20 @@ static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *, +/* ------------------------- INSCRIPTION DE POINTS D'ENTREE ------------------------- */ + + +/* Enregistre un point d'entrée au sein d'un binaire ELF. */ +static bool register_elf_entry_point(GElfFormat *, virt_t, GBinRoutine *); + +/* Désigne tous les points d'entrée par une étiquette dédiée. */ +static bool load_elf_entry_points_from_array(GElfFormat *, const elf_dyn *, const elf_dyn *, const char *); + +/* Enumère tous les points d'entrée principaux d'un binaire ELF. */ +static bool load_all_elf_basic_entry_points(GElfFormat *, GtkStatusStack *); + + +  /* ---------------------------------------------------------------------------------- */  /*                           CHARGEMENT GLOBAL DES SYMBOLES                           */  /* ---------------------------------------------------------------------------------- */ @@ -150,11 +158,8 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu      /* Symboles d'entrée, si encore besoin */ -    /** -     * Le tri en préalable -     */ - -    result &= load_all_elf_basic_entry_points(format); +    if (result) +        result = load_all_elf_basic_entry_points(format, status);      return result; @@ -163,272 +168,6 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu  /******************************************************************************  *                                                                             * -*  Paramètres  : format  = description de l'exécutable à compléter.           * -*                vaddr   = adresse virtuelle du symbole à insérer.            * -*                len     = taille de la routine à ajouter.                    * -*                routine = représentation de la fonction repérée.             * -*                                                                             * -*  Description : Enregistre un point d'entrée au sein d'un binaire ELF.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t len, GBinRoutine *routine) -{ -    GBinFormat *base;                       /* Version basique du format   */ -    virt_t final_vaddr;                     /* Adresse virtuelle retenue   */ -    bool status;                            /* Bilan d'une opération       */ -    vmpa2t addr;                            /* Localisation d'une routine  */ -    mrange_t range;                         /* Couverture mémoire associée */ -    GBinSymbol *symbol;                     /* Nouveau symbole construit   */ - -    /* Localisation complète du symbole */ - -    final_vaddr = format->ops.fix_virt(vaddr); - -    status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr); -    if (!status) return; - -    /* Comptabilisation en tant que symbole */ - -    if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol)) -    { -        g_object_unref(G_OBJECT(symbol)); -        g_object_unref(G_OBJECT(routine)); -    } - -    else -    { -        base = G_BIN_FORMAT(format); - -        init_mrange(&range, &addr, len); - -        symbol = G_BIN_SYMBOL(routine); - -        g_binary_symbol_set_range(symbol, &range); -        g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT); - -        g_binary_format_add_symbol(base, symbol); - -        /* Comptabilisation pour le désassemblage brut */ -        g_binary_format_register_code_point(base, vaddr, true); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : format = description de l'exécutable à consulter.            * -*                                                                             * -*  Description : Enumère tous les points d'entrée principaux d'un binaire ELF.* -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool load_all_elf_basic_entry_points(GElfFormat *format) -{ -    GBinFormat *base;                       /* Autre version du format     */ -    virt_t ep;                              /* Point d'entrée détecté      */ -    GBinRoutine *routine;                   /* Routine à associer à un pt. */ -    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/ -    elf_dyn item_a;                         /* Premier élément DYNAMIC     */ -    elf_dyn item_b;                         /* Second élément DYNAMIC      */ -    const GBinContent *content;             /* Contenu binaire à lire      */ -    phys_t length;                          /* Taille totale du contenu    */ -    bool status;                            /* Bilan d'une opération       */ -    vmpa2t pos;                             /* Tête de lecture courante    */ -    uint32_t virt_32;                       /* Adresse virtuelle sur 32b   */ -    uint64_t virt_64;                       /* Adresse virtuelle sur 64b   */ - -    base = G_BIN_FORMAT(format); - -    /* Point d'entrée principal éventuel */ - -    ep = ELF_HDR(format, format->header, e_entry); - -    if (ep != 0x0) -    { -        routine = g_binary_format_decode_routine(base, "entry_point"); -        register_elf_entry_point(format, ep, 0, routine); -    } - -    /* Chargemet de l'en-tête de programme DYNAMIC */ - -    if (!find_elf_dynamic_program_header(format, &dynamic)) -        goto laebep_exit; - -    /* Détection des constructeurs & destructeurs */ - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a)) -    { -        ep = ELF_DYN(format, item_a, d_un.d_ptr); - -        if (ep != 0x0) -        { -            routine = g_binary_format_decode_routine(base, "init_function"); -            register_elf_entry_point(format, ep, 0, routine); -        } - -    } - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a)) -    { -        ep = ELF_DYN(format, item_a, d_un.d_ptr); - -        if (ep != 0x0) -        { -            routine = g_binary_format_decode_routine(base, "termination_function"); -            register_elf_entry_point(format, ep, 0, routine); -        } - -    } - -    void load_entry_points_from_array(GElfFormat *fmt, const elf_dyn *ar, const elf_dyn *sz, const char *prefix) -    { -        unsigned int i;                     /* Boucle de parcours          */ -        char fullname[64];                  /* Désignation humaine         */ - -        assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1))); - -        content = G_BIN_FORMAT(fmt)->content; - -        status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), -                                                          ELF_DYN(fmt, *ar, d_un.d_val), -                                                          &pos); -        if (!status) return; - -        length = get_phy_addr(&pos) + ELF_DYN(fmt, *sz, d_un.d_val); - -        for (i = 0; get_phy_addr(&pos) < length; i++) -        { -            /** -             * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) : -             * -             *      DT_INIT_ARRAY -             *          Points to an array of function addresses that must be -             *          called, in-order, to perform initialization. Some of -             *          the entries in the array can be 0 or -1, and should -             *          be ignored. -             * -             * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY. -             */ - -            if (fmt->is_32b) -            { -                status = g_binary_content_read_u32(content, &pos, fmt->endian, &virt_32); -                status &= (virt_32 != 0x0 && virt_32 != 0xffffffff); -                ep = virt_32; -            } -            else -            { -                status = g_binary_content_read_u64(content, &pos, fmt->endian, &virt_64); -                status &= (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff); -                ep = virt_64; -            } - -            if (status) -            { -                snprintf(fullname, sizeof(fullname), "%s%u", prefix, i); - -                routine = g_binary_format_decode_routine(base, fullname); -                register_elf_entry_point(fmt, ep, 0, routine); - -            } - -        } - -    } - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a)) -    { -        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b)) -        { -            load_entry_points_from_array(format, &item_a, &item_b, "init_array_function_"); -        } - -    } - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a)) -    { -        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b)) -        { -            load_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_"); -        } - -    } - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a)) -    { -        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b)) -        { -            load_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_"); -        } - -    } - -    /* Identification de l'entrée de la PLT */ - -    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &item_a)) -    { -        status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), -                                                          ELF_DYN(format, item_a, d_un.d_val), -                                                          &pos); - -        if (status) -        { -            content = G_BIN_FORMAT(format)->content; - -            /* On saute le premier élément... */ -            if (format->is_32b) -                status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32); -            else -                status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64); - -            while (1) -            { -                if (format->is_32b) -                { -                    status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32); -                    ep = virt_32; -                } -                else -                { -                    status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64); -                    ep = virt_64; -                } - -                if (!status) break; - -                if (ep != 0x0) -                { -                    routine = g_binary_format_decode_routine(base, "plt_entry"); -                    register_elf_entry_point(format, ep, 0, routine); -                    break; -                } - -            } - -        } - -    } - - laebep_exit: - -    return true; - -} - - -/****************************************************************************** -*                                                                             *  *  Paramètres  : loading = chargement de symboles en cours.                   *  *                format  = format ELF à compléter.                            *  *                local   = s'apprête-t-on à constuire un symbole interne ?    * @@ -1449,3 +1188,300 @@ static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t re      return result;  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                           INSCRIPTION DE POINTS D'ENTREE                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format  = description de l'exécutable à compléter.           * +*                vaddr   = adresse virtuelle du symbole à insérer.            * +*                routine = représentation de la fonction repérée.             * +*                                                                             * +*  Description : Enregistre un point d'entrée au sein d'un binaire ELF.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool register_elf_entry_point(GElfFormat *format, virt_t vaddr, GBinRoutine *routine) +{ +    bool result;                            /* Bilan à renvoyer            */ +    virt_t final_vaddr;                     /* Adresse virtuelle retenue   */ +    vmpa2t addr;                            /* Localisation d'une routine  */ +    GBinFormat *base;                       /* Version basique du format   */ +    GBinSymbol *symbol;                     /* Nouveau symbole construit   */ +    mrange_t range;                         /* Couverture mémoire associée */ + +    /* Localisation complète du symbole */ + +    final_vaddr = format->ops.fix_virt(vaddr); + +    result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr); +    if (!result) goto exit; + +    base = G_BIN_FORMAT(format); + +    /* Comptabilisation en tant que symbole */ + +    if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol)) +    { +        /** +         * On ne relâche pas tout de suite le symbole trouvé, afin de le traiter +         * en fin de fonction. +         * +         * Par contre, la routine proposée est détruite ici. +         */ + +        g_object_unref(G_OBJECT(routine)); + +    } + +    else +    { +        symbol = G_BIN_SYMBOL(routine); +        g_object_ref(G_OBJECT(symbol)); + +        init_mrange(&range, &addr, 0); +        g_binary_symbol_set_range(symbol, &range); + +        g_binary_format_add_symbol(base, symbol); + +    } + +    /* Marquage */ + +    g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT); + +    g_object_unref(G_OBJECT(symbol)); + +    /* Comptabilisation pour le désassemblage brut */ +    g_binary_format_register_code_point(base, vaddr, true); + + exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à consulter.            * +*                array  = indications quant au tableau à charger.             * +*                size   = indications quant à la taille de ce tableau.        * +*                prefix = désignation de base des éléments du tableau.        * +*                                                                             * +*  Description : Désigne tous les points d'entrée par une étiquette dédiée.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool load_elf_entry_points_from_array(GElfFormat *format, const elf_dyn *array, const elf_dyn *size, const char *prefix) +{ +    bool result;                            /* Bilan à renvoyer            */ +    GBinFormat *base;                       /* Autre version du format     */ +    GBinContent *content;                   /* Contenu binaire à lire      */ +    vmpa2t pos;                             /* Tête de lecture courante    */ +    phys_t length;                          /* Taille totale du contenu    */ +    uint32_t virt_32;                       /* Adresse virtuelle sur 32b   */ +    uint64_t virt_64;                       /* Adresse virtuelle sur 64b   */ +    unsigned int i;                         /* Boucle de parcours          */ +    bool status;                            /* Bilan d'une opération       */ +    virt_t ep;                              /* Point d'entrée détecté      */ +    char fullname[64];                      /* Désignation humaine         */ +    GBinRoutine *routine;                   /* Routine à associer à un pt. */ + +    assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1))); + +    base = G_BIN_FORMAT(format); +    content = base->content; + +    result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), +                                                      ELF_DYN(format, *array, d_un.d_val), +                                                      &pos); +    if (!result) goto exit; + +    length = get_phy_addr(&pos) + ELF_DYN(format, *size, d_un.d_val); + +    for (i = 0; get_phy_addr(&pos) < length && result; i++) +    { +        /** +         * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) : +         * +         *      DT_INIT_ARRAY +         *          Points to an array of function addresses that must be +         *          called, in-order, to perform initialization. Some of +         *          the entries in the array can be 0 or -1, and should +         *          be ignored. +         * +         * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY. +         */ + +        if (format->is_32b) +        { +            result = g_binary_content_read_u32(content, &pos, format->endian, &virt_32); + +            status = (virt_32 != 0x0 && virt_32 != 0xffffffff); +            ep = virt_32; + +        } +        else +        { +            result = g_binary_content_read_u64(content, &pos, format->endian, &virt_64); + +            status = (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff); +            ep = virt_64; + +        } + +        if (result && status) +        { +            snprintf(fullname, sizeof(fullname), "%s%u", prefix, i); + +            routine = g_binary_format_decode_routine(base, fullname); +            result = register_elf_entry_point(format, ep, routine); + +        } + +    } + + exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à consulter.            * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Enumère tous les points d'entrée principaux d'un binaire ELF.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool load_all_elf_basic_entry_points(GElfFormat *format, GtkStatusStack *status) +{ +    bool result;                            /* Bilan à renvoyer            */ +    activity_id_t msg;                      /* Message de progression      */ +    GBinFormat *base;                       /* Autre version du format     */ +    virt_t ep;                              /* Point d'entrée détecté      */ +    GBinRoutine *routine;                   /* Routine à associer à un pt. */ +    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/ +    elf_dyn item_a;                         /* Premier élément DYNAMIC     */ +    elf_dyn item_b;                         /* Second élément DYNAMIC      */ + +    result = true; + +    msg = gtk_status_stack_add_activity(status, _("Registering entry points..."), 0); + +    base = G_BIN_FORMAT(format); + +    /* Point d'entrée principal éventuel */ + +    ep = ELF_HDR(format, format->header, e_entry); + +    if (ep != 0x0) +    { +        routine = g_binary_format_decode_routine(base, "entry_point"); +        result = register_elf_entry_point(format, ep, routine); +        if (!result) goto exit; +    } + +    /* Chargemet de l'en-tête de programme DYNAMIC */ + +    if (!find_elf_dynamic_program_header(format, &dynamic)) +        goto exit; + +    /* Détection des constructeurs & destructeurs */ + +    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a)) +    { +        ep = ELF_DYN(format, item_a, d_un.d_ptr); + +        if (ep != 0x0) +        { +            routine = g_binary_format_decode_routine(base, "init_function"); +            result = register_elf_entry_point(format, ep, routine); +            if (!result) goto exit; +        } + +    } + +    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a)) +    { +        ep = ELF_DYN(format, item_a, d_un.d_ptr); + +        if (ep != 0x0) +        { +            routine = g_binary_format_decode_routine(base, "termination_function"); +            result = register_elf_entry_point(format, ep, routine); +            if (!result) goto exit; +        } + +    } + +    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a)) +    { +        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b)) +        { +            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "init_array_function_"); +            if (!result) goto exit; +        } + +    } + +    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a)) +    { +        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b)) +        { +            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_"); +            if (!result) goto exit; +        } + +    } + +    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a)) +    { +        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b)) +        { +            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_"); +            if (!result) goto exit; +        } + +    } + +    /* Identification de l'entrée de la PLT */ + +    if (resolve_plt_using_got(format, &ep)) +    { +        if (ep != 0x0) +        { +            routine = g_binary_format_decode_routine(base, "plt_entry"); +            result = register_elf_entry_point(format, ep, routine); +        } + +    } + + exit: + +    gtk_status_stack_remove_activity(status, msg); + +    return result; + +} | 
