diff options
Diffstat (limited to 'src/analysis')
| -rwxr-xr-x | src/analysis/decomp/Makefile.am | 4 | ||||
| -rw-r--r-- | src/analysis/decomp/decompiler.c | 33 | ||||
| -rw-r--r-- | src/analysis/decomp/il.c | 382 | ||||
| -rw-r--r-- | src/analysis/decomp/il.h | 38 | ||||
| -rw-r--r-- | src/analysis/decomp/reduce.c | 53 | ||||
| -rw-r--r-- | src/analysis/decomp/reduce.h | 30 | ||||
| -rw-r--r-- | src/analysis/routine.c | 2 | 
7 files changed, 537 insertions, 5 deletions
diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am index 7b797bd..27388d6 100755 --- a/src/analysis/decomp/Makefile.am +++ b/src/analysis/decomp/Makefile.am @@ -2,7 +2,9 @@  noinst_LTLIBRARIES = libanalysisdecomp.la  libanalysisdecomp_la_SOURCES =			\ -	decompiler.h decompiler.c +	decompiler.h decompiler.c			\ +	il.h il.c							\ +	reduce.h reduce.c  libanalysisdecomp_la_LDFLAGS =  diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index 8e574c0..91a9163 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * decompiler.c - encadrement des phases de décompilation   * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -32,7 +32,9 @@  #include <i18n.h> +#include "il.h"  #include "../../decomp/output.h" +#include "../../decomp/expr/block.h"  #include "../../decomp/lang/java.h"    /* FIXME : remme ! */  #include "../../format/format.h" @@ -138,7 +140,11 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c      size_t i;      GDecContext *context;                   /* Contexte pour la décompil.  */ -    GDecInstruction *instr; +    GDecInstruction *dinstrs; + +    GArchInstruction *instrs;                /* Instructions natives        */ + +    vmpa_t max;                             /* Première adresse à écarter  */      format = g_loaded_binary_get_format(binary);      proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); @@ -152,7 +158,28 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c      {          context = g_arch_processor_get_decomp_context(proc); -        instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); +        g_object_set_data(G_OBJECT(context), "format", format); +        g_object_set_data(G_OBJECT(context), "routine", routines[i]); +        g_dec_context_set_max_address(context, max); + +        instrs = g_binary_routine_get_instructions(routines[i]); + +        max = g_binary_routine_get_address(routines[i]) +            + g_binary_routine_get_size(routines[i]); + +        printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i])); + +        dinstrs = build_decompiled_block(instrs, +                                         g_binary_routine_get_address(routines[i]), +                                         max, VMPA_MAX, context); + +        //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); + + + +        g_binary_routine_set_decomp_instructions(routines[i], dinstrs); + +          if (context != NULL)              g_object_unref(context); diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c new file mode 100644 index 0000000..d9b9588 --- /dev/null +++ b/src/analysis/decomp/il.c @@ -0,0 +1,382 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * il.h - mise en place d'un langage intermédiaire + * + * Copyright (C) 2012 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "il.h" + + +#include <malloc.h> +#include <stdlib.h> +#include <string.h> + + +#include "../../decomp/expr/block.h" +#include "../../decomp/instr/ite.h" + + + +/* Indications sur une branche */ +typedef struct _branch_info +{ +    vmpa_t *jumps;                          /* Jalons de la branche        */ +    size_t count;                           /* Quantité de ces jalons      */ + +} branch_info; + + +/* Indique si une adresse est retenue comme point de passage. */ +static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool); + +/* Identifie les différents points de passage d'une branche. */ +static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *); + +/* Retrouve le point de ralliement entre deux branches. */ +static vmpa_t compute_first_common_addr(branch_info *, branch_info *); + + + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = informations à consulter.                             * +*                addr = adresse à rechercher.                                 * +*                fast = autorise une recherche rapide.                        * +*                                                                             * +*  Description : Indique si une adresse est retenue comme point de passage.   * +*                                                                             * +*  Retour      : true si le jalon est déjà dans la liste, false sinon.        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ +    void *ptr;                              /* Résultat des recherches     */ + +    result = false; + +    if (!fast) +        for (i = 0; i < info->count && !result; i++) +            result = (info->jumps[i] == *addr); + +    else +    { +        ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); +        result = (ptr != NULL); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * +*                start  = adresse de début du bloc.                           * +*                end    = adresse de fin du bloc (exclusive).                 * +*                count  = nombre de sauts détectés. [OUT]                     * +*                                                                             * +*  Description : Identifie les différents points de passage d'une branche.    * +*                                                                             * +*  Retour      : Jalons dans le flot d'exécution.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info) +{ +    GArchInstruction *iter;                 /* Boucle de parcours #1       */ +    GArchInstruction **dests;               /* Instr. visée par une autre  */ +    InstructionLinkType *types;             /* Type de lien entre lignes   */ +    size_t dcount;                          /* Nombre de liens de dest.    */ +    size_t i;                               /* Boucle de parcours #2       */ +    vmpa_t addr;                            /* Adresse de la destination   */ + +    /* On évite de boucler... */ +    if (is_addr_in_branch(info, &start, false)) +        return; + +    info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); +    info->jumps[info->count - 1] = start; + +    /* On suit le flot jusqu'à la prochaine bifurcation */ +    for (iter = g_arch_instruction_find_by_address(instrs, start, true); +         iter != NULL; +         iter = g_arch_instruction_get_next_iter(instrs, iter, end)) +    { +        if (!g_arch_instruction_has_destinations(iter)) +            continue; + +        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + +        for (i = 0; i < dcount; i++) +            switch (types[i]) +            { +                case ILT_EXEC_FLOW: +                case ILT_JUMP: +                case ILT_JUMP_IF_TRUE: +                case ILT_JUMP_IF_FALSE: +                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); +                    find_next_jumps(instrs, addr, end, info); +                    break; + +                default: +                    break; + +            } + +        break; + +    } + +    /* Si on termine... */ +    if (iter != NULL && !is_addr_in_branch(info, &end, false)) +    { +        info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); +        info->jumps[info->count - 1] = end; +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : a = premier ensemble de jalons à parcourir.                  * +*                b = second ensemble de jalons à parcourir.                   * +*                                                                             * +*  Description : Retrouve le point de ralliement entre deux branches.         * +*                                                                             * +*  Retour      : Adresse commune à deux branches.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b) +{ +    vmpa_t result;                          /* Adresse trouvée à retourner */ +    size_t i;                               /* Boucle de parcours          */ + +    /* Valeur conceptuellement impossible à renvoyer */ +    result = VMPA_MAX; + +    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); +    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); + +    for (i = 0; i < a->count && result == VMPA_MAX; i++) +        if (is_addr_in_branch(b, &a->jumps[i], false)) +            result = a->jumps[i]; + +    return result; + +} + + + +#include "../../arch/processor.h" + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * +*                start  = adresse de début du bloc.                           * +*                end    = adresse de fin du bloc (exclusive).                 * +*                stop   = adresse d'arrêt en cas de saut ou VMPA_MAX.         * +*                ctx    = contexte de soutien à associer à l'opération.       * +*                                                                             * +*  Description : Procède à la décompilation basique d'un bloc déterminé.      * +*                                                                             * +*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop, GDecContext *ctx) +{ +    GDecInstruction *result;                /* Instructions décompilées    */ +    GArchInstruction *iter;                 /* Boucle de parcours          */ + +    GDecInstruction *pite;                  /* IfThenElse potientiel...    */ + +    GArchInstruction **dests;               /* Instr. visée par une autre  */ +    InstructionLinkType *types;             /* Type de lien entre lignes   */ +    size_t dcount;                          /* Nombre de liens de dest.    */ + +    size_t i;                               /* Boucle de parcours          */ +    vmpa_t addr;                            /* Adresse de la destination   */ + +    branch_info true_branch;                /* Branche 'condition vraie'   */ +    branch_info false_branch;               /* Branche 'condition fausse'  */ +    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */ +    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */ + +    vmpa_t next_addr;                       /* Prochaine instruction visée */ + +    GDecInstruction *first;                 /* Première décompilation      */ +    GDecInstruction *dinstr;                /* Nouvelle décompilation      */ + + +    GExeFormat *format;                     /* Format du binaire fourni    */ +    GArchProcessor *proc;                   /* Architecture du binaire     */ +    GDecContext *context;                   /* Contexte pour la décompil.  */ + + +    result = NULL; + +    printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop); + +    for (iter = g_arch_instruction_find_by_address(instrs, start, true); +         iter != NULL; +         ) +    { +        /* On s'arrêter si l'instruction est déjà décompilée */ +        if (g_object_get_data(G_OBJECT(iter), "decomp_done") != NULL) break; +        g_object_set_data(G_OBJECT(iter), "decomp_done", iter); + +        pite = g_arch_instruction_decompile(iter, ctx); + +        g_arch_instruction_get_location(iter, NULL, NULL, &addr); +        printf(" --- decomp %p @ 0x%08llx\n", pite, addr); + +        /* On n'approfondit que les chemins qui se séparent */ +        if (!g_arch_instruction_has_destinations(iter)) +        { +            iter = g_arch_instruction_get_next_iter(instrs, iter, end); +            continue; +        } + +        /* Adaptations en fonction du type de bifurcation */ + +        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + +        next_addr = 0; +        memset(&true_branch, 0, sizeof(branch_info)); +        memset(&false_branch, 0, sizeof(branch_info)); + +        for (i = 0; i < dcount; i++) +            switch (types[i]) +            { +                case ILT_EXEC_FLOW: +                case ILT_JUMP: +                    g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); +                    break; + +                case ILT_JUMP_IF_TRUE: +                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); +                    find_next_jumps(instrs, addr, end, &true_branch); +                    break; + +                case ILT_JUMP_IF_FALSE: +                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); +                    find_next_jumps(instrs, addr, end, &false_branch); +                    break; + +                default: +                    next_addr = VMPA_MAX; +                    break; + +            } + +        if (next_addr == VMPA_MAX) +        { +            iter = g_arch_instruction_get_next_iter(instrs, iter, end); +            continue; +        } + +        else if (true_branch.count > 0 || false_branch.count > 0) +        { +            next_addr = compute_first_common_addr(&true_branch, &false_branch); +            next_addr = MIN(next_addr, end); + +            format = g_object_get_data(G_OBJECT(ctx), "format"); +            proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); + +            context = g_arch_processor_get_decomp_context(proc); + +            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); +            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); +            g_dec_context_set_max_address(context, next_addr); + +            true_dinstr = build_decompiled_block(instrs, true_branch.jumps[0], +                                                 end, next_addr, context); + + +            context = g_arch_processor_get_decomp_context(proc); + +            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); +            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); +            g_dec_context_set_max_address(context, next_addr); + +            false_dinstr = build_decompiled_block(instrs, false_branch.jumps[0], +                                                  end, next_addr, context); + + +            printf("{branch : %p (0x%08llx) | %p (0x%08llx)\n", +                   true_dinstr, true_branch.jumps[0], +                   false_dinstr, false_branch.jumps[0]); + +            g_ite_instruction_set_branches(G_ITE_INSTRUCTION(pite), true_dinstr, false_dinstr); + +            if (next_addr == end) break; + +        } + +        /* Détermination du prochain point de chute */ + +        if (next_addr == stop) break; + +        iter = g_arch_instruction_find_by_address(instrs, next_addr, true); + +    } + + + + +    first = g_dec_context_get_decomp_instrs(ctx); + +    printf(" ... context instr : %p\n", first); + +    for (dinstr = first; +         dinstr != NULL; +         dinstr = g_dec_instruction_get_next_iter(first, dinstr)) +    { +        if (result == NULL) result = g_expr_block_new(dinstr); +        else g_expr_block_add_item(G_EXPR_BLOCK(result), dinstr); + +    } + +    printf(" ... return %p\n", result); + +    return result; + +} diff --git a/src/analysis/decomp/il.h b/src/analysis/decomp/il.h new file mode 100644 index 0000000..4f38b4f --- /dev/null +++ b/src/analysis/decomp/il.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * il.h - prototypes pour la mise en place d'un langage intermédiaire + * + * Copyright (C) 2012 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DECOMP_IL_H +#define _ANALYSIS_DECOMP_IL_H + + +#include "../../arch/instruction.h" +#include "../../decomp/instruction.h" + + + +/* Procède à la décompilation basique d'un bloc déterminé. */ +GDecInstruction *build_decompiled_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t, GDecContext *); + + + +#endif  /* _ANALYSIS_DECOMP_IL_H */ diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c new file mode 100644 index 0000000..926650d --- /dev/null +++ b/src/analysis/decomp/reduce.c @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * reduce.c - réduction de l'usage des [pseudo]-registres + * + * Copyright (C) 2012 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "reduce.h" + + +#if 0 + + + +/* Mémorisation de l'usage de chaque variable */ +typedef struct _var_usage +{ +    GDecInstruction *var;                   /* Variable manipulée          */ + +    size_t ref_counter;                     /* Décompte des utilisations   */ +    GDecInstruction *creation;              /* Emplacement de la création  */ +    GDecInstruction *usage;                 /* Lieu de dernère utilisation */ + +} var_usage; + +/* Réduction des usages */ +typedef struct _usage_reduc +{ + + + +} usage_reduc; + + +#endif + + diff --git a/src/analysis/decomp/reduce.h b/src/analysis/decomp/reduce.h new file mode 100644 index 0000000..aa13d7f --- /dev/null +++ b/src/analysis/decomp/reduce.h @@ -0,0 +1,30 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * reduce.h - prototypes pour la réduction de l'usage des [pseudo]-registres + * + * Copyright (C) 2012 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DECOMP_REDUCE_H +#define _ANALYSIS_DECOMP_REDUCE_H + + + + +#endif  /* _ANALYSIS_DECOMP_REDUCE_H */ diff --git a/src/analysis/routine.c b/src/analysis/routine.c index a21b6e7..7a191c9 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -998,7 +998,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang,          g_lang_output_start_routine_body(lang, buffer, line);          if (routine->dinstr != NULL) -            g_dec_instruction_print(routine->dinstr, buffer, NULL, lang); +            g_dec_instruction_print(routine->dinstr, buffer, line, lang);          g_lang_output_end_routine_body(lang, buffer);  | 
