/* Chrysalide - Outil d'analyse de fichiers binaires * params.c - affichage plus adapté des registres liés à des paramètres * * Copyright (C) 2012-2017 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 "params.h" #include #include #include #include #include /* Procède si nécessaire au remplacement du texte de l'opérande. */ static void process_register_operand(const GDexMethod *, GArchOperand *); /* Parcours en profondeur un ensemble d'arguments. */ static void process_args_operand(const GDexMethod *, const GDalvikArgsOperand *); /* Visite chaque opérande des instructions d'une méthode. */ static void visit_all_method_operands(const GDexMethod *, GArchInstruction *); /****************************************************************************** * * * Paramètres : method = routine en cours de parcours. * * operand = morceau d'instruction en cours de traitement. * * * * Description : Procède si nécessaire au remplacement du texte de l'opérande.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void process_register_operand(const GDexMethod *method, GArchOperand *operand) { GDalvikRegister *reg; /* Registre représenté */ uint16_t index; /* Indice de ce registre */ DexVariableIndex info; /* Nature réelle du registre */ char tmp[12 /* 4294967295U */]; /* Construction du texte */ reg = g_dalvik_register_operand_get(G_DALVIK_REGISTER_OPERAND(operand)); index = g_dalvik_register_get_index(reg); info = g_dex_method_get_variable(method, index); if (info & DVI_THIS) g_arch_operand_set_alt_text(operand, "this", RTT_REGISTER); else if (info & DVI_ARGUMENT) { snprintf(tmp, 12, "p%u", (unsigned int)DVI_INDEX(info)); g_arch_operand_set_alt_text(operand, tmp, RTT_REGISTER); } } /****************************************************************************** * * * Paramètres : method = routine en cours de parcours. * * args = liste d'opérandes à analyser. * * * * Description : Parcours en profondeur un ensemble d'arguments. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void process_args_operand(const GDexMethod *method, const GDalvikArgsOperand *args) { size_t count; /* Nombre d'opérandes */ size_t i; /* Boucle de parcours */ GArchOperand *operand; /* Operande à manipuler */ count = g_dalvik_args_count(args); for (i = 0; i < count; i++) { operand = g_dalvik_args_operand_get(args, i); if (G_IS_DALVIK_REGISTER_OPERAND(operand)) process_register_operand(method, operand); } } /****************************************************************************** * * * Paramètres : method = routine à venir parcourir. * * instrs = liste des instructions pour tout le binaire. * * * * Description : Visite chaque opérande des instructions d'une méthode. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void visit_all_method_operands(const GDexMethod *method, GArchInstruction *instrs) { GBinRoutine *routine; /* Abstraction de la méthode */ const mrange_t *range; /* Emplacement du symbole */ vmpa_t start; /* Début de la zone couverte */ vmpa_t end; /* Fin de la zone couverte */ GArchInstruction *iter; /* Boucle de parcours #1 */ size_t count; /* Nombre d'opérandes */ size_t i; /* Boucle de parcours #2 */ GArchOperand *operand; /* Operande à manipuler */ routine = g_dex_method_get_routine(method); range = g_binary_symbol_get_range(G_BIN_SYMBOL(routine)); start = get_mrange_addr(range)->virtual; end = start + get_mrange_length(range); g_object_unref(G_OBJECT(routine)); for (iter = g_arch_instruction_find_by_address(instrs, start, true); iter != NULL; iter = g_arch_instruction_get_next_iter(instrs, iter, end)) { g_arch_instruction_lock_operands(iter); count = _g_arch_instruction_count_operands(iter); for (i = 0; i < count; i++) { operand = _g_arch_instruction_get_operand(iter, i); if (G_IS_DALVIK_REGISTER_OPERAND(operand)) process_register_operand(method, operand); else if (G_IS_DALVIK_ARGS_OPERAND(operand)) process_args_operand(method, G_DALVIK_ARGS_OPERAND(operand)); g_object_unref(G_OBJECT(operand)); } g_arch_instruction_unlock_operands(iter); } } /****************************************************************************** * * * Paramètres : binary = représentation binaire à traiter. * * * * Description : Effectue le remplacement de tous les paramètres. * * * * Retour : true si une action a été menée, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool replace_parameters(GLoadedBinary *binary) { GDexFormat *format; /* Format du binaire chargé */ GArchProcessor *proc; /* Processeur de l'architecture*/ GArchInstruction *instrs; /* Instructions Dalvik */ size_t cls_count; /* Nombre de classes trouvées */ size_t i; /* Boucle de parcours #1 */ GDexClass *class; /* Classe à analyser */ size_t meth_count; /* Nombre de méthodes trouvées */ size_t j; /* Boucle de parcours #2 */ GDexMethod *method; /* Méthode à parcourir */ format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); proc = g_loaded_binary_get_processor(binary); instrs = NULL;//g_arch_processor_get_disassembled_instructions(proc); cls_count = g_dex_format_count_classes(format); for (i = 0; i < cls_count; i++) { class = g_dex_format_get_class(format, i); meth_count = g_dex_class_count_methods(class, false); for (j = 0; j < meth_count; j++) { method = g_dex_class_get_method(class, false, j); visit_all_method_operands(method, instrs); g_object_unref(G_OBJECT(method)); } meth_count = g_dex_class_count_methods(class, true); for (j = 0; j < meth_count; j++) { method = g_dex_class_get_method(class, true, j); visit_all_method_operands(method, instrs); g_object_unref(G_OBJECT(method)); } g_object_unref(G_OBJECT(class)); } g_object_unref(G_OBJECT(proc)); g_object_unref(G_OBJECT(format)); return true; }