/* Chrysalide - Outil d'analyse de fichiers binaires
* params.c - affichage plus adapté des registres liés à des paramètres
*
* Copyright (C) 2012 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 Foobar. 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 */
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);
start = g_binary_routine_get_address(routine);
end = start + g_binary_routine_get_size(routine);
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))
{
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));
}
}
}
/******************************************************************************
* *
* 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 = 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);
}
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(proc));
g_object_unref(G_OBJECT(format));
return true;
}