diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/disass/links.c | 6 | ||||
-rw-r--r-- | src/arch/instruction.h | 1 | ||||
-rw-r--r-- | src/format/dex/dex-int.c | 273 | ||||
-rwxr-xr-x | src/format/dex/dex-int.h | 23 | ||||
-rwxr-xr-x | src/format/dex/dex_def.h | 109 | ||||
-rw-r--r-- | src/gtkext/graph/layout.c | 1 |
6 files changed, 341 insertions, 72 deletions
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 0ba3fc6..df0c77f 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -108,9 +108,9 @@ void establish_links_between_lines(GArchInstruction *list, GBinRoutine **routine default: /** - * Note pour GCC : à ce stade du désassemblage, ILT_CATCH_EXCEPTION - * ne peut être présente, car ne provenant que de greffons. - * Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas. + * Note pour GCC : à ce stade du désassemblage, ILT_CASE_JUMP et + * ILT_CATCH_EXCEPTION ne peuvent être présentes, car ne provenant + * que de greffons. Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas. */ break; diff --git a/src/arch/instruction.h b/src/arch/instruction.h index ae0bd68..8963284 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -45,6 +45,7 @@ typedef enum _InstructionLinkType ILT_NONE, /* Aucune instruction visée */ ILT_EXEC_FLOW, /* Raccord attendu entre blocs */ ILT_JUMP, /* Saut inconditionnel */ + ILT_CASE_JUMP, /* Saut suite à aiguillage */ ILT_JUMP_IF_TRUE, /* Saut conditionnel (si vrai) */ ILT_JUMP_IF_FALSE, /* Saut conditionnel (si faux) */ ILT_CALL, /* Appel d'une fonction */ diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c index 200b01f..58211e5 100644 --- a/src/format/dex/dex-int.c +++ b/src/format/dex/dex-int.c @@ -27,11 +27,80 @@ #include <malloc.h> +#include "../../arch/dalvik/instruction-def.h" #include "../../common/endianness.h" /* ---------------------------------------------------------------------------------- */ +/* DESCRIPTION DU FORMAT DALVIK */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* header = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de programme DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + size_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) + result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + + for (i = 0; i < 20 && result; i++) + result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* ELEMENTS DE TABLE DES CONSTANTES */ /* ---------------------------------------------------------------------------------- */ @@ -840,18 +909,87 @@ void reset_dex_code_item(code_item *item) +/* ---------------------------------------------------------------------------------- */ +/* AIGUILLAGES DIVERS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* packed = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage compact. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_packed_switch(const GDexFormat *format, off_t *pos, packed_switch *packed) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + packed->targets = NULL; + + result &= read_u16(&packed->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&packed->size, content, pos, length, SRE_LITTLE); + result &= read_u32(&packed->first_key, content, pos, length, SRE_LITTLE); + if (result && packed->size > 0) + { + packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t)); + + for (i = 0; i < packed->size && result; i++) + result &= read_u32(&packed->targets[i], content, pos, length, SRE_LITTLE); + + } + + if (!result) + reset_dex_packed_switch(packed); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : packed = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +void reset_dex_packed_switch(packed_switch *packed) +{ + if (packed->targets != NULL) + free(packed->targets); +} /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * pos = position de début de lecture. [OUT] * -* header = structure lue à retourner. [OUT] * +* sparse = structure lue à retourner. [OUT] * * * -* Description : Procède à la lecture d'une en-tête de programme DEX. * +* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. * * * * Retour : Bilan de l'opération. * * * @@ -859,54 +997,131 @@ void reset_dex_code_item(code_item *item) * * ******************************************************************************/ -bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch *sparse) { bool result; /* Bilan à retourner */ const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ - size_t i; /* Boucle de parcours */ + uint16_t i; /* Boucle de parcours */ result = true; content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; - for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) - result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + sparse->keys = NULL; + sparse->targets = NULL; - result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->size, content, pos, length, SRE_LITTLE); - for (i = 0; i < 20 && result; i++) - result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + if (result && sparse->size > 0) + { + sparse->keys = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); + sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); - result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->targets[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + } + + if (!result) + reset_dex_sparse_switch(sparse); return result; } +/****************************************************************************** +* * +* Paramètres : sparse = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_sparse_switch(sparse_switch *sparse) +{ + if (sparse->keys != NULL) + free(sparse->keys); + + if (sparse->targets != NULL) + free(sparse->targets); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* dsxitch = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage Dex interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_switch(const GDexFormat *format, off_t *pos, dex_switch *dswitch) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t ident; /* Pseudo-code d'identification*/ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u16(&ident, content, (off_t []) { *pos }, length, SRE_LITTLE); + + if (result) + { + if (ident == DPO_PACKED_SWITCH) + result = read_dex_packed_switch(format, pos, (packed_switch *)dswitch); + + else if (ident == DPO_SPARSE_SWITCH) + result = read_dex_sparse_switch(format, pos, (sparse_switch *)dswitch); + + else + result = false; + } + + return result; +} + +/****************************************************************************** +* * +* Paramètres : dswitch = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_switch(dex_switch *dswitch) +{ + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + reset_dex_packed_switch((packed_switch *)dswitch); + else + reset_dex_sparse_switch((sparse_switch *)dswitch); + +} diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h index 6a153c1..55a48b5 100755 --- a/src/format/dex/dex-int.h +++ b/src/format/dex/dex-int.h @@ -68,6 +68,13 @@ size_t g_dex_format_count_classes(const GDexFormat *); GDexClass *g_dex_format_get_class(const GDexFormat *, size_t); +/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ + + +/* Procède à la lecture d'une en-tête de programme DEX. */ +bool read_dex_header(const GDexFormat *, off_t *, dex_header *); + + /* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */ @@ -147,14 +154,26 @@ void reset_dex_code_item(code_item *); +/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */ -/* Procède à la lecture d'une en-tête de programme DEX. */ -bool read_dex_header(const GDexFormat *, off_t *, dex_header *); +/* Procède à la lecture d'un contenu d'aiguillage compact. */ +bool read_dex_packed_switch(const GDexFormat *, off_t *, packed_switch *); + +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_packed_switch(packed_switch *); +/* Procède à la lecture d'un contenu d'aiguillage dispersé. */ +bool read_dex_sparse_switch(const GDexFormat *, off_t *, sparse_switch *); +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_sparse_switch(sparse_switch *); +/* Procède à la lecture d'un contenu d'aiguillage Dex interne. */ +bool read_dex_switch(const GDexFormat *, off_t *, dex_switch *); +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_switch(dex_switch *); diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h index d21ac15..eee3574 100755 --- a/src/format/dex/dex_def.h +++ b/src/format/dex/dex_def.h @@ -29,6 +29,55 @@ +/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ + + +/* Identifiant magique "dex\n035\0" */ +#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00" +#define DEX_FILE_MAGIC_LEN 8 + +/* Types de boutisme */ +#define ENDIAN_CONSTANT 0x12345678 +#define REVERSE_ENDIAN_CONSTANT 0x78563412 + +/* Indice non valide */ +#define NO_INDEX 0xffffffff + + +/* En-tête de tout programe Dex */ +typedef struct _dex_header +{ + uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */ + + uint32_t checksum; /* Somme de contrôle adler32 */ + uint8_t signature[20]; /* Emprunte SHA-1 du reste */ + uint32_t file_size; /* Taille du fichier */ + uint32_t header_size; /* Taille de cette en-tête */ + + uint32_t endian_tag; /* Boutisme du fichier */ + + uint32_t link_size; /* Taille de section 'liaisons'*/ + uint32_t link_off; /* Position de ladite section */ + uint32_t map_off; /* Position de la cartographie */ + uint32_t string_ids_size; /* Nombre de chaînes de carac. */ + uint32_t string_ids_off; /* Position de cette liste */ + uint32_t type_ids_size; /* Nom d'identifiant de type */ + uint32_t type_ids_off; /* Position de la liste */ + uint32_t proto_ids_size; /* Nombre de prototypes */ + uint32_t proto_ids_off; /* Position de la liste */ + uint32_t field_ids_size; /* Nombre de champs */ + uint32_t field_ids_off; /* Position de la liste */ + uint32_t method_ids_size; /* Nombre de méthodes */ + uint32_t method_ids_off; /* Position de la liste */ + uint32_t class_defs_size; /* Nombre de classes déclarées */ + uint32_t class_defs_off; /* Position de la liste */ + uint32_t data_size; /* Taille des données */ + uint32_t data_off; /* Début des données */ + +} dex_header; + + + /* -------------------------- CONSTANTES POUR DEX DIVERSES -------------------------- */ @@ -240,52 +289,36 @@ typedef struct _code_item -/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ - +/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */ -/* Identifiant magique "dex\n035\0" */ -#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00" -#define DEX_FILE_MAGIC_LEN 8 - -/* Types de boutisme */ -#define ENDIAN_CONSTANT 0x12345678 -#define REVERSE_ENDIAN_CONSTANT 0x78563412 -/* Indice non valide */ -#define NO_INDEX 0xffffffff +/* Aiguillage compressé */ +typedef struct _packed_switch +{ + uint16_t ident; /* Pseudo-code d'identification*/ + uint16_t size; /* Nombre d'entrées */ + uint32_t first_key; /* Première et plus petite clef*/ + uint32_t *targets; /* Cibles relatives */ +} packed_switch; -/* En-tête de tout programe Dex */ -typedef struct _dex_header +/* Aiguillage dispersé */ +typedef struct _sparse_switch { - uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */ - - uint32_t checksum; /* Somme de contrôle adler32 */ - uint8_t signature[20]; /* Emprunte SHA-1 du reste */ - uint32_t file_size; /* Taille du fichier */ - uint32_t header_size; /* Taille de cette en-tête */ + uint16_t ident; /* Pseudo-code d'identification*/ + uint16_t size; /* Nombre d'entrées */ + uint32_t *keys; /* Clefs valeureuses */ + uint32_t *targets; /* Cibles relatives */ - uint32_t endian_tag; /* Boutisme du fichier */ +} sparse_switch; - uint32_t link_size; /* Taille de section 'liaisons'*/ - uint32_t link_off; /* Position de ladite section */ - uint32_t map_off; /* Position de la cartographie */ - uint32_t string_ids_size; /* Nombre de chaînes de carac. */ - uint32_t string_ids_off; /* Position de cette liste */ - uint32_t type_ids_size; /* Nom d'identifiant de type */ - uint32_t type_ids_off; /* Position de la liste */ - uint32_t proto_ids_size; /* Nombre de prototypes */ - uint32_t proto_ids_off; /* Position de la liste */ - uint32_t field_ids_size; /* Nombre de champs */ - uint32_t field_ids_off; /* Position de la liste */ - uint32_t method_ids_size; /* Nombre de méthodes */ - uint32_t method_ids_off; /* Position de la liste */ - uint32_t class_defs_size; /* Nombre de classes déclarées */ - uint32_t class_defs_off; /* Position de la liste */ - uint32_t data_size; /* Taille des données */ - uint32_t data_off; /* Début des données */ +/* Manipulation interne */ +typedef union _dex_switch +{ + packed_switch packed; /* Modèle compact */ + sparse_switch sparse; /* Modèle dispersé */ -} dex_header; +} dex_switch; diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 3a2f4e3..45e3a82 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -169,6 +169,7 @@ static char *complete_graph_links(const GtkGraphView *view, GtkViewPanel **views { case ILT_EXEC_FLOW: case ILT_JUMP: + case ILT_CASE_JUMP: snprintf(cmd, LINKS_DESC_LEN, "_%p:s -> _%p:n [ltail=cluster_%p, lhead=cluster_%p];\n", views[i], views[k], views[i], views[k]); |