diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-06-17 16:11:45 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-06-17 16:11:45 (GMT) |
commit | 378be1ab322dce8e8377d692829d6877758e5960 (patch) | |
tree | 17dc518687a45649caa68304cc2a5750a0a50554 /plugins/lnxsyscalls/hops_armv7.c | |
parent | 1f7e9506775f66a3a5f2859779d33b914eee8ef4 (diff) |
Annotated linux kernel syscalls using a new plugin.
Diffstat (limited to 'plugins/lnxsyscalls/hops_armv7.c')
-rw-r--r-- | plugins/lnxsyscalls/hops_armv7.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/plugins/lnxsyscalls/hops_armv7.c b/plugins/lnxsyscalls/hops_armv7.c new file mode 100644 index 0000000..58b2702 --- /dev/null +++ b/plugins/lnxsyscalls/hops_armv7.c @@ -0,0 +1,262 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hops_armv7.c - recherche d'appels système spécifiques à ARMv7 + * + * 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 "hops_armv7.h" + + +#include <assert.h> +#include <string.h> + + +#include <plugins/arm/v7/registers/basic.h> + + + +/* Détermine si l'instruction lance un appel syystème. */ +static bool is_armv7_linux_syscall(GArchInstruction *); + +/* Identifie le numéro d'appel système en cours de manipulation. */ +static bool resolve_armv7_linux_syscall_number(tracked_path *, GArchProcessor *, const hunting_ops *, unsigned int *); + +/* Marque les registres associés aux n premiers arguments. */ +static bool look_for_armv7_linux_syscall_args(tracked_path *, size_t, size_t); + +/* Commente autant que possible un appel système brut. */ +static void comment_armv7_linux_syscall(tracked_path *, size_t, syscall_info_t *, comment_writer *); + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit les opérations spécifiques à ARMv7 pour une chasse. * +* * +* Retour : Ensemble d'opérations pour une chasse aux appels système. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const hunting_ops *get_armv7_hunting_ops(void) +{ + static const hunting_ops armv7_hops = { + + .arch = "arm", + + .is_syscall = is_armv7_linux_syscall, + .resolve_nr = resolve_armv7_linux_syscall_number, + .look_for_args = look_for_armv7_linux_syscall_args, + .comment = comment_armv7_linux_syscall + + }; + + return &armv7_hops; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à analyser. * +* * +* Description : Détermine si l'instruction lance un appel syystème. * +* * +* Retour : Bilan de l'analyse : true s'il s'agit bien d'un appel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_armv7_linux_syscall(GArchInstruction *instr) +{ + bool result; /* Conclusion à diffuser */ + const char *kwd; /* Désignation d'instruction */ + + kwd = g_arch_instruction_get_keyword(instr, ASX_INTEL); + + result = (strcmp(kwd, "svc") == 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : exec = suivi de l'utilisation des registres. * +* proc = processeur de l'architecture pour les instructions. * +* hops = opérations spécialement adaptées à une architecture. * +* nr = numéro de l'appel système identifié. [OUT] * +* * +* Description : Identifie le numéro d'appel système en cours de manipulation.* +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool resolve_armv7_linux_syscall_number(tracked_path *exec, GArchProcessor *proc, const hunting_ops *hops, unsigned int *nr) +{ + bool result; /* Bilan à faire remonter */ + GArchRegister *reg; /* Registre portant le numéro */ + bool got_nr; /* Bilan d'une recherche */ + GArchInstruction *instr; /* Instruction d'importance */ + const char *kwd; /* Désignation d'instruction */ + GArchOperand *op; /* Opérande avec une constante */ + + result = false; + + /* On vise r7... */ + reg = g_armv7_basic_register_new(7); + mark_register_in_tracker(exec, 0, reg, NULL); + + assert(count_register_tracker_stacks(exec) == 1); + + got_nr = look_for_registers(exec, 0, proc, hops); + + if (got_nr) + { + instr = get_register_write_location(exec, 0, reg); + kwd = g_arch_instruction_get_keyword(instr, ASX_INTEL); + + /* ... et uniquement les instructions 'mov r7, <imm>' */ + if (strncmp(kwd, "mov", 3) != 0) + goto ralsn_exit; + + op = g_arch_instruction_get_operand(instr, 1); + + if (!G_IS_IMM_OPERAND(op)) + goto ralsn_exit; + + *nr = g_imm_operand_get_raw_value(G_IMM_OPERAND(op)); + result = true; + + } + + ralsn_exit: + + g_object_unref(G_OBJECT(reg)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : exec = chemin d'exécution à préparer. * +* sid = identifiant de la pile d'exécution à traiter. * +* argc = nombre d'arguments à repérer. * +* * +* Description : Marque les registres associés aux n premiers arguments. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool look_for_armv7_linux_syscall_args(tracked_path *exec, size_t sid, size_t argc) +{ + bool result; /* Bilan à faire remonter */ + size_t i; /* Boucle de parcours */ + GArchRegister *reg; /* Registre portant le numéro */ + + /** + * man 2 syscall : + * + * arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7 + * ────────────────────────────────────────────────────────── + * arm/OABI a1 a2 a3 a4 v1 v2 v3 + * arm/EABI r0 r1 r2 r3 r4 r5 r6 + */ + + result = (argc <= 7); + + if (result) + for (i = 0; i < argc; i++) + { + reg = g_armv7_basic_register_new(i); + mark_register_in_tracker(exec, sid, reg, NULL); + g_object_ref(G_OBJECT(reg)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : exec = chemin d'exécution identifié. * +* sid = identifiant de la pile d'exécution à traiter. * +* info = fiche d'identité d'un appel système. * +* writer = conservateur des commentaires à écrire au final. * +* * +* Description : Commente autant que possible un appel système brut. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void comment_armv7_linux_syscall(tracked_path *exec, size_t sid, syscall_info_t *info, comment_writer *writer) +{ + GArchRegister *reg; /* Registre intervenant */ + GArchInstruction *instr; /* Instruction impliquée */ + size_t i; /* Boucle de parcours */ + + /* Type d'appel système */ + + reg = g_armv7_basic_register_new(7); + + instr = get_register_write_location(exec, sid, reg); + + if (instr != NULL) + add_comment_at(writer, info->name, instr); + + g_object_unref(G_OBJECT(instr)); + + g_object_unref(G_OBJECT(reg)); + + /* Eventuels arguments */ + + for (i = 0; i < info->argc; i++) + { + reg = g_armv7_basic_register_new(i); + + instr = get_register_write_location(exec, sid, reg); + + if (instr != NULL) + add_comment_at(writer, info->argv[i], instr); + + g_object_unref(G_OBJECT(instr)); + + g_object_unref(G_OBJECT(reg)); + + } + +} |