From 044b4d6d7ba4de50cd4d05b92621900e929e2231 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 12 Oct 2011 13:31:00 +0000 Subject: Processed skipped instructions and used contexts. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@212 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 44 +++++++++ plugins/theseus/theseus.c | 2 +- src/analysis/disass/fetch.c | 16 +++- src/arch/Makefile.am | 2 + src/arch/artificial.c | 46 +++++++++ src/arch/artificial.h | 14 ++- src/arch/context-int.h | 49 ++++++++++ src/arch/context.c | 77 +++++++++++++++ src/arch/context.h | 52 ++++++++++ src/arch/dalvik/Makefile.am | 2 + src/arch/dalvik/context.c | 229 ++++++++++++++++++++++++++++++++++++++++++++ src/arch/dalvik/context.h | 73 ++++++++++++++ src/arch/dalvik/processor.c | 40 +++++++- src/arch/dalvik/specins.c | 115 ++++++++++++++++++++++ src/arch/dalvik/specins.h | 51 ++++++++++ src/arch/processor-int.h | 8 +- src/arch/processor.c | 42 +++++++- src/arch/processor.h | 6 +- src/format/elf/helper_x86.c | 2 +- 19 files changed, 854 insertions(+), 16 deletions(-) create mode 100644 src/arch/context-int.h create mode 100644 src/arch/context.c create mode 100644 src/arch/context.h create mode 100644 src/arch/dalvik/context.c create mode 100644 src/arch/dalvik/context.h create mode 100644 src/arch/dalvik/specins.c create mode 100644 src/arch/dalvik/specins.h diff --git a/ChangeLog b/ChangeLog index 227acaf..7411094 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +11-10-12 Cyrille Bagard + + * plugins/theseus/theseus.c: + Update code: provide a context when calling g_arch_processor_decode_instruction(). + + * src/analysis/disass/fetch.c: + Update code: provide a context when calling g_arch_processor_decode_instruction(). + Count skipped instructions as processed. Fix a bug: count only in DEBUG mode. + + * src/arch/artificial.c: + Mark this kind of instructions as being able to be skipped. + + * src/arch/artificial.h: + Mark this kind of instructions as being able to be skipped. + Fix a bug in the definition of the G_TYPE_DB_INSTRUCTION type. + + * src/arch/context.c: + * src/arch/context.h:: + * src/arch/context-int.h: + * src/arch/dalvik/context.c: + * src/arch/dalvik/context.h: + New entries: define context for decoding instructions. + + * src/arch/dalvik/Makefile.am: + Add the context.[ch] and specins.[ch] files to libarchdalvik_la_SOURCES. + + * src/arch/dalvik/processor.c: + Process skipped instructions and use contexts. + + * src/arch/dalvik/specins.c: + * src/arch/dalvik/specins.h: + New entries: handle special Dalvik opcodes. + + * src/arch/Makefile.am: + Add the context-int.h and context.[ch] files to libarch_la_SOURCES. + + * src/arch/processor.c: + * src/arch/processor.h: + * src/arch/processor-int.h: + Process skipped instructions and use contexts. + + * src/format/elf/helper_x86.c: + Update code: provide a context when calling g_arch_processor_decode_instruction(). + 11-10-05 Cyrille Bagard * src/analysis/disass/disassembler.c: diff --git a/plugins/theseus/theseus.c b/plugins/theseus/theseus.c index aec5353..dd389ed 100644 --- a/plugins/theseus/theseus.c +++ b/plugins/theseus/theseus.c @@ -505,7 +505,7 @@ static GRenderingLine *disassemble_target_address(GOpenidaBinary *binary, GRende /* Décodage des instructions */ - instr = g_arch_processor_decode_instruction(proc, data, + instr = g_arch_processor_decode_instruction(proc, NULL /*FIXME*/, data, &offset, length, 0/*offset*/, target); line = g_code_line_new(target, instr, options); diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 5f93eba..2ac9f5c 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -62,6 +62,7 @@ GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *binary, GBinPar off_t len; /* Taille de cette même zone */ vmpa_t base; /* Adresse de la zone binaire */ off_t start; /* Conservation du pt de départ*/ + GProcContext *context; /* Contexte pour le décodage */ vmpa_t addr; /* Adresse d'une instruction */ GArchInstruction *instr; /* Instruction décodée */ @@ -89,6 +90,8 @@ GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *binary, GBinPar if (len > bin_length) continue; + context = g_arch_processor_get_context(proc); + /* Décodage des instructions */ #ifdef DEBUG @@ -103,13 +106,15 @@ GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *binary, GBinPar { addr = base + pos; - instr = g_arch_processor_decode_instruction(proc, &bin_data[start], + instr = g_arch_processor_decode_instruction(proc, context, &bin_data[start], &pos, len, start, addr); g_arch_instruction_add_to_list(&result, instr); #ifdef DEBUG - if (G_IS_DB_INSTRUCTION(instr)) db++; - else valid++; + if (G_IS_DB_INSTRUCTION(instr) && !g_db_instruction_is_skipped(G_DB_INSTRUCTION(instr))) + db++; + else + valid++; #endif if (pos < len) @@ -117,7 +122,12 @@ GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *binary, GBinPar } + if (context != NULL) + g_object_unref(context); + +#ifdef DEBUG g_binary_part_set_checkup(parts[i], valid, db); +#endif done += len; gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 1a02c07..4f410cc 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -4,6 +4,8 @@ noinst_LTLIBRARIES = libarch.la libarch_la_SOURCES = \ archbase.h archbase.c \ artificial.h artificial.c \ + context-int.h \ + context.h context.c \ immediate.h immediate.c \ instruction-int.h \ instruction.h instruction.c \ diff --git a/src/arch/artificial.c b/src/arch/artificial.c index 7556d0a..4ffcbe3 100644 --- a/src/arch/artificial.c +++ b/src/arch/artificial.c @@ -37,6 +37,10 @@ struct _GDbInstruction { GArchInstruction parent; /* A laisser en premier */ +#ifdef DEBUG + bool skipped; /* Donnée traitée */ +#endif + }; /* Définition générique d'une instruction d'architecture inconnue (classe) */ @@ -217,3 +221,45 @@ static bool g_db_instruction_is_return(const GDbInstruction *instr) return false; } + + +#ifdef DEBUG + +/****************************************************************************** +* * +* Paramètres : instr = instruction à mettre à jour. * +* * +* Description : Marque une donnée comme ayant été considérée au sein du code.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_instruction_mark_as_skipped(GDbInstruction *instr) +{ + instr->skipped = true; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* * +* Description : Indique si une donnée fait partie du code exécutable. * +* * +* Retour : true si la donnée est intégrée dans le code, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_instruction_is_skipped(const GDbInstruction *instr) +{ + return instr->skipped; + +} + +#endif diff --git a/src/arch/artificial.h b/src/arch/artificial.h index 3e98595..f4a661d 100644 --- a/src/arch/artificial.h +++ b/src/arch/artificial.h @@ -37,9 +37,9 @@ #define G_TYPE_DB_INSTRUCTION g_db_instruction_get_type() -#define G_DB_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_instruction_get_type(), GArchOperand)) +#define G_DB_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_instruction_get_type(), GDbInstruction)) #define G_IS_DB_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_instruction_get_type())) -#define G_DB_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_db_instruction_get_type(), GArchOperandIface)) +#define G_DB_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_db_instruction_get_type(), GDbInstructionIface)) /* Définition générique d'une instruction d'architecture inconnue (instance) */ @@ -55,6 +55,16 @@ GType g_db_instruction_get_type(void); /* Crée une instruction de type 'db' à partir de données. */ GArchInstruction *g_db_instruction_new_from_data(const bin_t *, off_t *, off_t, vmpa_t, const GArchProcessor *); +#ifdef DEBUG + +/* Marque une donnée comme ayant été considérée au sein du code. */ +void g_db_instruction_mark_as_skipped(GDbInstruction *); + +/* Indique si une donnée fait partie du code exécutable. */ +bool g_db_instruction_is_skipped(const GDbInstruction *); + +#endif + #endif /* _ARCH_ARTIFICIAL_H */ diff --git a/src/arch/context-int.h b/src/arch/context-int.h new file mode 100644 index 0000000..c5bd386 --- /dev/null +++ b/src/arch/context-int.h @@ -0,0 +1,49 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context-int.h - prototypes internes pour le contexte lié à l'exécution d'un processeur + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 . + */ + + +#ifndef _ARCH_CONTEXT_INT_H +#define _ARCH_CONTEXT_INT_H + + +#include "context.h" + + + +/* Définition d'un contexte pour processeur (instance) */ +struct _GProcContext +{ + GObject parent; /* A laisser en premier */ + +}; + + +/* Définition d'un contexte pour processeur (classe) */ +struct _GProcContextClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _ARCH_CONTEXT_INT_H */ diff --git a/src/arch/context.c b/src/arch/context.c new file mode 100644 index 0000000..3d8f08c --- /dev/null +++ b/src/arch/context.c @@ -0,0 +1,77 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.c - contexte lié à l'exécution d'un processeur + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "context.h" + + +#include "context-int.h" + + + +/* Initialise la classe des contextes de processeur. */ +static void g_proc_context_class_init(GProcContextClass *); + +/* Initialise une instance de contexte de processeur. */ +static void g_proc_context_init(GProcContext *); + + + +/* Indique le type définit par la GLib pour le contexte de processeur. */ +G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de processeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_proc_context_class_init(GProcContextClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à initialiser. * +* * +* Description : Initialise une instance de contexte de processeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_proc_context_init(GProcContext *ctx) +{ + +} diff --git a/src/arch/context.h b/src/arch/context.h new file mode 100644 index 0000000..4111767 --- /dev/null +++ b/src/arch/context.h @@ -0,0 +1,52 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.h - prototypes pour le contexte lié à l'exécution d'un processeur + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 . + */ + + +#ifndef _ARCH_CONTEXT_H +#define _ARCH_CONTEXT_H + + +#include + + + +#define G_TYPE_PROC_CONTEXT g_proc_context_get_type() +#define G_PROC_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_proc_context_get_type(), GProcContext)) +#define G_IS_PROC_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_proc_context_get_type())) +#define G_PROC_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PROC_CONTEXT, GGProcContextClass)) +#define G_IS_PROC_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PROC_CONTEXT)) +#define G_PROC_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PROC_CONTEXT, GGProcContextClass)) + + +/* Définition d'un contexte pour processeur (instance) */ +typedef struct _GProcContext GProcContext; + +/* Définition d'un contexte pour processeur (classe) */ +typedef struct _GProcContextClass GProcContextClass; + + +/* Indique le type définit par la GLib pour le contexte de processeur. */ +GType g_proc_context_get_type(void); + + + +#endif /* _ARCH_CONTEXT_H */ diff --git a/src/arch/dalvik/Makefile.am b/src/arch/dalvik/Makefile.am index e8406b9..6640180 100644 --- a/src/arch/dalvik/Makefile.am +++ b/src/arch/dalvik/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libarchdalvik.la libarchdalvik_la_SOURCES = \ + context.h context.c \ instruction.h instruction.c \ dop_aget.c \ dop_aput.c \ @@ -42,6 +43,7 @@ libarchdalvik_la_SOURCES = \ operand.h operand.c \ processor.h processor.c \ register.h register.c \ + specins.h specins.c \ translate.h libarchdalvik_la_LIBADD = \ diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c new file mode 100644 index 0000000..67c1861 --- /dev/null +++ b/src/arch/dalvik/context.c @@ -0,0 +1,229 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.c - contexte lié à l'exécution d'un processeur + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "context.h" + + +#include +#include + + +#include "../context-int.h" + + + +/* Mémorisation d'un saut dans le code */ +typedef struct _skipped_dalvik_area skipped_dalvik_area; + + +/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */ + + +/* Définition d'un contexte pour processeur Dalkvik (instance) */ +struct _GDalvikContext +{ + GProcContext parent; /* A laisser en premier */ + + skipped_dalvik_area *skip; /* Liste de Zones à écarter */ + size_t count; /* Taille de cette liste */ + +}; + + +/* Définition d'un contexte pour processeur Dalkvik (classe) */ +struct _GDalvikContextClass +{ + GProcContextClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des contextes de processeur Dalkvik. */ +static void g_dalvik_context_class_init(GDalvikContextClass *); + +/* Initialise une instance de contexte de processeur Dalkvik. */ +static void g_dalvik_context_init(GDalvikContext *); + + + +/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */ + + +/* Mémorisation d'un saut dans le code */ +struct _skipped_dalvik_area +{ + vmpa_t start; /* Début de la zone concernée */ + vmpa_t end; /* Fin de la zone concernée */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION GLOBALE DU CONTEXTE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type définit par la GLib pour le contexte de processeur Dalkvik. */ +G_DEFINE_TYPE(GDalvikContext, g_dalvik_context, G_TYPE_PROC_CONTEXT); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de processeur Dalkvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_context_class_init(GDalvikContextClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à initialiser. * +* * +* Description : Initialise une instance de contexte de processeur Dalkvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_context_init(GDalvikContext *ctx) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un contexte pour l'exécution du processeur Dalvik. * +* * +* Retour : Contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDalvikContext *g_dalvik_context_new(void) +{ + GDalvikContext *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_CONTEXT, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MEMORISATION DES SAUTS DE CODE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* start = début de la zone à écarter du traitement. * +* end = fin de la zone à écarter du traitement. * +* * +* Description : Mémorise une nouvelle zone de code comme étant des données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dalvik_context_skip_new_area(GDalvikContext *ctx, vmpa_t start, vmpa_t end) +{ + ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip, + ++ctx->count * sizeof(skipped_dalvik_area)); + + ctx->skip[ctx->count - 1].start = start; + ctx->skip[ctx->count - 1].end = end; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter. * +* addr = adresse à mainupuler. * +* * +* Description : Indique si l'adresse est considérée comme zone de données. * +* * +* Retour : true si l'adresse est considérée comme zone de données. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_dalvik_context_have_to_skip(GDalvikContext *ctx, vmpa_t addr) +{ + bool result; /* verdict à retourner */ + size_t i; /* Boucle de parcours */ + + result = false; + + for (i = 0; i < ctx->count && !result; i++) + if (ctx->skip[i].start <= addr && addr < ctx->skip[i].end) + { + result = true; + ctx->skip[i].start += sizeof(uint16_t); + + /* BUG_ON(ctx->skip[i].start > ctx->skip[i].end) */ + + if (ctx->skip[i].start >= ctx->skip[i].end) + { + if (i <= (ctx->count - 1)) + memmove(&ctx->skip[i], &ctx->skip[i + 1], ctx->count - i - 1); + + if (--ctx->count == 0) + ctx->skip = NULL; + else + ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip, + ++ctx->count * sizeof(skipped_dalvik_area)); + + } + + break; + + } + + return result; + +} diff --git a/src/arch/dalvik/context.h b/src/arch/dalvik/context.h new file mode 100644 index 0000000..459cc22 --- /dev/null +++ b/src/arch/dalvik/context.h @@ -0,0 +1,73 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.h - prototypes pour le contexte lié à l'exécution d'un processeur + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 . + */ + + +#ifndef _ARCH_DALVIK_CONTEXT_H +#define _ARCH_DALVIK_CONTEXT_H + + +#include +#include + + +#include "../archbase.h" + + + +/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */ + + +#define G_TYPE_DALVIK_CONTEXT g_dalvik_context_get_type() +#define G_DALVIK_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_context_get_type(), GDalvikContext)) +#define G_IS_DALVIK_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_context_get_type())) +#define G_DALVIK_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_CONTEXT, GGDalvikContextClass)) +#define G_IS_DALVIK_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_CONTEXT)) +#define G_DALVIK_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_CONTEXT, GGDalvikContextClass)) + + +/* Définition d'un contexte pour processeur Dalkvik (instance) */ +typedef struct _GDalvikContext GDalvikContext; + +/* Définition d'un contexte pour processeur Dalkvik (classe) */ +typedef struct _GDalvikContextClass GDalvikContextClass; + + +/* Indique le type définit par la GLib pour le contexte de processeur Dalkvik. */ +GType g_dalvik_context_get_type(void); + +/* Crée un contexte pour l'exécution du processeur Dalvik. */ +GDalvikContext *g_dalvik_context_new(void); + + + +/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */ + + +/* Mémorise une nouvelle zone de code comme étant des données. */ +void g_dalvik_context_skip_new_area(GDalvikContext *, vmpa_t, vmpa_t); + +/* Indique si l'adresse est considérée comme zone de données. */ +bool g_dalvik_context_have_to_skip(GDalvikContext *, vmpa_t); + + + +#endif /* _ARCH_DALVIK_CONTEXT_H */ diff --git a/src/arch/dalvik/processor.c b/src/arch/dalvik/processor.c index 4fd8a2f..2f56f87 100644 --- a/src/arch/dalvik/processor.c +++ b/src/arch/dalvik/processor.c @@ -24,8 +24,10 @@ #include "processor.h" +#include "context.h" #include "instruction.h" #include "opcodes.h" +#include "specins.h" #include "../processor-int.h" @@ -52,8 +54,11 @@ static void g_dalvik_processor_class_init(GDalvikProcessorClass *); /* Initialise une instance de processeur de VM Dalvik. */ static void g_dalvik_processor_init(GDalvikProcessor *); +/* Fournit un contexte pour l'exécution du processeur Dalvik. */ +static GDalvikContext *g_dalvik_processor_get_context(const GDalvikProcessor *); + /* Décode une instruction dans un flux de données. */ -static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *, const bin_t *, off_t *, off_t, vmpa_t); +static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *, GDalvikContext *, const bin_t *, off_t *, off_t, vmpa_t); /* Indique le type défini par la GLib pour le processeur DALVIK. */ @@ -101,6 +106,7 @@ static void g_dalvik_processor_init(GDalvikProcessor *proc) parent->memsize = MDS_32_BITS; parent->inssize = MDS_16_BITS; + parent->get_ctx = (get_processor_context_fc)g_dalvik_processor_get_context; parent->decode = (decode_instruction_fc)g_dalvik_processor_decode_instruction; } @@ -131,7 +137,27 @@ GArchProcessor *g_dalvik_processor_new(void) /****************************************************************************** * * +* Paramètres : proc = architecture, spectatrice ici. * +* * +* Description : Fournit un contexte pour l'exécution du processeur Dalvik. * +* * +* Retour : Contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDalvikContext *g_dalvik_processor_get_context(const GDalvikProcessor *proc) +{ + return g_dalvik_context_new(); + +} + + +/****************************************************************************** +* * * Paramètres : proc = architecture visée par la procédure. * +* ctx = contexte lié à l'exécution du processeur. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * @@ -145,7 +171,7 @@ GArchProcessor *g_dalvik_processor_new(void) * * ******************************************************************************/ -static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) +static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *proc, GDalvikContext *ctx, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) { GArchInstruction *result; /* Instruction à renvoyer */ DalvikOpcodes id; /* Identifiant d'instruction */ @@ -315,6 +341,16 @@ static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProc }; + /* Continuité d'une zone spéciale... */ + if (g_dalvik_context_have_to_skip(ctx, addr)) + return SKIPPED_INSTR; + + /* Début d'une nouvelle zone spéciale... */ + if (g_dalvik_guess_special_instruction(ctx, data, *pos, len, addr)) + return SKIPPED_INSTR; + + /* Ou instruction classique */ + id = dalvik_guess_next_instruction(data, *pos, len); if (id != DOP_COUNT) (*pos)++; diff --git a/src/arch/dalvik/specins.c b/src/arch/dalvik/specins.c new file mode 100644 index 0000000..b6a7c4e --- /dev/null +++ b/src/arch/dalvik/specins.c @@ -0,0 +1,115 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * specins.c - gestion des instructions spéciales de la VM Dalvik + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "specins.h" + + +#include "../../common/endianness.h" + + + +/****************************************************************************** +* * +* Paramètres : ctx = contexte lié à l'exécution du processeur. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* * +* Description : Détermine si du code doit être écarté du traitement. * +* * +* Retour : true si une nouvelle zone de données est à écarter. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_dalvik_guess_special_instruction(GDalvikContext *ctx, const bin_t *data, off_t pos, off_t len, vmpa_t addr) +{ + bool result; /* Bilan à retourner */ + uint16_t ident; /* Valeur lue dans le code */ + vmpa_t start; /* Début d'une zone de données */ + vmpa_t end; /* Fin d'une zone de données */ + uint16_t switch_size; /* Taille du switch considéré */ + uint16_t array_width; /* Taille des éléments */ + uint32_t array_size; /* Taille du tableau */ + + /* Vérification astucieuse et rapide...*/ + if (data[pos] != 0x00 /* DOP_NOP */) return false; + + if (!read_u16(&ident, data, &pos, len, SRE_LITTLE)) + return false; + + start = addr + sizeof(ident); + end = start; + + switch (ident) + { + case DID_PACKED_SWITCH: + + if (!read_u16(&switch_size, data, &pos, len, SRE_LITTLE)) + return false; + + end += sizeof(switch_size) + (1 + switch_size) * sizeof(uint32_t); + + g_dalvik_context_skip_new_area(ctx, start, end); + result = true; + + break; + + case DID_SPARSE_SWITCH: + + if (!read_u16(&switch_size, data, &pos, len, SRE_LITTLE)) + return false; + + end += sizeof(switch_size) + (2 * switch_size) * sizeof(uint32_t); + + g_dalvik_context_skip_new_area(ctx, start, end); + result = true; + + break; + + case DID_FILL_ARRAY_DATA: + + if (!read_u16(&array_width, data, &pos, len, SRE_LITTLE)) + return false; + if (!read_u32(&array_size, data, &pos, len, SRE_LITTLE)) + return false; + + end += sizeof(array_width) + sizeof(array_size) + + array_width * array_size; + + g_dalvik_context_skip_new_area(ctx, start, end); + result = true; + + break; + + default: + result = false; + break; + + } + + return result; + +} diff --git a/src/arch/dalvik/specins.h b/src/arch/dalvik/specins.h new file mode 100644 index 0000000..51cf6e9 --- /dev/null +++ b/src/arch/dalvik/specins.h @@ -0,0 +1,51 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * specins.h - prototypes pour la gestion des instructions spéciales de la VM Dalvik + * + * Copyright (C) 2011 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 . + */ + + +#ifndef _ARCH_DALVIK_SPECINS_H +#define _ARCH_DALVIK_SPECINS_H + + +#include + + +#include "../archbase.h" +#include "context.h" + + + +/* Speinss spéciales */ +typedef enum _DalvikIdents +{ + DID_PACKED_SWITCH = 0x0100, /* Switch aux clefs compactes */ + DID_SPARSE_SWITCH = 0x0200, /* Switch aux clefs éclatées */ + DID_FILL_ARRAY_DATA = 0x0300 /* Contenu de tableau */ + +} DalvikIdents; + + +/* Détermine si du code doit être écarté du traitement. */ +bool g_dalvik_guess_special_instruction(GDalvikContext *, const bin_t *, off_t, off_t, vmpa_t); + + + +#endif /* _ARCH_DALVIK_SPECINS_H */ diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h index ccaaa57..9d067b1 100644 --- a/src/arch/processor-int.h +++ b/src/arch/processor-int.h @@ -46,10 +46,11 @@ - +/* Fournit un contexte propre au processeur d'une architecture. */ +typedef GProcContext * (* get_processor_context_fc) (const GArchProcessor *); /* Décode une instruction dans un flux de données. */ -typedef GArchInstruction * (* decode_instruction_fc) (const GArchProcessor *, const bin_t *, off_t *, off_t, vmpa_t); +typedef GArchInstruction * (* decode_instruction_fc) (const GArchProcessor *, GProcContext *, const bin_t *, off_t *, off_t, vmpa_t); /* Définition générique d'un processeur d'architecture (instance) */ @@ -61,6 +62,7 @@ struct _GArchProcessor MemoryDataSize memsize; /* Taille de l'espace mémoire */ MemoryDataSize inssize; /* Taille min. d'encodage */ + get_processor_context_fc get_ctx; /* Obtention d'un contexte */ decode_instruction_fc decode; /* Traduction en instructions */ }; @@ -81,6 +83,8 @@ struct _GArchProcessorClass +#define SKIPPED_INSTR ((void *)-1) + diff --git a/src/arch/processor.c b/src/arch/processor.c index 2b1f060..0e4fc3f 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -115,6 +115,33 @@ static void g_arch_processor_init(GArchProcessor *proc) /****************************************************************************** * * +* Paramètres : proc = architecture visée par la procédure. * +* * +* Description : Fournit un contexte propre au processeur d'une architecture. * +* * +* Retour : Nouveau contexte mise à disposition. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GProcContext *g_arch_processor_get_context(const GArchProcessor *proc) +{ + GProcContext *result; /* Contexte à retourner */ + + if (proc->get_ctx != NULL) + result = proc->get_ctx(proc); + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : proc = processeur d'architecture à consulter. * * * * Description : Fournit le boustime du processeur d'une architecture. * @@ -173,6 +200,7 @@ MemoryDataSize g_arch_processor_get_instruction_size(const GArchProcessor *proc) /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * +* ctx = contexte lié à l'exécution du processeur. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * @@ -187,20 +215,26 @@ MemoryDataSize g_arch_processor_get_instruction_size(const GArchProcessor *proc) * * ******************************************************************************/ -GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc, const bin_t *data, off_t *pos, off_t len, off_t base, vmpa_t addr) +GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc, GProcContext *ctx, const bin_t *data, off_t *pos, off_t len, off_t base, vmpa_t addr) { GArchInstruction *result; /* Instruction à renvoyer */ off_t old_pos; /* Sauvegarde de la position */ + bool skipped; /* Données prise en compte ? */ old_pos = *pos; - result = proc->decode(proc, data, pos, len, addr); + result = proc->decode(proc, ctx, data, pos, len, addr); - if (result == NULL) + if (result == NULL || result == SKIPPED_INSTR) { + skipped = (result == SKIPPED_INSTR); + *pos = old_pos; - printf("ERRerr while decoding opcode 0x%02hhx at 0x%08llx\n", data[*pos], addr); result = g_db_instruction_new_from_data(data, pos, len, base, proc); + + if (skipped) + g_db_instruction_mark_as_skipped(G_DB_INSTRUCTION(result)); + } g_arch_instruction_set_location(result, base + old_pos, *pos - old_pos, addr); diff --git a/src/arch/processor.h b/src/arch/processor.h index a7c171d..fbdbb38 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -28,6 +28,7 @@ #include +#include "context.h" #include "instruction.h" #include "../common/endianness.h" @@ -49,6 +50,9 @@ typedef struct _GArchProcessorClass GArchProcessorClass; /* Indique le type défini pour un processeur d'architecture. */ GType g_arch_processor_get_type(void); +/* Fournit un contexte propre au processeur d'une architecture. */ +GProcContext *g_arch_processor_get_context(const GArchProcessor *); + /* Fournit le boustime du processeur d'une architecture. */ SourceEndian g_arch_processor_get_endianness(const GArchProcessor *); @@ -59,7 +63,7 @@ MemoryDataSize g_arch_processor_get_memory_size(const GArchProcessor *); MemoryDataSize g_arch_processor_get_instruction_size(const GArchProcessor *); /* Décode une instruction dans un flux de données. */ -GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *, const bin_t *, off_t *, off_t, off_t, vmpa_t); +GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *, GProcContext *, const bin_t *, off_t *, off_t, off_t, vmpa_t); diff --git a/src/format/elf/helper_x86.c b/src/format/elf/helper_x86.c index 3b9084c..dd6d278 100644 --- a/src/format/elf/helper_x86.c +++ b/src/format/elf/helper_x86.c @@ -219,7 +219,7 @@ GArchInstruction **decode_elf_relocations(GElfFormat *format, const elf_shdr *pl { address = plt_address + pos; - instr = g_arch_processor_decode_instruction(proc, &G_BIN_FORMAT(format)->content[plt_start], + instr = g_arch_processor_decode_instruction(proc, NULL /*FIXME*/, &G_BIN_FORMAT(format)->content[plt_start], &pos, plt_size, 0/* FIXME*/, address); result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *)); -- cgit v0.11.2-87-g4458