From 4da58817622d6c4c35e4cd4e6a99111065a87f54 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 28 Nov 2018 19:30:12 +0100 Subject: Adapted ROP finding to architectures in a better way. --- plugins/ropgadgets/Makefile.am | 1 + plugins/ropgadgets/finder.c | 70 ++++++++++++++----------- plugins/ropgadgets/helper.c | 110 ++++++++++++++++++++++++++++++++++++++++ plugins/ropgadgets/helper.h | 43 ++++++++++++++++ plugins/ropgadgets/helper_arm.c | 87 ++++++++++++++++++++++++------- plugins/ropgadgets/helper_arm.h | 8 ++- 6 files changed, 269 insertions(+), 50 deletions(-) create mode 100644 plugins/ropgadgets/helper.c create mode 100644 plugins/ropgadgets/helper.h diff --git a/plugins/ropgadgets/Makefile.am b/plugins/ropgadgets/Makefile.am index 8df1c2e..3302421 100644 --- a/plugins/ropgadgets/Makefile.am +++ b/plugins/ropgadgets/Makefile.am @@ -6,6 +6,7 @@ libdir = $(pluginslibdir) libropgadgets_la_SOURCES = \ finder.h finder.c \ + helper.h helper.c \ helper_arm.h helper_arm.c \ plugin.h plugin.c \ select.h select.c diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c index 7296757..3e7ed1a 100644 --- a/plugins/ropgadgets/finder.c +++ b/plugins/ropgadgets/finder.c @@ -28,22 +28,33 @@ #include -#include #include #include +#include "helper.h" #include "helper_arm.h" +/* Actions selon l'architecture */ +typedef struct _domain_ops +{ + size_t (* list) (char ***); + GProcContext * (* get) (const GArchProcessor *, size_t); + + const phys_t * (* setup) (size_t *); + +} domain_ops; + /* Données utiles à transmettre */ typedef struct _search_domain { GExeFormat *format; /* Format du fichier binaire */ GBinContent *content; /* Contenu associé récupéré */ GArchProcessor *proc; /* Processeur idéal en place */ - GProcContext *ctx; /* Contexte de désassemblage */ + + domain_ops ops; /* Actions particulières */ mrange_t *exe_ranges; /* Liste de zones exécutables */ size_t exe_count; /* Nombre de ces zones */ @@ -56,22 +67,23 @@ typedef struct _search_domain /* Désassemble rapidement une instruction. */ -static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, vmpa2t *); +static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, size_t, vmpa2t *); /* Etend la constitution d'une chaîne d'instructions. */ static rop_chain *push_new_instruction(rop_chain *, GArchInstruction *); /* Désassemble en amont d'une position autant que possible. */ -static void look_backward_for_gadgets(const search_domain *, const mrange_t *, const vmpa2t *, unsigned int, rop_chain *); +static void look_backward_for_gadgets(const search_domain *, size_t, const mrange_t *, const vmpa2t *, unsigned int, rop_chain *); /* Etablit une liste de tous les gadgets présents. */ -static rop_chain **list_all_gadgets_in_domain(const search_domain *, unsigned int, update_search_progress_cb, GObject *, size_t *); +static rop_chain **list_all_gadgets_in_domain(const search_domain *, size_t, unsigned int, update_search_progress_cb, GObject *, size_t *); /****************************************************************************** * * * Paramètres : domain = ensemble d'auxiliaires à disposition. * +* index = indice du type de contexte désiré. * * pos = tête de lecture pour le désassemblage. * * * * Description : Désassemble rapidement une instruction. * @@ -82,12 +94,12 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *, unsigned in * * ******************************************************************************/ -static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, vmpa2t *pos) +static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, size_t index, vmpa2t *pos) { GArchInstruction *result; /* Instruction à retourner */ GProcContext *ctx; /* Contexte de désassemblage */ - ctx = domain->ctx; /* TODO : copie */ + ctx = domain->ops.get(domain->proc, index); result = g_arch_processor_disassemble(domain->proc, ctx, domain->content, pos, domain->format); @@ -97,7 +109,7 @@ static GArchInstruction *disassemble_instruction_in_domain(const search_domain * g_arch_instruction_call_hook(result, IPH_POST, domain->proc, ctx, domain->format); } - //g_object_unref(G_OBJECT(ctx)); /* TODO */ + g_object_unref(G_OBJECT(ctx)); return result; @@ -151,6 +163,7 @@ static rop_chain *push_new_instruction(rop_chain *chain, GArchInstruction *instr /****************************************************************************** * * * Paramètres : domain = ensemble d'auxiliaires à disposition. * +* index = indice du type de contexte désiré. * * exe_range = couverture globale dont il ne faut pas sortir. * * ret = point de retour final déjà trouvé. * * max_depth = profondeur maximale des recherches. * @@ -164,7 +177,7 @@ static rop_chain *push_new_instruction(rop_chain *chain, GArchInstruction *instr * * ******************************************************************************/ -static void look_backward_for_gadgets(const search_domain *domain, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth, rop_chain *chain) +static void look_backward_for_gadgets(const search_domain *domain, size_t index, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth, rop_chain *chain) { const phys_t *ins_sizes; /* Tailles potentielles */ size_t sizes_count; /* Quantité de tailles à tester*/ @@ -177,8 +190,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_ phys_t diff; /* Volume de données traité */ mrange_t range; /* Couverture de l'instruction */ - ins_sizes = (phys_t []){ 2, 4 }; /* FIXME */ - sizes_count = 2; + ins_sizes = domain->ops.setup(&sizes_count); copy_vmpa(&last, ret); @@ -197,7 +209,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_ copy_vmpa(&end, &start); - instr = disassemble_instruction_in_domain(domain, &end); + instr = disassemble_instruction_in_domain(domain, index, &end); if (instr == NULL) continue; /* La jointure est-elle parfaite ? */ @@ -241,6 +253,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_ /****************************************************************************** * * * Paramètres : domain = ensemble d'auxiliaires à disposition. * +* index = indice du type de contexte désiré. * * max_depth = profondeur maximale des recherches. * * update = fonction de suivi mise à disposition. * * data = données à associer à une phase d'actualisation. * @@ -254,7 +267,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_ * * ******************************************************************************/ -static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count) +static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, size_t index, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count) { rop_chain **result; /* Liste de listes à renvoyer */ phys_t done; /* Accumulation des quantités */ @@ -295,7 +308,7 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsig copy_vmpa(&tmp, &ret); - gadget = disassemble_instruction_in_domain(domain, &tmp); + gadget = disassemble_instruction_in_domain(domain, index, &tmp); if (gadget == NULL) continue; /* A-t-on bien affaire à une instruction de retour ? */ @@ -325,7 +338,7 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsig chain = push_new_instruction(NULL, gadget); - look_backward_for_gadgets(domain, &domain->exe_ranges[i], &ret, max_depth, chain); + look_backward_for_gadgets(domain, index, &domain->exe_ranges[i], &ret, max_depth, chain); result = (rop_chain **)realloc(result, ++(*count) * sizeof(rop_chain *)); result[*count - 1] = chain; @@ -363,7 +376,6 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd const char *target; /* Sous-traitance requise */ search_domain domain; /* Outils pour la recherche */ GBinPortion *portions; /* Couche première de portions */ - GProcContext **contexts; /* Contextes pour recherches */ char **names; /* Désignations humaines liées */ size_t i; /* Boucle de parcours */ @@ -410,19 +422,20 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd /* Récupération des différents contextes */ if (strcmp(target, "armv7") == 0) - contexts = get_rop_contexts_for_arm(domain.proc, &names, count); - + { + domain.ops.list = list_rop_contexts_for_arm; + domain.ops.get = get_rop_contexts_for_arm; + domain.ops.setup = setup_instruction_sizes_for_arm; + } else { - contexts = (GProcContext **)calloc(1, sizeof(GProcContext *)); - names = (char **)calloc(1, sizeof(char *)); - *count = 1; - - contexts[0] = g_arch_processor_get_context(domain.proc); - names[0] = _("all"); - + domain.ops.list = list_rop_contexts_by_default; + domain.ops.get = get_rop_contexts_by_default; + domain.ops.setup = setup_instruction_sizes_by_default; } + *count = domain.ops.list(&names); + /* Calcul de la surface totale à parcourir */ domain.sum = 0; @@ -444,18 +457,13 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd { result[i].category = names[i]; - domain.ctx = contexts[i]; - - result[i].gadgets = list_all_gadgets_in_domain(&domain, max_depth, update, data, &result[i].count); - - g_object_unref(G_OBJECT(domain.ctx)); + result[i].gadgets = list_all_gadgets_in_domain(&domain, i, max_depth, update, data, &result[i].count); domain.runs_done++; } free(names); - free(contexts); free(domain.exe_ranges); diff --git a/plugins/ropgadgets/helper.c b/plugins/ropgadgets/helper.c new file mode 100644 index 0000000..ff89e85 --- /dev/null +++ b/plugins/ropgadgets/helper.c @@ -0,0 +1,110 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helper.c - recherche générique de gadgets + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#include "helper.h" + + +#include +#include + + +#include + + + +/****************************************************************************** +* * +* Paramètres : names = noms attribués aux différents contextes. [OUT] * +* * +* Description : Etablit une liste des contextes utiles à la recherche. * +* * +* Retour : Nombre de contextes gérés pour cette architecture. * +* * +* Remarques : Tous les tableaux créés sont à libérer après usage. * +* * +******************************************************************************/ + +size_t list_rop_contexts_by_default(char ***names) +{ + size_t result; /* Quantité à renvoyer */ + + result = 1; + + (*names) = malloc(result * sizeof(char *)); + + (*names)[0] = _("all"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : proc = processeur lié à l'architecture visée. * +* index = indice du type de contexte désiré. * +* * +* Description : Etablit un contexte utile et adapté à une recherche. * +* * +* Retour : Contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GProcContext *get_rop_contexts_by_default(const GArchProcessor *proc, size_t index) +{ + GProcContext *result; /* Contexte à retourner */ + + assert(index == 0); + + result = g_arch_processor_get_context(proc); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : count = nombre d'éléments du tableau retourné. [OUT] * +* * +* Description : Définit les tailles possibles d'une instruction recherchée. * +* * +* Retour : Liste de tailles plausibles. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const phys_t *setup_instruction_sizes_by_default(size_t *count) +{ + const phys_t *result; /* Liste de taille à renvoyer */ + + result = (phys_t []){ 1 }; + + *count = 1; + + return result; + +} diff --git a/plugins/ropgadgets/helper.h b/plugins/ropgadgets/helper.h new file mode 100644 index 0000000..84e5e13 --- /dev/null +++ b/plugins/ropgadgets/helper.h @@ -0,0 +1,43 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helper.h - prototypes pour la recherche générique de gadgets + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#ifndef _PLUGINS_ROPGADGETS_HELPER_H +#define _PLUGINS_ROPGADGETS_HELPER_H + + +#include + + + +/* Etablit une liste des contextes utiles à la recherche. */ +size_t list_rop_contexts_by_default(char ***); + +/* Etablit un contexte utile et adapté à une recherche. */ +GProcContext *get_rop_contexts_by_default(const GArchProcessor *, size_t); + +/* Définit les tailles possibles d'une instruction recherchée. */ +const phys_t *setup_instruction_sizes_by_default(size_t *); + + + +#endif /* _PLUGINS_ROPGADGETS_HELPER_H */ diff --git a/plugins/ropgadgets/helper_arm.c b/plugins/ropgadgets/helper_arm.c index 2361f06..ae6edf3 100644 --- a/plugins/ropgadgets/helper_arm.c +++ b/plugins/ropgadgets/helper_arm.c @@ -24,6 +24,7 @@ #include "helper_arm.h" +#include #include @@ -33,43 +34,93 @@ /****************************************************************************** * * -* Paramètres : proc = processeur lié à l'architecture visée. * -* names = noms attribués aux différents contextes. * -* count = nombre de gadgets trouvés. [OUT] * +* Paramètres : names = noms attribués aux différents contextes. [OUT] * * * * Description : Etablit une liste des contextes utiles à la recherche. * * * -* Retour : Liste de contextes mis en place. * +* Retour : Nombre de contextes gérés pour cette architecture. * * * -* Remarques : Toues les tableaux créés sont à libérer après usage. * +* Remarques : Tous les tableaux créés sont à libérer après usage. * * * ******************************************************************************/ -GProcContext **get_rop_contexts_for_arm(const GArchProcessor *proc, char ***names, size_t *count) +size_t list_rop_contexts_for_arm(char ***names) { - GProcContext **result; /* Contextes à retourner */ + size_t result; /* Quantité à renvoyer */ - result = (GProcContext **)calloc(2, sizeof(GProcContext *)); + result = 2; - (*names) = (char **)calloc(2, sizeof(char *)); + (*names) = malloc(result * sizeof(char *)); - *count = 2; + (*names)[0] = "Thumb"; + (*names)[1] = "ARM"; - /* Thumb */ + return result; - result[0] = g_arch_processor_get_context(proc); +} - g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[0]), 0, AV7IS_THUMB); - (*names)[0] = "Thumb"; +/****************************************************************************** +* * +* Paramètres : proc = processeur lié à l'architecture visée. * +* index = indice du type de contexte désiré. * +* * +* Description : Etablit un contexte utile et adapté à une recherche. * +* * +* Retour : Contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ - /* ARMM */ +GProcContext *get_rop_contexts_for_arm(const GArchProcessor *proc, size_t index) +{ + GProcContext *result; /* Contexte à retourner */ - result[1] = g_arch_processor_get_context(proc); + result = g_arch_processor_get_context(proc); - g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[1]), 0, AV7IS_ARM); + switch (index) + { + /* Thumb */ + case 0: + g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result), 0, AV7IS_THUMB); + break; - (*names)[1] = "ARM"; + /* ARM */ + case 1: + g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result), 0, AV7IS_ARM); + break; + + default: + assert(false); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : count = nombre d'éléments du tableau retourné. [OUT] * +* * +* Description : Définit les tailles possibles d'une instruction recherchée. * +* * +* Retour : Liste de tailles plausibles. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const phys_t *setup_instruction_sizes_for_arm(size_t *count) +{ + const phys_t *result; /* Liste de taille à renvoyer */ + + result = (phys_t []){ 2, 4 }; + + *count = 2; return result; diff --git a/plugins/ropgadgets/helper_arm.h b/plugins/ropgadgets/helper_arm.h index cb2021f..c9f3892 100644 --- a/plugins/ropgadgets/helper_arm.h +++ b/plugins/ropgadgets/helper_arm.h @@ -30,7 +30,13 @@ /* Etablit une liste des contextes utiles à la recherche. */ -GProcContext **get_rop_contexts_for_arm(const GArchProcessor *, char ***, size_t *); +size_t list_rop_contexts_for_arm(char ***); + +/* Etablit un contexte utile et adapté à une recherche. */ +GProcContext *get_rop_contexts_for_arm(const GArchProcessor *, size_t); + +/* Définit les tailles possibles d'une instruction recherchée. */ +const phys_t *setup_instruction_sizes_for_arm(size_t *); -- cgit v0.11.2-87-g4458