/* 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); g_binary_symbol_set_alt_label(symbol, 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; }