diff options
Diffstat (limited to 'plugins/lnxsyscalls/hunter.c')
-rw-r--r-- | plugins/lnxsyscalls/hunter.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/plugins/lnxsyscalls/hunter.c b/plugins/lnxsyscalls/hunter.c new file mode 100644 index 0000000..4cac8e6 --- /dev/null +++ b/plugins/lnxsyscalls/hunter.c @@ -0,0 +1,346 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hunter.c - recherche de portes vers le noyau + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "hunter.h" + + +#include <analysis/routine.h> +#include <glibext/delayed-int.h> + + +#include "db.h" + + + +/* Chasse à l'appel système (instance) */ +struct _GGateHunter +{ + GDelayedWork parent; /* A laisser en premier */ + + const GPluginModule *plugin; /* Liens pour les messages */ + + GLoadedBinary *binary; /* Binaire chargé et concerné */ + GBinFormat *format; /* Format de fichier manipulé */ + GProcContext *context; /* Contexte de désassemblage */ + + size_t begin; /* Point de départ du parcours */ + size_t end; /* Point d'arrivée exclu */ + + activity_id_t id; /* Identifiant pour messages */ + + const hunting_ops *hops; /* Opérations particulières */ + sqlite3 *db; /* Base de données à manipuler */ + +}; + +/* Chasse à l'appel système (classe) */ +struct _GGateHunterClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +}; + + +/* Indique le type défini pour les tâches d'étude de routines. */ +GType g_gate_hunter_get_type(void); + +/* Initialise la classe des tâches d'étude de routines. */ +static void g_gate_hunter_class_init(GGateHunterClass *); + +/* Initialise une tâche d'étude de routines. */ +static void g_gate_hunter_init(GGateHunter *); + +/* Supprime toutes les références externes. */ +static void g_gate_hunter_dispose(GGateHunter *); + +/* Procède à la libération totale de la mémoire. */ +static void g_gate_hunter_finalize(GGateHunter *); + +/* Effectue une recherche d'appels système. */ +static void g_gate_hunter_process(GGateHunter *, GtkStatusStack *); + + + +/* Indique le type défini pour les tâches d'étude de routines. */ +G_DEFINE_TYPE(GGateHunter, g_gate_hunter, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tâches d'étude de routines. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gate_hunter_class_init(GGateHunterClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDelayedWorkClass *work; /* Version en classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_gate_hunter_dispose; + object->finalize = (GObjectFinalizeFunc)g_gate_hunter_finalize; + + work = G_DELAYED_WORK_CLASS(klass); + + work->run = (run_task_fc)g_gate_hunter_process; + +} + + +/****************************************************************************** +* * +* Paramètres : hunter = instance à initialiser. * +* * +* Description : Initialise une tâche d'étude de routines. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gate_hunter_init(GGateHunter *hunter) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : hunter = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gate_hunter_dispose(GGateHunter *hunter) +{ + g_object_unref(G_OBJECT(hunter->binary)); + + g_binary_format_unlock_symbols_rd(hunter->format); + g_object_unref(G_OBJECT(hunter->format)); + + g_object_unref(G_OBJECT(hunter->context)); + + G_OBJECT_CLASS(g_gate_hunter_parent_class)->dispose(G_OBJECT(hunter)); + +} + + +/****************************************************************************** +* * +* Paramètres : hunter = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gate_hunter_finalize(GGateHunter *hunter) +{ + if (hunter->db != NULL) + close_syscalls_database(hunter->db); + + G_OBJECT_CLASS(g_gate_hunter_parent_class)->finalize(G_OBJECT(hunter)); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* binary = binaire dont la définition est à compléter. * +* context = contexte de désassemblage. * +* begin = point de départ du parcours de liste. * +* end = point d'arrivée exclu du parcours. * +* id = identifiant du message affiché à l'utilisateur. * +* hops = opérations spécifiques à une architecture. * +* * +* Description : Crée une tâche de recherche de portes différée. * +* * +* Retour : Tâche créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGateHunter *g_gate_hunter_new(const GPluginModule *plugin, GLoadedBinary *binary, GProcContext *context, size_t begin, size_t end, activity_id_t id, const hunting_ops *hops) +{ + GGateHunter *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_GATE_HUNTER, NULL); + + result->plugin = plugin; + + result->binary = binary; + g_object_ref(G_OBJECT(binary)); + + result->format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + + g_binary_format_lock_symbols_rd(result->format); + + result->context = context; + g_object_ref(G_OBJECT(context)); + + result->begin = begin; + result->end = end; + + result->id = id; + + result->hops = hops; + + result->db = open_syscalls_database(plugin); + if (result->db == NULL) goto gghn_db_error; + + return result; + + gghn_db_error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : hunter = étude de routines à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Effectue une recherche d'appels système. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gate_hunter_process(GGateHunter *hunter, GtkStatusStack *status) +{ + GArchProcessor *proc; /* Architecture du binaire */ + size_t i; /* Boucle de parcours #1 */ + GBinSymbol *symbol; /* Commodité d'accès */ + const mrange_t *range; /* Couverture d'une routine */ + instr_iter_t *iter; /* Boucle de parcours #2 */ + GArchInstruction *instr; /* Instruction analysée */ + tracked_path *exec; /* Chemin d'exécution à suivre */ + unsigned int nr; /* Numéro d'appel système */ + bool ret; /* Bilan d'un appel */ + syscall_info_t *info; /* Information sur l'appel */ + size_t loop; /* Quantité de boucles en vue */ + size_t k; /* Boucle de parcours #3 */ + comment_writer *writer; /* Ecriture de commentaires */ + + proc = g_loaded_binary_get_processor(hunter->binary); + + for (i = hunter->begin; i < hunter->end; i++) + { + symbol = g_binary_format_get_symbol(hunter->format, i); + + if (!G_IS_BIN_ROUTINE(symbol)) + goto gghp_next; + + range = g_binary_symbol_get_range(symbol); + + iter = g_arch_processor_get_iter_from_address(proc, get_mrange_addr(range)); + + if (iter != NULL) + { + restrict_instruction_iterator(iter, range); + + for (instr = get_instruction_iterator_current(iter); + instr != NULL; + instr = get_instruction_iterator_next(iter)) + { + if (hunter->hops->is_syscall(instr)) + { + exec = create_register_tracker(iter); + + ret = hunter->hops->resolve_nr(exec, proc, hunter->hops, &nr); + if (!ret) goto unknown_syscall; + + info = extract_from_syscalls_database(hunter->db, hunter->plugin, hunter->hops->arch, nr); + if (info == NULL) goto unknown_syscall; + + loop = count_register_tracker_stacks(exec); + + for (k = 0; k < loop; k++) + { + ret = hunter->hops->look_for_args(exec, k, info->argc); + if (!ret) goto unknown_syscall; + + look_for_registers(exec, k, proc, hunter->hops); + + } + + writer = create_comment_writer(); + + loop = count_register_tracker_stacks(exec); + + for (k = 0; k < loop; k++) + hunter->hops->comment(exec, k, info, writer); + + write_all_comments(writer, G_PRELOAD_INFO(hunter->context)); + + delete_comment_writer(writer); + + unknown_syscall: + + delete_register_tracker(exec); + + } + + g_object_unref(G_OBJECT(instr)); + + } + + delete_instruction_iterator(iter); + + } + + gghp_next: + + gtk_status_stack_update_activity_value(status, hunter->id, 1); + + g_object_unref(G_OBJECT(symbol)); + + } + + g_object_unref(G_OBJECT(proc)); + +} |