From 4c5f0e1341b094fed40f9e6944134545f971b1eb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 15 Oct 2016 14:12:15 +0200 Subject: Built proper comments for all the Dalvik switch cases. --- ChangeLog | 13 +++ src/analysis/db/item.c | 14 +-- src/analysis/db/item.h | 2 +- src/arch/dalvik/link.c | 185 ++++++++++++++++++++++++++++++++++++---- src/arch/dalvik/pseudo/switch.c | 24 +++--- src/arch/dalvik/pseudo/switch.h | 2 +- 6 files changed, 202 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94120dd..4f75240 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +16-10-15 Cyrille Bagard + + * src/analysis/db/item.c: + * src/analysis/db/item.h: + Ensure all items have their label when it is requested. + + * src/arch/dalvik/link.c: + Build proper comments for all the Dalvik switch cases. + + * src/arch/dalvik/pseudo/switch.c: + * src/arch/dalvik/pseudo/switch.h: + Follow the specifications for the sign of the switch keys and targets. + 16-10-14 Cyrille Bagard * src/analysis/disass/disassembler.c: diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index 62e8ce9..243e97b 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -241,7 +241,7 @@ gint g_db_item_cmp(GDbItem *a, GDbItem *b, bool with) result = cmp_timestamp(&a->created, &b->created); if (result == 0) - result = strcmp(a->label, b->label); + result = strcmp(g_db_item_get_label(a), g_db_item_get_label(b)); return result; @@ -343,8 +343,6 @@ bool g_db_item_recv(GDbItem *item, int fd, int flags) result = G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags); - G_DB_ITEM_GET_CLASS(item)->build_label(item); - return result; } @@ -470,8 +468,14 @@ bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary) * * ******************************************************************************/ -const char *g_db_item_get_label(const GDbItem *item) +const char *g_db_item_get_label(GDbItem *item) { + if (item->label == NULL) + { + G_DB_ITEM_GET_CLASS(item)->build_label(item); + assert(item->label != NULL); + } + return item->label; } @@ -721,8 +725,6 @@ bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count) result = G_DB_ITEM_GET_CLASS(item)->load(item, values, count); - G_DB_ITEM_GET_CLASS(item)->build_label(item); - return result; } diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index f8bb707..afeaed3 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -85,7 +85,7 @@ bool g_db_item_apply(GDbItem *, GLoadedBinary *); bool g_db_item_cancel(GDbItem *, GLoadedBinary *); /* Décrit l'élément de collection en place. */ -const char *g_db_item_get_label(const GDbItem *); +const char *g_db_item_get_label(GDbItem *); /* Fournit l'horodatage associé à l'élément de collection. */ timestamp_t g_db_item_get_timestamp(const GDbItem *); diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c index b698f03..538a57f 100644 --- a/src/arch/dalvik/link.c +++ b/src/arch/dalvik/link.c @@ -26,6 +26,7 @@ #include #include +#include #include @@ -34,6 +35,27 @@ #include "pseudo/switch.h" #include "../target.h" +#include "../../common/extstr.h" + + + +/* Mémorisation des cas rencontrés */ +typedef struct _case_comment +{ + bool valid; /* Entrée utilisable ? */ + + vmpa2t handler; /* Position du code associé */ + + bool is_default; /* Gestion par défaut ? */ + union + { + int32_t key; /* Clef unique */ + int32_t *keys; /* Ensemble de clefs dynamique */ + }; + + size_t count; /* Nombre de clefs conservées */ + +} case_comment; @@ -60,14 +82,20 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * GArchInstruction *switch_ins; /* Instruction de branchements */ const mrange_t *range; /* Zone d'occupation */ const vmpa2t *start_addr; /* Adresse de référentiel */ + const int32_t *keys; /* Conditions de sauts */ + const int32_t *targets; /* Positions relatives liées */ + uint16_t count; /* Taille de ces tableaux */ + case_comment *comments; /* Mémorisation progressive */ vmpa2t def_addr; /* Traitement par défaut */ GArchInstruction *target; /* Ligne visée par la référence*/ - GDbComment *comment; /* Indication sur la condition */ - const uint32_t *keys; /* Conditions de sauts */ - const uint32_t *targets; /* Positions relatives liées */ - uint16_t count; /* Taille de ces tableaux */ - uint16_t i; /* Boucle de parcours */ - char *int_val;/* Valeur en chaîne de carac. */ + case_comment *comment; /* Commentaire à éditer */ + uint16_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + int32_t tmp; /* Sauvegarde temporaire */ + char *msg; /* Indication à imprimer */ + size_t k; /* Boucle de parcours #3 */ + char *int_val; /* Valeur en chaîne de carac. */ + GDbComment *item; /* Indication sur la condition */ assert(g_arch_instruction_count_operands(instr) == 2); @@ -99,6 +127,12 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * start_addr = get_mrange_addr(range); + /* Préparation de l'édition des commentaires */ + + count = g_dalvik_switch_get_data(G_DALVIK_SWITCH_INSTR(switch_ins), &keys, &targets); + + comments = (case_comment *)calloc(1 + count, sizeof(case_comment)); + /* Cas par défaut */ compute_mrange_end_addr(range, &def_addr); @@ -107,10 +141,13 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * if (target != NULL) { - comment = g_db_comment_new_area(&def_addr, BLF_NONE, _("Defaut case"), true); + comment = &comments[0]; + + comment->valid = true; - // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true); - g_proc_context_add_db_item(context, G_DB_ITEM(comment)); + copy_vmpa(&comment->handler, &def_addr); + + comment->is_default = true; g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP); @@ -118,10 +155,6 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * /* Autres cas */ - assert(G_IS_DALVIK_SWITCH_INSTR(switch_ins)); - - count = g_dalvik_switch_get_data(G_DALVIK_SWITCH_INSTR(switch_ins), &keys, &targets); - for (i = 0; i < count; i++) { copy_vmpa(&addr, start_addr); @@ -134,12 +167,59 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * if (target != NULL) { - asprintf(&int_val, _("Case %d"), keys[i]); - comment = g_db_comment_new_area(&addr, BLF_NONE, int_val, true); - free(int_val); + for (j = 0; j < (1 + count); j++) + { + if (!comments[j].valid) + break; + + if (cmp_vmpa(&addr, &comments[j].handler) == 0) + break; + + } + + assert(j < (1 + count)); + + comment = &comments[j]; + + if (!comment->valid) + { + comment->valid = true; + + copy_vmpa(&comment->handler, &addr); + + comment->key = keys[i]; + comment->count = 1; + + } + else + { + if (comment->count == 0) + comment->key = keys[i]; + + if (comment->count == 1) + { + tmp = comment->key; + + comment->keys = (int32_t *)calloc(2, sizeof(int32_t)); + + comment->keys[0] = tmp; + comment->keys[1] = keys[i]; + + comment->count = 2; - // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true); - g_proc_context_add_db_item(context, G_DB_ITEM(comment)); + } + + else + { + comment->count++; + + comment->keys = (int32_t *)realloc(comment->keys, comment->count * sizeof(int32_t)); + + comment->keys[comment->count - 1] = keys[i]; + + } + + } g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP); @@ -147,6 +227,75 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * } + /* Edition des commentaires et nettoyage */ + + for (j = 0; j < (1 + count); j++) + { + comment = &comments[j]; + + if (!comment->valid) + break; + + switch (comment->count) + { + case 0: + msg = NULL; + break; + + case 1: + asprintf(&msg, _("Case %d"), comment->key); + break; + + default: + + msg = NULL; + + /** + * Les spécifications indiquent que les clefs sont triées. + * Donc nul besoin de s'occuper de leur ordre ici. + */ + + for (k = 0; k < comment->count; k++) + { + if (k > 0) + msg = stradd(msg, COMMENT_LINE_SEP); + + asprintf(&int_val, _("Case %d:"), comment->keys[k]); + msg = stradd(msg, int_val); + free(int_val); + + } + + break; + + } + + if (comment->is_default) + { + if (msg == NULL) + msg = strdup(_("Defaut case:")); + else + { + msg = stradd(msg, COMMENT_LINE_SEP); + msg = stradd(msg, _("Defaut case")); + } + + } + + item = g_db_comment_new_area(&comment->handler, BLF_NONE, msg, true); + + g_db_item_set_volatile(G_DB_ITEM(item), true); + g_proc_context_add_db_item(context, G_DB_ITEM(item)); + + free(msg); + + if (comment->count > 1) + free(comment->keys); + + } + + free(comments); + } } diff --git a/src/arch/dalvik/pseudo/switch.c b/src/arch/dalvik/pseudo/switch.c index fd7e442..70afb3e 100644 --- a/src/arch/dalvik/pseudo/switch.c +++ b/src/arch/dalvik/pseudo/switch.c @@ -39,8 +39,8 @@ struct _GDalvikSwitchInstr uint16_t switch_size; /* Taille du switch considéré */ - uint32_t *keys; /* Table de clefs */ - uint32_t *targets; /* Table des sauts relatifs */ + int32_t *keys; /* Table de clefs */ + int32_t *targets; /* Table des sauts relatifs */ }; @@ -194,9 +194,9 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, goto gdsin_bad; if (ident != DPO_PACKED_SWITCH) - consumed = (1 + result->switch_size) * sizeof(uint32_t); + consumed = (1 + result->switch_size) * sizeof(int32_t); else - consumed = (2 * result->switch_size) * sizeof(uint32_t); + consumed = (2 * result->switch_size) * sizeof(int32_t); if (!g_dalvik_context_register_switch_data(ctx, pos, consumed)) goto gdsin_bad; @@ -229,24 +229,24 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinContent *content, const vmpa2t *pos) { vmpa2t iter; /* Position modifiable */ - uint32_t first_key; /* Première clef */ + int32_t first_key; /* Première clef */ uint16_t i; /* Boucle de parcours */ - instr->keys = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t)); - instr->targets = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t)); + instr->keys = (int32_t *)calloc(instr->switch_size, sizeof(int32_t)); + instr->targets = (int32_t *)calloc(instr->switch_size, sizeof(int32_t)); copy_vmpa(&iter, pos); if (G_DALVIK_INSTRUCTION(instr)->ptype == DPO_PACKED_SWITCH) { - if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &first_key)) + if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &first_key)) goto gdsdd_bad; for (i = 0; i < instr->switch_size; i++) { instr->keys[i] = first_key + i; - if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i])) + if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->targets[i])) goto gdsdd_bad; } @@ -256,11 +256,11 @@ static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinCon else { for (i = 0; i < instr->switch_size; i++) - if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->keys[i])) + if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->keys[i])) goto gdsdd_bad; for (i = 0; i < instr->switch_size; i++) - if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i])) + if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->targets[i])) goto gdsdd_bad; } @@ -288,7 +288,7 @@ static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinCon * * ******************************************************************************/ -uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const uint32_t **keys, const uint32_t **targets) +uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const int32_t **keys, const int32_t **targets) { if (keys != NULL) *keys = instr->keys; diff --git a/src/arch/dalvik/pseudo/switch.h b/src/arch/dalvik/pseudo/switch.h index ae52758..b0fb1b2 100644 --- a/src/arch/dalvik/pseudo/switch.h +++ b/src/arch/dalvik/pseudo/switch.h @@ -56,7 +56,7 @@ GType g_dalvik_switch_instr_get_type(void); GArchInstruction *g_dalvik_switch_instr_new(uint16_t, GDalvikContext *, const GBinContent *, vmpa2t *); /* Fournit les données associées à un branchement Dalvik. */ -uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *, const uint32_t **, const uint32_t **); +uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *, const int32_t **, const int32_t **); -- cgit v0.11.2-87-g4458