From 60160c213f574ba1386a954d4c3fa4bf3435782e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "post.h"
+
+
+#include <assert.h>
+
+
+#include <arch/target.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  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