/* Chrysalide - Outil d'analyse de fichiers binaires
* pool.c - extraction des informations issues des tables globales
*
* Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* OpenIDA 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.
*
* OpenIDA 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 "pool.h"
#include
#include "dex-int.h"
#include "../mangling/demangler.h"
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à analyser. *
* *
* Description : Charge en mémoire toutes les chaînes trouvées. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool find_all_dex_strings(GDexFormat *format)
{
uint32_t i; /* Boucle de parcours */
const char *text; /* Texte issu du binaire */
GBinSymbol *symbol; /* Nouveau symbole construit */
for (i = 0; i < format->header.string_ids_size; i++)
{
text = get_string_from_dex_pool(format, i);
if (text == NULL) continue;
symbol = g_binary_symbol_new(STP_STRING, NULL, i);
g_binary_symbol_set_alt_name(symbol, strdup(text));
g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
}
return true;
}
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index du type recherchée. *
* *
* Description : Extrait une chaîne de caractères d'une table DEX. *
* *
* Retour : Chaîne de caractères trouvées ou NULL en cas d'erreur. *
* *
* Remarques : - *
* *
******************************************************************************/
const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
{
off_t pos; /* Tête de lecture */
string_id_item str_id; /* Identifiant de chaîne */
string_data_item str_data; /* Description de chaîne */
if (index >= format->header.string_ids_size)
return NULL;
pos = format->header.string_ids_off + index * sizeof(string_id_item);
if (!read_dex_string_id_item(format, &pos, &str_id))
return NULL;
pos = str_id.string_data_off;
if (!read_dex_string_data_item(format, &pos, &str_data))
return NULL;
return (const char *)str_data.data;
}
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index du type recherchée. *
* *
* Description : Extrait une représentation de type d'une table DEX. *
* *
* Retour : Composant GLib créé. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index)
{
off_t pos; /* Tête de lecture */
type_id_item type_id; /* Définition de la classe */
string_id_item str_id; /* Identifiant de chaîne */
string_data_item str_data; /* Description de chaîne */
//printf("Tp Index :: %hd / %d\n", index, format->header.type_ids_size);
if (index >= format->header.type_ids_size)
return NULL;
pos = format->header.type_ids_off + index * sizeof(type_id_item);
if (!read_dex_type_id_item(format, &pos, &type_id))
return NULL;
pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item);
if (!read_dex_string_id_item(format, &pos, &str_id))
return NULL;
pos = str_id.string_data_off;
if (!read_dex_string_data_item(format, &pos, &str_data))
return NULL;
//printf(">> String :: '%s'\n", str_data.data);
return demangle_type(DGT_JAVA, (char *)str_data.data);
}
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index de la classe recherchée. *
* *
* Description : Extrait une représentation de classe d'une table DEX. *
* *
* Retour : Composant GLib créé. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index)
{
GDataType *result; /* Instance à retourner */
off_t pos; /* Tête de lecture */
class_def_item class_def; /* Définition de la classe */
if (index >= format->header.class_defs_size)
return NULL;
pos = format->header.class_defs_off + index * sizeof(class_def_item);
if (!read_dex_class_def_item(format, &pos, &class_def))
return NULL;
result = NULL;
return result;
}
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index du champ recherché. *
* *
* Description : Extrait une représentation de champ d'une table DEX. *
* *
* Retour : Composant GLib créé. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index)
{
GBinVariable *result; /* Instance à retourner */
off_t pos; /* Tête de lecture */
field_id_item field_id; /* Description du champ */
GDataType *type; /* Type du champ */
const char *name; /* Désignation humaine */
GDataType *owner; /* Propriétaire du champ */
if (index >= format->header.field_ids_size)
return NULL;
pos = format->header.field_ids_off + index * sizeof(field_id_item);
if (!read_dex_field_id_item(format, &pos, &field_id))
return NULL;
type = get_type_from_dex_pool(format, field_id.type_idx);
name = get_string_from_dex_pool(format, field_id.name_idx);
if (name == NULL) goto bad_name;
result = g_binary_variable_new(type);
g_binary_variable_set_name(result, name);
if (field_id.class_idx != NO_INDEX)
{
owner = get_type_from_dex_pool(format, field_id.class_idx);
if (owner == NULL) goto bad_owner;
g_binary_variable_set_owner(result, owner);
}
return result;
bad_owner:
g_object_ref(G_OBJECT(type));
g_object_unref(G_OBJECT(result));
bad_name:
g_object_unref(G_OBJECT(type));
return NULL;
}
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index de la routine recherchée. *
* *
* Description : Extrait une représentation de routine d'une table DEX. *
* *
* Retour : Composant GLib créé. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index)
{
GBinRoutine *result; /* Instance à retourner */
off_t pos; /* Tête de lecture */
method_id_item meth_id; /* Description de la méthode */
GDataType *type;
string_id_item str_id; /* Identifiant de chaîne */
string_data_item str_data; /* Description de chaîne */
proto_id_item proto_id; /* Information de prototypage */
type_list args; /* Liste des arguments */
uint32_t i; /* Boucle de parcours */
GBinVariable *arg; /* Argument reconstitué */
if (index >= format->header.method_ids_size)
return NULL;
pos = format->header.method_ids_off + index * sizeof(method_id_item);
if (!read_dex_method_id_item(format, &pos, &meth_id))
return NULL;
type = get_type_from_dex_pool(format, meth_id.class_idx);
/*
if (type == NULL)
printf("class is nil\n");
else
printf("class = '%s'\n", g_data_type_to_string(type));
*/
/* Nom de la méthode */
pos = format->header.string_ids_off + meth_id.name_idx * sizeof(string_id_item);
if (!read_dex_string_id_item(format, &pos, &str_id))
return NULL;
pos = str_id.string_data_off;
if (!read_dex_string_data_item(format, &pos, &str_data))
return NULL;
//printf("String :: '%s'\n", str_data.data);
result = g_binary_routine_new();
g_binary_routine_set_name(result, (char *)str_data.data);
if (type != NULL)
g_binary_routine_set_namespace(result, type);
/*
printf(" ####\n");
printf(" #### ROUTINE '%s'\n", g_binary_routine_to_string(result));
printf(" ####\n");
printf(" ####\n");
*/
//printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result));
/* Retour de la routine */
pos = format->header.proto_ids_off + meth_id.proto_idx * sizeof(proto_id_item);
if (!read_dex_proto_id_item(format, &pos, &proto_id))
goto no_more_info;
type = get_type_from_dex_pool(format, proto_id.return_type_idx);
g_binary_routine_set_return_type(result, type);
/* Arguments de la routine */
pos = proto_id.parameters_off;
if (read_dex_type_list(format, &pos, &args))
for (i = 0; i < args.size; i++)
{
type = get_type_from_dex_pool(format, args.list[i].type_idx);
if (type == NULL) continue;
arg = g_binary_variable_new(type);
g_binary_routine_add_arg(result, arg);
}
no_more_info:
return result;
}