From 60160c213f574ba1386a954d4c3fa4bf3435782e Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 10 Jun 2018 14:44:11 +0200 Subject: Improved Dalvik fill instruction loading and created links to their payload. --- plugins/dalvik/Makefile.am | 2 +- plugins/dalvik/fetch.h | 5 ++ plugins/dalvik/link.c | 2 +- plugins/dalvik/post.c | 98 ++++++++++++++++++++++++++++++++++++ plugins/dalvik/post.h | 4 ++ plugins/dalvik/processor-int.h | 2 +- plugins/dalvik/processor.c | 38 ++++++++------ plugins/dalvik/v35/opdefs/array_26.d | 7 +++ plugins/dalvik/v35/processor.c | 24 +++++++-- 9 files changed, 160 insertions(+), 22 deletions(-) create mode 100644 plugins/dalvik/post.c diff --git a/plugins/dalvik/Makefile.am b/plugins/dalvik/Makefile.am index 33dab13..e60b3ed 100644 --- a/plugins/dalvik/Makefile.am +++ b/plugins/dalvik/Makefile.am @@ -13,7 +13,7 @@ libdalvik_la_SOURCES = \ instruction.h instruction.c \ link.h link.c \ operand.h operand.c \ - post.h \ + post.h post.c \ processor-int.h \ processor.h processor.c \ register.h register.c diff --git a/plugins/dalvik/fetch.h b/plugins/dalvik/fetch.h index 45e6e1c..352353c 100644 --- a/plugins/dalvik/fetch.h +++ b/plugins/dalvik/fetch.h @@ -36,6 +36,11 @@ void help_fetching_with_dalvik_instruction(GArchInstruction *, GArchProcessor *, GDalvikContext *, GExeFormat *, size_t); +static inline void help_fetching_with_dalvik_fill_array_data_instruction(GArchInstruction *ins, GArchProcessor *proc, GDalvikContext *ctx, GExeFormat *fmt) +{ + help_fetching_with_dalvik_instruction(ins, proc, ctx, fmt, 1); +} + static inline void help_fetching_with_dalvik_goto_instruction(GArchInstruction *ins, GArchProcessor *proc, GDalvikContext *ctx, GExeFormat *fmt) { help_fetching_with_dalvik_instruction(ins, proc, ctx, fmt, 0); diff --git a/plugins/dalvik/link.c b/plugins/dalvik/link.c index 3b4afb1..aaed263 100644 --- a/plugins/dalvik/link.c +++ b/plugins/dalvik/link.c @@ -95,7 +95,7 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * GArchInstruction *target; /* Ligne visée par la référence*/ case_comment *comment; /* Commentaire à éditer */ uint16_t i; /* Boucle de parcours #1 */ - uint16_t j; /* Boucle de parcours #2 */ + uint16_t j; /* Boucle de parcours #2 */ int32_t tmp; /* Sauvegarde temporaire */ char *msg; /* Indication à imprimer */ size_t k; /* Boucle de parcours #3 */ diff --git a/plugins/dalvik/post.c b/plugins/dalvik/post.c new file mode 100644 index 0000000..4a98c64 --- /dev/null +++ b/plugins/dalvik/post.c @@ -0,0 +1,98 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * post.h - prototypes pour les traitements complémentaires à la phase de désassemblage + * + * Copyright (C) 2018 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 "post.h" + + +#include + + +#include + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = accès aux données du binaire d'origine. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void post_process_data_payload_references(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GExeFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + virt_t addr; /* Adresse visée par le saut */ + GBinFormat *bfmt; /* Version basique du format */ + GTargetOperand *new; /* Instruction de ciblage */ + vmpa2t target; /* Défination finale précise */ + mrange_t trange; /* Etendue du symbole à créer */ + VMPA_BUFFER(loc); /* Conversion en chaîne */ + char name[12 + VMPA_MAX_LEN]; /* Etiquette de la destination */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + g_arch_instruction_lock_operands(instr); + + op = _g_arch_instruction_get_operand(instr, 1); + assert(G_IS_IMM_OPERAND(op)); + + if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr) + && g_exe_format_translate_address_into_vmpa(format, addr, &target)) + { + bfmt = G_BIN_FORMAT(format); + + new = G_TARGET_OPERAND(g_target_operand_new(MDS_32_BITS_UNSIGNED, &target)); + + if (!g_target_operand_resolve(new, bfmt, true)) + { + init_mrange(&trange, &target, 0); + + vmpa2_to_string(&target, MDS_UNDEFINED, loc, NULL); + + snprintf(name, sizeof(name), "array_data_%s", loc + 2); + + symbol = g_binary_symbol_new(&trange, STP_CODE_LABEL); + g_binary_symbol_set_alt_label(symbol, name); + + g_binary_format_add_symbol(bfmt, symbol); + + g_target_operand_resolve(new, bfmt, true); + + } + + _g_arch_instruction_replace_operand(instr, op, G_ARCH_OPERAND(new)); + + } + + g_object_unref(G_OBJECT(op)); + + g_arch_instruction_unlock_operands(instr); + +} diff --git a/plugins/dalvik/post.h b/plugins/dalvik/post.h index 8306b26..a31cf37 100644 --- a/plugins/dalvik/post.h +++ b/plugins/dalvik/post.h @@ -48,5 +48,9 @@ static inline void post_process_dalvik_ifz_target_resolution(GArchInstruction *i } +/* Complète un désassemblage accompli pour une instruction. */ +void post_process_data_payload_references(GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); + + #endif /* _PLUGINS_DALVIK_POST_H */ diff --git a/plugins/dalvik/processor-int.h b/plugins/dalvik/processor-int.h index 7568533..f4f8b3b 100644 --- a/plugins/dalvik/processor-int.h +++ b/plugins/dalvik/processor-int.h @@ -52,7 +52,7 @@ struct _GDalvikProcessorClass /* Décode une pseudo-instruction dans un flux de données. */ -GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *, GDalvikContext *, const GBinContent *, vmpa2t *, uint8_t); +GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *, GDalvikContext *, const GBinContent *, vmpa2t *, uint8_t, bool *); diff --git a/plugins/dalvik/processor.c b/plugins/dalvik/processor.c index 8d24d5a..3ed0507 100644 --- a/plugins/dalvik/processor.c +++ b/plugins/dalvik/processor.c @@ -197,12 +197,13 @@ static GDalvikDContext *g_dalvik_processor_get_decomp_context(const GDalvikProce /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* addr = adresse virtuelle de l'instruction. * -* low8 = 8 bits de poids faible déjà lus. * +* Paramètres : proc = architecture visée par la procédure. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* low8 = 8 bits de poids faible déjà lus. * +* handled = dit si une pseudo-instruction était bien là. [OUT] * * * * Description : Décode une pseudo-instruction dans un flux de données. * * * @@ -212,22 +213,25 @@ static GDalvikDContext *g_dalvik_processor_get_decomp_context(const GDalvikProce * * ******************************************************************************/ -GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *proc, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos, uint8_t low8) +GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *proc, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos, uint8_t low8, bool *handled) { GArchInstruction *result; /* Instruction à renvoyer */ vmpa2t tmp; /* Position modifiable */ uint8_t high8; /* Nouvelle octet à venir lire */ uint16_t ident; /* Valeur lue dans le code */ - /* Vérification astucieuse et rapide...*/ - if (low8 != 0x00 /* DOP_NOP */) - return NULL; + /* Définition facultative, mais bon... */ + *handled = false; result = NULL; + /* Vérification astucieuse et rapide...*/ + if (low8 != 0x00 /* DOP_NOP */) + goto gdpdp_exit; + copy_vmpa(&tmp, pos); - if (!g_binary_content_read_u8(content, pos, &high8)) + if (!g_binary_content_read_u8(content, &tmp, &high8)) goto gdpdp_exit; ident = high8 << 8 | low8; @@ -236,11 +240,13 @@ GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *pr { case DPO_PACKED_SWITCH: case DPO_SPARSE_SWITCH: - result = g_dalvik_switch_instr_new(ident, ctx, content, pos); + result = g_dalvik_switch_instr_new(ident, ctx, content, &tmp); + *handled = true; break; case DPO_FILL_ARRAY_DATA: - result = g_dalvik_fill_instr_new(ident, ctx, content, pos); + result = g_dalvik_fill_instr_new(ident, ctx, content, &tmp); + *handled = true; break; default: @@ -249,11 +255,11 @@ GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *pr } - gdpdp_exit: - - if (result == NULL) + if (result != NULL) copy_vmpa(pos, &tmp); + gdpdp_exit: + return result; } diff --git a/plugins/dalvik/v35/opdefs/array_26.d b/plugins/dalvik/v35/opdefs/array_26.d index efb3261..2236500 100644 --- a/plugins/dalvik/v35/opdefs/array_26.d +++ b/plugins/dalvik/v35/opdefs/array_26.d @@ -35,4 +35,11 @@ @format 31t + @hooks { + + fetch = help_fetching_with_dalvik_fill_array_data_instruction + post = post_process_data_payload_references + + } + } diff --git a/plugins/dalvik/v35/processor.c b/plugins/dalvik/v35/processor.c index 57b8875..19141e5 100644 --- a/plugins/dalvik/v35/processor.c +++ b/plugins/dalvik/v35/processor.c @@ -201,6 +201,7 @@ static GArchInstruction *g_dalvik35_processor_disassemble(const GArchProcessor * { GArchInstruction *result; /* Instruction à renvoyer */ uint8_t raw8; /* Donnée de 8 bits à analyser */ + bool pseudo_handled; /* Détection de pseudo-instruc.*/ Dalvik35Opcodes id; /* Identifiant d'instruction */ static const disass_instr_fc decodings[DOP35_COUNT] = { @@ -464,6 +465,10 @@ static GArchInstruction *g_dalvik35_processor_disassemble(const GArchProcessor * }; + vmpa2t ttmp; + + copy_vmpa(&ttmp, pos); + /* Données brutes associées à une instruction ? */ result = g_dalvik_context_get_raw_data(ctx, content, pos); @@ -475,9 +480,22 @@ static GArchInstruction *g_dalvik35_processor_disassemble(const GArchProcessor * if (!g_binary_content_read_u8(content, pos, &raw8)) return NULL; - result = g_dalvik_processor_disassemble_pseudo(proc, ctx, content, pos, raw8); - - if (result != NULL) goto gdpd_done; + result = g_dalvik_processor_disassemble_pseudo(proc, ctx, content, pos, raw8, &pseudo_handled); + + /** + * Il faut distinguer : + * + * - result == NULL : ce n'était pas une pseudo-instruction. + * + * - result == NULL : c'était une pseudo-instruction, mais un thread + * parallèle avait déjà réservé la zone de donnée correspondante. + * + * Dans ce dernier cas, on ne chercher pas à désassembler d'avantage, + * car une pseudo-instruction est déjà en place et on ne veut surtout pas + * la remplacer par une instruction basique. + */ + + if (result != NULL || pseudo_handled) goto gdpd_done; /* ... ou instruction classique */ -- cgit v0.11.2-87-g4458