/* Chrysalide - Outil d'analyse de fichiers binaires * code.c - annotation des éléments de code Dalvik * * Copyright (C) 2016 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 "code.h" #include #include #include #include #include #include #include /* Commente les définitions d'une protection contre exceptions. */ static bool annotate_dex_try_item(const GDexFormat *, vmpa2t *); /*Commente les définitions des listes de gestion d'exceptions. */ static bool annotate_dex_encoded_catch_handler_list(const GDexFormat *, vmpa2t *); /* Commente les définitions d'une prise en compte d'exceptions. */ static bool annotate_dex_encoded_catch_handler(const GDexFormat *, vmpa2t *); /* Commente les définitions des gestions d'exceptions par type. */ static bool annotate_dex_encoded_type_addr_pair(const GDexFormat *, vmpa2t *); /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Commente les définitions d'un corps de méthode. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_code_item(const GDexFormat *format, uleb128_t offset) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ SourceEndian endian; /* Boutisme utilisé */ vmpa2t pos; /* Tête de lecture des symboles*/ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *text; /* Texte constant à insérer */ uint16_t tries_size; /* Nombre de gestionnaires */ uint32_t insns_size; /* Nombre d'instructions */ uint16_t i; /* Boucle de parcours */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); endian = SRE_LITTLE;//g_dex_format_get_endianness(format); if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), offset, &pos)) return false; /* registers_size */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of registers used by this code")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); g_binary_symbol_define_as_block_start(symbol, true); /* ins_size */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of words of incoming arguments to the method that this code is for")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* outs_size */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of words of outgoing argument space required by this code for method invocation")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* tries_size */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of try_items for this instance")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); g_imm_operand_get_value(G_IMM_OPERAND(operand), MDS_16_BITS, &tries_size); /* debug_info_off */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Offset to the debug info sequence for this code")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* insns_size */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Size of the instructions list, in 16-bit code units")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* insns */ g_imm_operand_get_value(G_IMM_OPERAND(operand), MDS_32_BITS, &insns_size); advance_vmpa(&pos, insns_size * 2); /* padding */ if (insns_size % 2 != 0) { instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Pading")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); } /* tries */ result = true; for (i = 0; i < tries_size && result; i++) result = annotate_dex_try_item(format, &pos); if (tries_size > 0 && result) result = annotate_dex_encoded_catch_handler_list(format, &pos); /* Nettoyage final */ g_object_unref(G_OBJECT(content)); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * pos = tête de lecture pour les symboles. * * * * Description : Commente les définitions d'une protection contre exceptions. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_dex_try_item(const GDexFormat *format, vmpa2t *pos) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ SourceEndian endian; /* Boutisme utilisé */ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *text; /* Texte constant à insérer */ result = true; content = g_binary_format_get_content(G_BIN_FORMAT(format)); endian = SRE_LITTLE;//g_dex_format_get_endianness(format); /* start_addr */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Start address of the block of code covered by this entry")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); g_binary_symbol_define_as_block_start(symbol, true); /* insn_count */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of 16-bit code units covered by this entry")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* handler_off */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Offset to the encoded_catch_handler for this entry")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* Nettoyage final */ g_object_unref(G_OBJECT(content)); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * pos = tête de lecture physique des symboles. * * * * Description : Commente les définitions des listes de gestion d'exceptions. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_dex_encoded_catch_handler_list(const GDexFormat *format, vmpa2t *pos) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *text; /* Texte constant à insérer */ uleb128_t size; /* Nombre d'entrées */ uleb128_t i; /* Boucle de parcours */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* static_fields_size */ instr = g_raw_instruction_new_uleb128(content, pos); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Size of the list, in entries")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); g_binary_symbol_define_as_block_start(symbol, true); /* instance_fields_size */ g_imm_operand_as_uleb128(G_IMM_OPERAND(operand), &size); result = true; for (i = 0; i < size && result; i++) result = annotate_dex_encoded_catch_handler(format, pos); /* Nettoyage final */ g_object_unref(G_OBJECT(content)); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * pos = tête de lecture physique des symboles. * * * * Description : Commente les définitions d'une prise en compte d'exceptions. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_dex_encoded_catch_handler(const GDexFormat *format, vmpa2t *pos) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *text; /* Texte constant à insérer */ leb128_t size; /* Nombre de gestionnaires */ bool has_catch_all; /* Gestion par défaut ? */ uleb128_t i; /* Boucle de parcours */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* size */ instr = g_raw_instruction_new_sleb128(content, pos); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Number of static fields defined in this item")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); g_binary_symbol_define_as_block_start(symbol, true); g_imm_operand_as_leb128(G_IMM_OPERAND(operand), &size); has_catch_all = (size <= 0); if (size < 0) size *= -1; /* handlers */ result = true; for (i = 0; i < size && result; i++) result = annotate_dex_encoded_type_addr_pair(format, pos); /* catch_all_addr */ if (has_catch_all) { instr = g_raw_instruction_new_uleb128(content, pos); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Bytecode address of the catch-all handler")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); } /* Nettoyage final */ g_object_unref(G_OBJECT(content)); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * pos = tête de lecture des symboles. * * * * Description : Commente les définitions des gestions d'exceptions par type. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_dex_encoded_type_addr_pair(const GDexFormat *format, vmpa2t *pos) { GBinContent *content; /* Contenu binaire à lire */ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *text; /* Texte constant à insérer */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* type_idx */ instr = g_raw_instruction_new_uleb128(content, pos); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); asprintf(&text, _("Index for the type of the exception to catch")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* addr */ instr = g_raw_instruction_new_uleb128(content, pos); SET_IMM_DISPLAY(instr, operand, 0, IOD_HEX); asprintf(&text, _("Bytecode address of the associated exception handler")); ADD_RAW_AS_SYM(format, symbol, instr, comment, text); free(text); /* Nettoyage final */ g_object_unref(G_OBJECT(content)); return true; }