diff options
Diffstat (limited to 'plugins/java')
-rw-r--r-- | plugins/java/Makefile.am | 29 | ||||
-rw-r--r-- | plugins/java/attribute.c | 717 | ||||
-rw-r--r-- | plugins/java/attribute.h | 40 | ||||
-rw-r--r-- | plugins/java/e_java.c | 284 | ||||
-rw-r--r-- | plugins/java/e_java.h | 49 | ||||
-rw-r--r-- | plugins/java/field.c | 158 | ||||
-rw-r--r-- | plugins/java/field.h | 40 | ||||
-rw-r--r-- | plugins/java/java-int.c | 92 | ||||
-rw-r--r-- | plugins/java/java-int.h | 66 | ||||
-rw-r--r-- | plugins/java/java.c | 508 | ||||
-rw-r--r-- | plugins/java/java.h | 63 | ||||
-rw-r--r-- | plugins/java/java_def.h | 418 | ||||
-rw-r--r-- | plugins/java/method.c | 187 | ||||
-rw-r--r-- | plugins/java/method.h | 44 | ||||
-rw-r--r-- | plugins/java/pool.c | 474 | ||||
-rw-r--r-- | plugins/java/pool.h | 56 |
16 files changed, 3225 insertions, 0 deletions
diff --git a/plugins/java/Makefile.am b/plugins/java/Makefile.am new file mode 100644 index 0000000..0e40bfa --- /dev/null +++ b/plugins/java/Makefile.am @@ -0,0 +1,29 @@ + +noinst_LTLIBRARIES = libformatjava.la + +libformatjava_la_SOURCES = \ + java-int.h java-int.c \ + java.h java.c \ + java_def.h \ + pool.h pool.c + + +# libformatjava_la_SOURCES = \ +# attribute.h attribute.c \ +# e_java.h e_java.c \ +# field.h field.c \ +# java-int.h \ +# method.h method.c \ +# pool.h pool.c + +libformatjava_la_LDFLAGS = + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=%) + +dev_HEADERS = $(libformatjava_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/java/attribute.c b/plugins/java/attribute.c new file mode 100644 index 0000000..3e04ea9 --- /dev/null +++ b/plugins/java/attribute.c @@ -0,0 +1,717 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * attribute.c - manipulation des attributs Java + * + * Copyright (C) 2009-2017 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 "attribute.h" + + +#include <malloc.h> +#include <string.h> + + +#include "java-int.h" +#include "pool.h" +#include "../../common/endianness.h" +#include "../../panel/log.h" + + + +#define _(str) str + + + +/* Charge les propriétés d'un attribut quelconque. */ +bool load_java_attribute(java_format *, java_attribute *, off_t *); + +/* Décharge les propriétés d'un attribut quelconque. */ +void unload_java_attribute(java_format *, java_attribute *); + +/* Charge les propriétés d'un attribut de valeur constante. */ +bool load_java_const_value_attribute(java_format *, const_value_attrib *, off_t *); + +/* Charge les propriétés d'un attribut de code. */ +bool load_java_code_attribute(java_format *, code_attrib *, off_t *); + +/* Décharge les propriétés d'un attribut de code. */ +void unload_java_code_attribute(java_format *, code_attrib *); + +/*Charge les propriétés d'un attribut d'exceptions lançables. */ +bool load_java_exceptions_attribute(java_format *, exceptions_attrib *, off_t *); + +/* Décharge les propriétés d'un attribut d'exceptions lançables. */ +void unload_java_exceptions_attribute(java_format *, exceptions_attrib *); + +/* Charge les propriétés d'un attribut de classes internes. */ +bool load_java_inner_classes_attribute(java_format *, inner_classes_attrib *, off_t *); + +/* Décharge les propriétés d'un attribut de classes internes. */ +void unload_java_inner_classes_attribute(java_format *, inner_classes_attrib *); + +/* Charge les propriétés d'un attribut de fichier source. */ +bool load_java_source_file_attribute(java_format *, source_file_attrib *, off_t *); + +/* Charge les propriétés d'un attribut de correspondance. */ +bool load_java_line_number_attribute(java_format *, line_number_attrib *, off_t *); + +/* Décharge les propriétés d'un attribut de correspondance. */ +void unload_java_line_number_attribute(java_format *, line_number_attrib *); + +/* Charge les propriétés d'un attribut de variables locales. */ +bool load_java_local_variables_attribute(java_format *, local_variables_attrib *, off_t *); + +/* Décharge les propriétés d'un attribut de variables locales. */ +void unload_java_local_variables_attribute(java_format *, local_variables_attrib *); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* pos = point de lecture à faire évoluer. [OUT] * +* attributes = tableau des attributs chargés. [OUT] * +* count = nombre d'éléments à charger. [OUT] * +* * +* Description : Charge les attribus d'un élément d'un binaire Java. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_attributes(java_format *format, off_t *pos, java_attribute **attributes, uint16_t *count) +{ + bool result; /* Bilan à remonter */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(count, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + if (!result) return false; + + if (*count > 0) + { + *attributes = (java_attribute *)calloc(*count, sizeof(java_attribute)); + + for (i = 0; i < *count && result; i++) + result = load_java_attribute(format, &(*attributes)[i], pos); + + if (!result) + unload_java_attributes(format, *attributes, *count); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à libérer. * +* attributes = tableau des attributs à décharger. * +* count = nombre d'éléments à décharger. * +* * +* Description : Décharge les attribus d'un élément d'un binaire Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_attributes(java_format *format, java_attribute *attributes, uint16_t count) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < count; i++) + unload_java_attribute(format, &attributes[i]); + + free(attributes); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut quelconque. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_attribute(java_format *format, java_attribute *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t index; /* Indice du nom assimilé */ + const char *name; /* Version humainement lisible */ + uint32_t attrib_length; /* Taille de la charge utile */ + off_t saved_pos; /* Conservation de la position */ + + result = read_u16(&index, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + result &= get_java_pool_ut8_string(format, index, &name); + + if (result) + { + result = read_u32(&attrib_length, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + saved_pos = *pos; + + if (result && strcmp("ConstantValue", name) == 0) + { + attrib->type = JAT_CONSTANT_VALUE; + result = load_java_const_value_attribute(format, &attrib->info.const_value, pos); + } + + else if (result && strcmp("Code", name) == 0) + { + attrib->type = JAT_CODE; + result = load_java_code_attribute(format, &attrib->info.code, pos); + } + + else if (result && strcmp("Exceptions", name) == 0) + { + attrib->type = JAT_EXCEPTIONS; + result = load_java_exceptions_attribute(format, &attrib->info.exceptions, pos); + } + + else if (result && strcmp("InnerClasses", name) == 0) + { + attrib->type = JAT_INNER_CLASSES; + result = load_java_inner_classes_attribute(format, &attrib->info.inner_classes, pos); + } + + else if (result && strcmp("Synthetic", name) == 0) + attrib->type = JAT_SYNTHETIC; + + else if (result && strcmp("SourceFile", name) == 0) + { + attrib->type = JAT_LINE_NUMBER; + result = load_java_source_file_attribute(format, &attrib->info.source_file, pos); + } + + else if (result && strcmp("LineNumberTable", name) == 0) + { + attrib->type = JAT_SOURCE_FILE; + result = load_java_line_number_attribute(format, &attrib->info.line_number, pos); + } + + else if (result && strcmp("LocalVariableTable", name) == 0) + { + attrib->type = JAT_LOCAL_VARIABLES; + result = load_java_local_variables_attribute(format, &attrib->info.local_vars, pos); + } + + else if (result && strcmp("Deprecated", name) == 0) + attrib->type = JAT_DEPRECATED; + + else if (result) + { + result = false; + log_variadic_message(LMT_BAD_BINARY, _("Attribute name not supported: '%s'"), name); + } + + if (result && attrib_length != (*pos - saved_pos)) + log_variadic_message(LMT_BAD_BINARY, _("Size indication of the attribute '%s' not verified: %d vs %d"), + name, attrib_length, *pos - saved_pos); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer. * +* * +* Description : Décharge les propriétés d'un attribut quelconque. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_attribute(java_format *format, java_attribute *attrib) +{ + switch (attrib->type) + { + case JAT_NONE: + break; + + case JAT_CONSTANT_VALUE: + break; + + case JAT_CODE: + unload_java_code_attribute(format, &attrib->info.code); + break; + + case JAT_EXCEPTIONS: + unload_java_exceptions_attribute(format, &attrib->info.exceptions); + break; + + case JAT_INNER_CLASSES: + unload_java_inner_classes_attribute(format, &attrib->info.inner_classes); + break; + + case JAT_SYNTHETIC: + break; + + case JAT_SOURCE_FILE: + break; + + case JAT_LINE_NUMBER: + unload_java_line_number_attribute(format, &attrib->info.line_number); + break; + + case JAT_LOCAL_VARIABLES: + unload_java_local_variables_attribute(format, &attrib->info.local_vars); + break; + + case JAT_DEPRECATED: + break; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de valeur constante. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_const_value_attribute(java_format *format, const_value_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = read_u16(&attrib->const_value_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de code. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_code_attribute(java_format *format, code_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&attrib->max_stack, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->max_locals, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u32(&attrib->code_length, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= ((*pos + attrib->code_length) <= EXE_FORMAT(format)->length); + + if (result) + { + attrib->content = *pos; + *pos += attrib->code_length; + } + + result &= read_u16(&attrib->exceptions_count, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result && attrib->exceptions_count > 0) + { + attrib->exceptions = (code_exception *)calloc(attrib->exceptions_count, sizeof(code_exception)); + + for (i = 0; i < attrib->exceptions_count && result; i++) + { + result &= read_u16(&attrib->exceptions[i].start_pc, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->exceptions[i].end_pc, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->exceptions[i].handler_pc, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->exceptions[i].catch_type, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + } + + } + + result &= load_java_attributes(format, pos, &attrib->attributes, &attrib->attributes_count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer de la mémoire. * +* * +* Description : Décharge les propriétés d'un attribut de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_code_attribute(java_format *format, code_attrib *attrib) +{ + if (attrib->exceptions != NULL) + free(attrib->exceptions); + + if (attrib->attributes != NULL) + unload_java_attributes(format, attrib->attributes, attrib->attributes_count); + +} + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut d'exceptions lançables. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_exceptions_attribute(java_format *format, exceptions_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&attrib->throw_count, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result && attrib->throw_count > 0) + { + attrib->throw = (uint16_t *)calloc(attrib->throw_count, sizeof(uint16_t)); + + for (i = 0; i < attrib->throw_count && result; i++) + result &= read_u16(&attrib->throw[i], EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer de la mémoire. * +* * +* Description : Décharge les propriétés d'un attribut d'exceptions lançables.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_exceptions_attribute(java_format *format, exceptions_attrib *attrib) +{ + if (attrib->throw != NULL) + free(attrib->throw); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de classes internes. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_inner_classes_attribute(java_format *format, inner_classes_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&attrib->classes_count, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result && attrib->classes_count > 0) + { + attrib->classes = (inner_class *)calloc(attrib->classes_count, sizeof(inner_class)); + + for (i = 0; i < attrib->classes_count && result; i++) + { + result &= read_u16(&attrib->classes[i].inner_class_info_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->classes[i].outer_class_info_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->classes[i].inner_name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16((uint16_t *)&attrib->classes[i].access, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer de la mémoire. * +* * +* Description : Décharge les propriétés d'un attribut de classes internes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_inner_classes_attribute(java_format *format, inner_classes_attrib *attrib) +{ + if (attrib->classes != NULL) + free(attrib->classes); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de fichier source. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_source_file_attribute(java_format *format, source_file_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = read_u16(&attrib->source_file_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de correspondance. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_line_number_attribute(java_format *format, line_number_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&attrib->lines_count, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result && attrib->lines_count > 0) + { + attrib->lines = (pc_and_line *)calloc(attrib->lines_count, sizeof(pc_and_line)); + + for (i = 0; i < attrib->lines_count && result; i++) + { + result &= read_u16(&attrib->lines[i].start_pc, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->lines[i].number, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer de la mémoire. * +* * +* Description : Décharge les propriétés d'un attribut de correspondance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_line_number_attribute(java_format *format, line_number_attrib *attrib) +{ + if (attrib->lines != NULL) + free(attrib->lines); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un attribut de variables locales. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_local_variables_attribute(java_format *format, local_variables_attrib *attrib, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&attrib->vars_count, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result && attrib->vars_count > 0) + { + attrib->vars = (local_variable *)calloc(attrib->vars_count, sizeof(local_variable)); + + for (i = 0; i < attrib->vars_count && result; i++) + { + result &= read_u16(&attrib->vars[i].start_pc, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->vars[i].length, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->vars[i].name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->vars[i].descriptor_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&attrib->vars[i].index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* attrib = élément à libérer de la mémoire. * +* * +* Description : Décharge les propriétés d'un attribut de variables locales. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_local_variables_attribute(java_format *format, local_variables_attrib *attrib) +{ + if (attrib->vars != NULL) + free(attrib->vars); + +} diff --git a/plugins/java/attribute.h b/plugins/java/attribute.h new file mode 100644 index 0000000..155aa7e --- /dev/null +++ b/plugins/java/attribute.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * attribute.h - prototypes pour la manipulation des attributs Java + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_ATTRIBUTE_H +#define _FORMAT_JAVA_ATTRIBUTE_H + + +#include "e_java.h" + + + +/* Charge les attribus d'un élément d'un binaire Java. */ +bool load_java_attributes(java_format *, off_t *, java_attribute **, uint16_t *); + +/* Décharge les attribus d'un élément d'un binaire Java. */ +void unload_java_attributes(java_format *, java_attribute *, uint16_t); + + + +#endif /* _FORMAT_JAVA_ATTRIBUTE_H */ diff --git a/plugins/java/e_java.c b/plugins/java/e_java.c new file mode 100644 index 0000000..7d05fa9 --- /dev/null +++ b/plugins/java/e_java.c @@ -0,0 +1,284 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * e_java.c - support du format Java + * + * Copyright (C) 2009-2017 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 "e_java.h" + + +#include <malloc.h> +#include <string.h> + + +#include "attribute.h" +#include "field.h" +#include "java-int.h" +#include "method.h" +#include "pool.h" +#include "../../common/endianness.h" + + + + +/* Indique le type d'architecture visée par le format. */ +FormatTargetMachine get_java_target_machine(const java_format *); + + + +/* Fournit les références aux zones de code à analyser. */ +bin_part **get_java_default_code_parts(const java_format *, size_t *); + + +/* Fournit le prototype de toutes les routines détectées. */ +GBinRoutine **get_all_java_routines(const java_format *, size_t *); + + + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool java_is_matching(const uint8_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + + result = false; + + if (length >= 4) + result = (strncmp((const char *)content, "\xca\xfe\xba\xbe", 4) == 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge une nouvelle classe Java. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +exe_format *load_java(const uint8_t *content, off_t length) +{ + java_format *result; /* Adresse à retourner */ + off_t pos; /* Point d'analyse */ + uint32_t magic; /* Identifiant Java */ + uint16_t i; /* Boucle de parcours */ + + result = (java_format *)calloc(1, sizeof(java_format)); + + EXE_FORMAT(result)->content = content; + EXE_FORMAT(result)->length = length; + + EXE_FORMAT(result)->get_target_machine = (get_target_machine_fc)get_java_target_machine; + EXE_FORMAT(result)->get_def_parts = (get_def_parts_fc)get_java_default_code_parts; + EXE_FORMAT(result)->get_all_routines = (get_all_routines_fc)get_all_java_routines; + + pos = 0; + + if (!read_u32(&magic, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->minor_version, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->major_version, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!load_java_pool(result, &pos)) + goto ldj_error; + + if (!read_u16((uint16_t *)&result->access, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->this_class, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->super_class, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->interfaces_count, content, &pos, length, SRE_BIG)) + goto ldj_error; + + for (i = 0; i < result->interfaces_count; i++) + if (!read_u16(&result->interfaces[i], content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!load_java_fields(result, &pos)) + goto ldj_error; + + if (!load_java_methods(result, &pos)) + goto ldj_error; + + if (!load_java_attributes(result, &pos, &result->attributes, &result->attributes_count)) + goto ldj_error; + + return EXE_FORMAT(result); + + ldj_error: + + unload_java(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à supprimer. * +* * +* Description : Efface la prise en charge une nouvelle classe Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java(java_format *format) +{ + if (format->pool_len > 0) + unload_java_pool(format); + + if (format->interfaces_count > 0) + free(format->interfaces); + + if (format->fields_count > 0) + unload_java_fields(format); + + if (format->methods_count > 0) + unload_java_methods(format); + + if (format->attributes_count > 0) + unload_java_attributes(format, format->attributes, format->attributes_count); + + free(format); + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +FormatTargetMachine get_java_target_machine(const java_format *format) +{ + return FTM_JVM; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones de code à analyser. * +* * +* Retour : Zones de code à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_part **get_java_default_code_parts(const java_format *format, size_t *count) +{ + bin_part **result; /* Tableau à retourner */ + uint16_t i; /* Boucle de parcours */ + off_t offset; /* Position physique */ + off_t size; /* Taille de la partie */ + bin_part *part; /* Partie à intégrer à la liste*/ + + result = NULL; + *count = 0; + + for (i = 0; i < format->methods_count; i++) + if (find_java_method_code_part(&format->methods[i], &offset, &size)) + { + part = create_bin_part(); + + set_bin_part_values(part, offset, size, offset); + + result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); + result[*count - 1] = part; + + } + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = taille du tableau créé. [OUT] * +* * +* Description : Fournit le prototype de toutes les routines détectées. * +* * +* Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine **get_all_java_routines(const java_format *format, size_t *count) +{ + *count = 0; + + return NULL; + +} diff --git a/plugins/java/e_java.h b/plugins/java/e_java.h new file mode 100644 index 0000000..65befbd --- /dev/null +++ b/plugins/java/e_java.h @@ -0,0 +1,49 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * e_java.h - prototypes pour le support du format Java + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_E_JAVA_H +#define _FORMAT_JAVA_E_JAVA_H + + +#include "../exe_format.h" + + +/* Description des attributs Java */ +typedef struct _java_attribute java_attribute; + +/* Description du format Java */ +typedef struct _java_format java_format; + + +/* Indique si le format peut être pris en charge ici. */ +bool java_is_matching(const uint8_t *, off_t); + +/* Prend en charge une nouvelle classe Java. */ +exe_format *load_java(const uint8_t *, off_t); + +/* Efface la prise en charge une nouvelle classe Java. */ +void unload_java(java_format *); + + + +#endif /* _FORMAT_JAVA_E_JAVA_H */ diff --git a/plugins/java/field.c b/plugins/java/field.c new file mode 100644 index 0000000..e7df342 --- /dev/null +++ b/plugins/java/field.c @@ -0,0 +1,158 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.c - gestion des champs Java + * + * Copyright (C) 2009-2017 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 "field.h" + + +#include <malloc.h> + + +#include "attribute.h" +#include "java-int.h" +#include "../../common/endianness.h" + + + +/* Charge les propriétés d'un champ de classe. */ +bool load_java_field(java_format *, java_field *, off_t *); + +/* Décharge les propriétés d'un champ de classe. */ +void unload_java_field(java_format *, java_field *); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les champs d'un binaire Java. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_fields(java_format *format, off_t *pos) +{ + bool result; /* Bilan à remonter */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&format->fields_count, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + if (!result) return false; + + if (format->fields_count > 0) + { + format->fields = (java_field *)calloc(format->fields_count, sizeof(java_field)); + + for (i = 0; i < format->fields_count && result; i++) + result = load_java_field(format, &format->fields[i], pos); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à vider. * +* * +* Description : Décharge les champs d'un binaire Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_fields(java_format *format) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < format->fields_count; i++) + unload_java_field(format, &format->fields[i]); + + free(format->fields); + + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* field = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'un champ de classe. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_field(java_format *format, java_field *field, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = read_u16((uint16_t *)&field->access, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&field->name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&field->descriptor_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= load_java_attributes(format, pos, + &field->attributes, &field->attributes_count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* field = élément à libérer. * +* * +* Description : Décharge les propriétés d'un champ de classe. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_field(java_format *format, java_field *field) +{ + if (field->attributes_count > 0) + unload_java_attributes(format, field->attributes, field->attributes_count); + +} diff --git a/plugins/java/field.h b/plugins/java/field.h new file mode 100644 index 0000000..686c13f --- /dev/null +++ b/plugins/java/field.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.h - prototypes pour la gestion des champs Java + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_FIELD_H +#define _FORMAT_JAVA_FIELD_H + + +#include "e_java.h" + + + +/* Charge les champs d'un binaire Java. */ +bool load_java_fields(java_format *, off_t *); + +/* Décharge les champs d'un binaire Java. */ +void unload_java_fields(java_format *); + + + +#endif /* _FORMAT_JAVA_FIELD_H */ diff --git a/plugins/java/java-int.c b/plugins/java/java-int.c new file mode 100644 index 0000000..c1c8aa5 --- /dev/null +++ b/plugins/java/java-int.c @@ -0,0 +1,92 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java-int.c - structures internes du format Java + * + * Copyright (C) 2010-2017 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 "java-int.h" + + +#include "pool.h" +#include "../../common/endianness.h" + + + +/****************************************************************************** +* * +* 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 Java. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_java_header(const GJavaFormat *format, off_t *pos, java_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint32_t magic; /* Identifiant Java */ + size_t i; /* Boucle de parcours */ + + result = true; + + content = NULL; //G_BIN_FORMAT(format)->content; + length = 0; //G_BIN_FORMAT(format)->length; + + result &= read_u32(&magic, content, pos, length, SRE_BIG); + printf("magic :: 0x%08x\n", magic); + result &= read_u16(&header->minor_version, content, pos, length, SRE_BIG); + result &= read_u16(&header->major_version, content, pos, length, SRE_BIG); + + printf("avant :: %d\n", result); + + result &= load_java_pool(format, pos); + + printf("après :: %d\n", result); + + result &= read_u16((uint16_t *)&header->access, content, pos, length, SRE_BIG); + result &= read_u16(&header->this_class, content, pos, length, SRE_BIG); + result &= read_u16(&header->super_class, content, pos, length, SRE_BIG); + result &= read_u16(&header->interfaces_count, content, pos, length, SRE_BIG); + +/* for (i = 0; i < header->interfaces_count; i++) */ +/* result &= read_u16(&header->interfaces[i], content, pos, length, SRE_BIG)) */ +/* goto ldj_error; */ + +/* result &= load_java_fields(result, pos); */ + +/* result &= load_java_methods(result, pos); */ + +/* result &= load_java_attributes(result, pos, &header->attributes, &header->attributes_count); */ + + return result; + +} + + + + + diff --git a/plugins/java/java-int.h b/plugins/java/java-int.h new file mode 100644 index 0000000..1636d1e --- /dev/null +++ b/plugins/java/java-int.h @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java-int.h - prototypes pour les structures internes du format Java + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_JAVA_INT_H +#define _FORMAT_JAVA_JAVA_INT_H + + +#include "java.h" +#include "java_def.h" +#include "../executable-int.h" + + + + + +/* Format d'exécutable Java (instance) */ +struct _GJavaFormat +{ + GExeFormat parent; /* A laisser en premier */ + + java_header header; /* En-tête du programme */ + +}; + +/* Format d'exécutable Java (classe) */ +struct _GJavaFormatClass +{ + GExeFormatClass parent; /* A laisser en premier */ + +}; + + + + + +/* Procède à la lecture d'une en-tête de programme Java. */ +bool read_java_header(const GJavaFormat *, off_t *, java_header *); + + + + + + + + +#endif /* _FORMAT_JAVA_JAVA_INT_H */ diff --git a/plugins/java/java.c b/plugins/java/java.c new file mode 100644 index 0000000..dcd8299 --- /dev/null +++ b/plugins/java/java.c @@ -0,0 +1,508 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java.c - support du format Java + * + * Copyright (C) 2010-2017 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 "java.h" + + +#include <string.h> + + +#include "java-int.h" + + + + + + + + + + + +/* Initialise la classe des formats d'exécutables Java. */ +static void g_java_format_class_init(GJavaFormatClass *); + +/* Initialise une instance de format d'exécutable Java. */ +static void g_java_format_init(GJavaFormat *); + +/* Supprime toutes les références externes. */ +static void g_java_format_dispose(GJavaFormat *); + +/* Procède à la libération totale de la mémoire. */ +static void g_java_format_finalize(GJavaFormat *); + +/* Indique le type d'architecture visée par le format. */ +static const char *g_java_format_get_target_machine(const GJavaFormat *); + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool java_is_matching(GBinContent *content) +{ + bool result; /* Bilan à faire connaître */ + vmpa2t addr; /* Tête de lecture initiale */ + char magic[4]; /* Idenfiant standard */ + + init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); + + result = g_binary_content_read_raw(content, &addr, 4, (bin_t *)magic); + + result &= (memcmp(magic, "\xca\xfe\xba\xbe", 4) == 0); + + return result; + +} + + +/* Indique le type défini pour un format d'exécutable Java. */ +G_DEFINE_TYPE(GJavaFormat, g_java_format, G_TYPE_EXE_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_format_class_init(GJavaFormatClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GExeFormatClass *exe; /* Version en exécutable */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_java_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_java_format_finalize; + + exe = G_EXE_FORMAT_CLASS(klass); + + exe->get_machine = (get_target_machine_fc)g_java_format_get_target_machine; + //exe->refine_portions = (refine_portions_fc)g_java_format_refine_portions; + + exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa; + exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa; + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_format_init(GJavaFormat *format) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_format_dispose(GJavaFormat *format) +{ + G_OBJECT_CLASS(g_java_format_parent_class)->dispose(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_format_finalize(GJavaFormat *format) +{ + G_OBJECT_CLASS(g_java_format_parent_class)->finalize(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge un nouveau format Java. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_java_format_new(const bin_t *content, off_t length) +{ + GJavaFormat *result; /* Structure à retourner */ + off_t offset; /* Tête de lecture */ + + result = g_object_new(G_TYPE_JAVA_FORMAT, NULL); + + //g_binary_format_set_content(G_BIN_FORMAT(result), content, length); + + + offset = 0; + + if (!read_java_header(result, &offset, &result->header)) + { + /* TODO */ + return NULL; + } + + + return G_BIN_FORMAT(result); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_java_format_get_target_machine(const GJavaFormat *format) +{ + return "jvm"; + +} + + + + + + + + + + + + +#if 0 + +#include <malloc.h> +#include <string.h> + + +#include "attribute.h" +#include "field.h" +#include "java-int.h" +#include "method.h" +#include "pool.h" +#include "../../common/endianness.h" + + + + +/* Indique le type d'architecture visée par le format. */ +FormatTargetMachine get_java_target_machine(const java_format *); + + + +/* Fournit les références aux zones de code à analyser. */ +bin_part **get_java_default_code_parts(const java_format *, size_t *); + + +/* Fournit le prototype de toutes les routines détectées. */ +GBinRoutine **get_all_java_routines(const java_format *, size_t *); + + + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool java_is_matching(const uint8_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + + result = false; + + if (length >= 4) + result = (strncmp((const char *)content, "\xca\xfe\xba\xbe", 4) == 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge une nouvelle classe Java. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +exe_format *load_java(const uint8_t *content, off_t length) +{ + java_format *result; /* Adresse à retourner */ + off_t pos; /* Point d'analyse */ + uint32_t magic; /* Identifiant Java */ + uint16_t i; /* Boucle de parcours */ + + result = (java_format *)calloc(1, sizeof(java_format)); + + EXE_FORMAT(result)->content = content; + EXE_FORMAT(result)->length = length; + + EXE_FORMAT(result)->get_target_machine = (get_target_machine_fc)get_java_target_machine; + EXE_FORMAT(result)->get_def_parts = (get_def_parts_fc)get_java_default_code_parts; + EXE_FORMAT(result)->get_all_routines = (get_all_routines_fc)get_all_java_routines; + + pos = 0; + + if (!read_u32(&magic, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->minor_version, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->major_version, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!load_java_pool(result, &pos)) + goto ldj_error; + + if (!read_u16((uint16_t *)&result->access, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->this_class, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->super_class, content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!read_u16(&result->interfaces_count, content, &pos, length, SRE_BIG)) + goto ldj_error; + + for (i = 0; i < result->interfaces_count; i++) + if (!read_u16(&result->interfaces[i], content, &pos, length, SRE_BIG)) + goto ldj_error; + + if (!load_java_fields(result, &pos)) + goto ldj_error; + + if (!load_java_methods(result, &pos)) + goto ldj_error; + + if (!load_java_attributes(result, &pos, &result->attributes, &result->attributes_count)) + goto ldj_error; + + return EXE_FORMAT(result); + + ldj_error: + + unload_java(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à supprimer. * +* * +* Description : Efface la prise en charge une nouvelle classe Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java(java_format *format) +{ + if (format->pool_len > 0) + unload_java_pool(format); + + if (format->interfaces_count > 0) + free(format->interfaces); + + if (format->fields_count > 0) + unload_java_fields(format); + + if (format->methods_count > 0) + unload_java_methods(format); + + if (format->attributes_count > 0) + unload_java_attributes(format, format->attributes, format->attributes_count); + + free(format); + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +FormatTargetMachine get_java_target_machine(const java_format *format) +{ + return FTM_JVM; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones de code à analyser. * +* * +* Retour : Zones de code à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_part **get_java_default_code_parts(const java_format *format, size_t *count) +{ + bin_part **result; /* Tableau à retourner */ + uint16_t i; /* Boucle de parcours */ + off_t offset; /* Position physique */ + off_t size; /* Taille de la partie */ + bin_part *part; /* Partie à intégrer à la liste*/ + + result = NULL; + *count = 0; + + for (i = 0; i < format->methods_count; i++) + if (find_java_method_code_part(&format->methods[i], &offset, &size)) + { + part = create_bin_part(); + + set_bin_part_values(part, offset, size, offset); + + result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); + result[*count - 1] = part; + + } + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = taille du tableau créé. [OUT] * +* * +* Description : Fournit le prototype de toutes les routines détectées. * +* * +* Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine **get_all_java_routines(const java_format *format, size_t *count) +{ + *count = 0; + + return NULL; + +} + +#endif diff --git a/plugins/java/java.h b/plugins/java/java.h new file mode 100644 index 0000000..ad70e43 --- /dev/null +++ b/plugins/java/java.h @@ -0,0 +1,63 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java.h - prototypes pour le support du format Java + * + * Copyright (C) 2010-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_JAVA_H +#define _FORMAT_JAVA_JAVA_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <sys/types.h> + + +#include "../../core/formats.h" + + + +#define G_TYPE_JAVA_FORMAT g_java_format_get_type() +#define G_JAVA_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_JAVA_FORMAT, GJavaFormat)) +#define G_IS_JAVA_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_JAVA_FORMAT)) +#define G_JAVA_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JAVA_FORMAT, GJavaFormatClass)) +#define G_IS_JAVA_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JAVA_FORMAT)) +#define G_JAVA_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JAVA_FORMAT, GJavaFormatClass)) + + +/* Format d'exécutable Java (instance) */ +typedef struct _GJavaFormat GJavaFormat; + +/* Format d'exécutable Java (classe) */ +typedef struct _GJavaFormatClass GJavaFormatClass; + + +/* Indique si le format peut être pris en charge ici. */ +bool java_is_matching(GBinContent *); + +/* Indique le type défini pour un format d'exécutable Java. */ +GType g_java_format_get_type(void); + +/* Prend en charge un nouveau format Java. */ +GBinFormat *g_java_format_new(const bin_t *, off_t); + + + +#endif /* _FORMAT_JAVA_JAVA_H */ diff --git a/plugins/java/java_def.h b/plugins/java/java_def.h new file mode 100644 index 0000000..2b1da67 --- /dev/null +++ b/plugins/java/java_def.h @@ -0,0 +1,418 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java_def.h - liste des structures et constantes utilisées par le format Java + * + * Copyright (C) 2010-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_JAVA_DEF_H +#define _FORMAT_JAVA_JAVA_DEF_H + + +#include <stdint.h> + + + +/* Description des attributs Java */ +typedef struct _java_attribute java_attribute; + + + +/* ----------------------- ELEMENTS DU RESERVOIR A CONSTANTES ----------------------- */ + + +/* Types de données dans le réservoir (§4.4) */ +typedef enum _ConstantPoolTag +{ + CONSTANT_EMPTY = 0, /* Non initialisé ou sur 2 */ + + CONSTANT_CLASS = 7, /* Classe ou interface */ + CONSTANT_FIELD_REF = 9, /* Champ ou méthode */ + CONSTANT_METHOD_REF = 10, /* Champ ou méthode */ + CONSTANT_INTERFACE_METHOD_REF = 11, /* Champ ou méthode */ + CONSTANT_STRING = 8, /* Chaîne constante */ + CONSTANT_INTEGER = 3, /* Valeur entière */ + CONSTANT_FLOAT = 4, /* Valeur flottante */ + CONSTANT_LONG = 5, /* Valeur longue */ + CONSTANT_DOUBLE = 6, /* Valeur double */ + CONSTANT_NAME_AND_TYPE = 12, /* Prototype complet */ + CONSTANT_UTF8 = 1 /* Chaîne codée en UTF8 */ + +} ConstantPoolTag; + + +/* Représentation d'une classe ou d'une interface */ +typedef struct _class_info +{ + uint16_t name_index; /* Indice pour le nom */ + +} class_info; + +/* Représentation d'un champ ou d'une méthode */ +typedef struct _ref_info +{ + uint16_t class_index; /* Indice de la classe */ + uint16_t name_and_type_index; /* Prototype associé */ + +} ref_info; + +/* Représentation d'une chaîne constante */ +typedef struct _string_info +{ + uint16_t string_index; /* Indice de la valeur UTF8 */ + +} string_info; + +/* Représentation d'une valeur 'int' */ +typedef struct _integer_info +{ + uint32_t val; /* Valeur au format 'int' */ + +} integer_info; + +/* Représentation d'une valeur 'float' */ +typedef struct _float_info +{ + float val; /* Valeur au format 'float' */ + +} float_info; + +/* Représentation d'une valeur 'long' */ +typedef struct _long_info +{ + long val; /* Valeur au format 'long' */ + +} long_info; + +/* Représentation d'une valeur 'double' */ +typedef struct _double_info +{ + double val; /* Valeur au format 'double' */ + +} double_info; + +/* Représentation brève d'un champ ou d'une méthode */ +typedef struct _name_and_type_info +{ + uint16_t name_index; /* Indice du nom correspondant */ + uint16_t descriptor_index; /* Prototype associé */ + +} name_and_type_info; + +/* Représentation d'une chaîne codée en UTF8 */ +typedef struct _utf8_info +{ + char *bytes; /* Valeur de la chaîne */ + +} utf8_info; + + +/* Entrée du réservoir */ +typedef struct _constant_pool_entry +{ + ConstantPoolTag tag; /* Type d'entrée présente */ + + union + { + class_info class; + ref_info ref; + string_info string; + integer_info int_val; + float_info float_val; + long_info long_val; + double_info double_val; + name_and_type_info name_type; + utf8_info utf8; + + } info; /* Infos portées par l'entrée */ + +} constant_pool_entry; + + + +/* ------------------------ ATTRIBUTS POUR DES ELEMENTS JAVA ------------------------ */ + + +/* Types des attributs reconnus */ +typedef enum _JavaAttributeType +{ + JAT_NONE = 0, /* Attribu non chargé */ + + JAT_CONSTANT_VALUE, /* Valeur constante */ + JAT_CODE, /* Code exécutable */ + JAT_EXCEPTIONS, /* Exceptions remontables */ + JAT_INNER_CLASSES, /* Classes internes */ + JAT_SYNTHETIC, /* Membre non présent */ + JAT_SOURCE_FILE, /* Fichier source du code */ + JAT_LINE_NUMBER, /* Correspondances de débogage */ + JAT_LOCAL_VARIABLES, /* Variable(s) locale(s) */ + JAT_DEPRECATED /* Elément vieillot à oublier */ + +} JavaAttributeType; + +/* Représentation d'un attribut à valeur constante (§4.7.2) */ +typedef struct _const_value_attrib +{ + uint16_t const_value_index; /* Indice dans le réservoir */ + +} const_value_attrib; + +/* Représentation d'un attribut de code (§4.7.3) */ + +typedef struct _code_exception +{ + uint16_t start_pc; /* Début de la zone couverte */ + uint16_t end_pc; /* Fin de la zone couverte */ + uint16_t handler_pc; /* Début du gestionnaire */ + uint16_t catch_type; /* Indice du type d'exception */ + +} code_exception; + +typedef struct _code_attrib +{ + uint16_t max_stack; /* Taille maximale de la pile */ + uint16_t max_locals; /* Nombre de variables (!) */ + uint32_t code_length; /* Taille du code référencé */ + + off_t content; /* Début du code exécutable */ + + code_exception *exceptions; /* Exceptions gérées */ + uint16_t exceptions_count; /* Nombre de ces exceptions */ + + java_attribute *attributes; /* Attributs liés au code */ + uint16_t attributes_count; /* Nombre de ces attributs */ + +} code_attrib; + +/* Représentation d'un attribut fixant les exceptions remontables (§4.7.4) */ + +typedef struct _exceptions_attrib +{ + uint16_t *throw; /* Exceptions remontées */ + uint16_t throw_count; /* Nombre de ces exceptions */ + +} exceptions_attrib; + +/* Représentation d'un attribut présentant les classes internes (§4.7.5) */ + +typedef enum _InnerClassAccessFlags +{ + ICA_PUBLIC = 0x0001, /* Elément public */ + ICA_PRIVATE = 0x0002, /* Elément privé */ + ICA_PROTECTED = 0x0004, /* Elément sous protection */ + ICA_STATIC = 0x0008, /* Elément statique */ + ICA_FINAL = 0x0010, /* Elément défini un seule fois*/ + ICA_INTERFACE = 0x0200, /* Déclaration d'interface */ + ICA_ABSTRACT = 0x0400 /* Déclaré comme abstrait */ + +} InnerClassAccessFlags; + +typedef struct _inner_class +{ + uint16_t inner_class_info_index; /* Propriétés de la classe */ + uint16_t outer_class_info_index; /* Propriétés de la parente */ + uint16_t inner_name_index; /* Nom de la classe */ + InnerClassAccessFlags access; /* Droits d'accès */ + +} inner_class; + +typedef struct _inner_classes_attrib +{ + inner_class *classes; /* Classes internes */ + uint16_t classes_count; /* Nombre de ces classe */ + +} inner_classes_attrib; + +/* Représentation d'un fichier source (§4.7.7) */ +typedef struct _source_file_attrib +{ + uint16_t source_file_index; /* Indice dans le réservoir */ + +} source_file_attrib; + +/* Représentation des correspondances entre lignes et code (§4.7.8) */ + +typedef struct _pc_and_line +{ + uint16_t start_pc; /* Début de la zone visée */ + uint16_t number; /* Numéro de ligne du code */ + +} pc_and_line; + +typedef struct _line_number_attrib +{ + pc_and_line *lines; /* Correspondances code/source */ + uint16_t lines_count; /* Nombre de correspondances */ + +} line_number_attrib; + +/* Représentation des variables locales (§4.7.9) */ + +typedef struct _local_variable +{ + uint16_t start_pc; /* Position dans le code */ + uint16_t length; /* Taille de la variable */ + uint16_t name_index; /* Indice nominal de réservoir */ + uint16_t descriptor_index; /* Type de la variable */ + uint16_t index; /* Place dans la liste complète*/ + +} local_variable; + +typedef struct _local_variables_attrib +{ + local_variable *vars; /* Variables locales */ + uint16_t vars_count; /* Nombre de ces variables */ + +} local_variables_attrib; + +/* Description des attributs Java */ +struct _java_attribute +{ + JavaAttributeType type; /* Type d'attribut représenté */ + + union + { + const_value_attrib const_value; + code_attrib code; + exceptions_attrib exceptions; + inner_classes_attrib inner_classes; + source_file_attrib source_file; + line_number_attrib line_number; + local_variables_attrib local_vars; + + } info; /* Infos portées par l'attribut*/ + +}; + + + +/* ---------------------------- CHAMPS POUR CLASSES JAVA ---------------------------- */ + + +/* Types d'accès aux champs (§4.5) */ +typedef enum _FieldAccessFlags +{ + FAC_PUBLIC = 0x0001, /* Elément public */ + FAC_PRIVATE = 0x0002, /* Elément privé */ + FAC_PROTECTED = 0x0004, /* Elément sous protection */ + FAC_STATIC = 0x0008, /* Elément statique */ + FAC_FINAL = 0x0010, /* Elément défini un seule fois*/ + FAC_VOLATILE = 0x0040, /* Elément sans cache */ + FAC_TRANSIENT = 0x0080 /* Elément ni lu ni écrit... */ + +} FieldAccessFlags; + +/* Description d'un champ Java */ +typedef struct _java_field +{ + FieldAccessFlags access; /* Droits d'accès */ + + uint16_t name_index; /* Nom dans le réservoir */ + uint16_t descriptor_index; /* Prototype au même endroit */ + + java_attribute *attributes; /* Attributs liés au champ */ + uint16_t attributes_count; /* Nombre de ces attributs */ + +} java_field; + + + +/* --------------------------- METHODES POUR CLASSES JAVA --------------------------- */ + + +/* Types d'accès aux champs (§4.6) */ +typedef enum _MethodAccessFlags +{ + MAC_PUBLIC = 0x0001, /* Elément public */ + MAC_PRIVATE = 0x0002, /* Elément privé */ + MAC_PROTECTED = 0x0004, /* Elément sous protection */ + MAC_STATIC = 0x0008, /* Elément statique */ + MAC_FINAL = 0x0010, /* Elément défini un seule fois*/ + MAC_SYNCHRONIZED = 0x0020, /* Elément avec mutex natif */ + MAC_NATIVE = 0x0100, /* Elément conçu sans Java */ + MAC_ABSTRACT = 0x0400, /* Elément sans implantation */ + MAC_STRICT = 0x0800 /* Elément déclaré stricte FP */ + +} MethodAccessFlags; + +/* Description d'une méthode Java */ +typedef struct _java_method +{ + MethodAccessFlags access; /* Droits d'accès */ + + uint16_t name_index; /* Nom dans le réservoir */ + uint16_t descriptor_index; /* Prototype au même endroit */ + + java_attribute *attributes; /* Attributs liés à la méthode */ + uint16_t attributes_count; /* Nombre de ces attributs */ + +} java_method; + + + +/* ---------------------------- LISTE DES DROITS D'ACCES ---------------------------- */ + + +/* Types d'accès (§4.1) */ +typedef enum _ClassAccessFlags +{ + CAC_PUBLIC = 0x0001, /* Elément public */ + CAC_FINAL = 0x0010, /* Déclaré comme final */ + CAC_SUPER = 0x0020, /* Traitement spécial */ + CAC_INTERFACE = 0x0200, /* Déclaration d'interface */ + CAC_ABSTRACT = 0x0400 /* Déclaré comme abstrait */ + +} ClassAccessFlags; + + + +/* --------------------------- DESCRIPTION DU FORMAT JAVA --------------------------- */ + + +/* En-tête de tout programe Java */ +typedef struct _java_header +{ + uint16_t minor_version; /* Numéro de révision mineur */ + uint16_t major_version; /* Numéro de révision majeur */ + + constant_pool_entry *pool; /* Réservoir de constantes */ + uint16_t pool_len; /* Quantité de ces éléments */ + + ClassAccessFlags access; /* Type de classe/interface */ + + uint16_t this_class; /* Infos sur la classe */ + uint16_t super_class; /* Infos sur la classe parente */ + + uint16_t *interfaces; /* Interfaces intégrées */ + uint16_t interfaces_count; /* Nombre de ces interfaces */ + + java_field *fields; /* Champs de la classe */ + uint16_t fields_count; /* Nombre de champs présents */ + + java_method *methods; /* Méthodes de la classe */ + uint16_t methods_count; /* Nombre de méthodes listées */ + + java_attribute *attributes; /* Attributs liés à la classe */ + uint16_t attributes_count; /* Nombre de ces attributs */ + +} java_header; + + + +#endif /* _FORMAT_JAVA_JAVA_DEF_H */ diff --git a/plugins/java/method.c b/plugins/java/method.c new file mode 100644 index 0000000..371ba8c --- /dev/null +++ b/plugins/java/method.c @@ -0,0 +1,187 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * method.c - gestion des méthodes Java + * + * Copyright (C) 2009-2017 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 "method.h" + + +#include <malloc.h> + + +#include "attribute.h" +#include "../../common/endianness.h" + + + +/* Charge les propriétés d'une méthode de classe. */ +bool load_java_method(java_format *, java_method *, off_t *); + +/* Décharge les propriétés d'une méthode de classe. */ +void unload_java_method(java_format *, java_method *); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les méthodes d'un binaire Java. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_methods(java_format *format, off_t *pos) +{ + bool result; /* Bilan à remonter */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&format->methods_count, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + if (!result) return false; + + if (format->methods_count > 0) + { + format->methods = (java_method *)calloc(format->methods_count, sizeof(java_method)); + + for (i = 0; i < format->methods_count && result; i++) + result = load_java_method(format, &format->methods[i], pos); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à vider. * +* * +* Description : Décharge les méthodes d'un binaire Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_methods(java_format *format) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < format->methods_count; i++) + unload_java_method(format, &format->methods[i]); + + free(format->methods); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* method = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'une méthode de classe. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_method(java_format *format, java_method *method, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = read_u16((uint16_t *)&method->access, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= read_u16(&method->name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&method->descriptor_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + result &= load_java_attributes(format, pos, + &method->attributes, &method->attributes_count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* method = élément à libérer. * +* * +* Description : Décharge les propriétés d'une méthode de classe. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_method(java_format *format, java_method *method) +{ + if (method->attributes_count > 0) + unload_java_attributes(format, method->attributes, method->attributes_count); + +} + + +/****************************************************************************** +* * +* Paramètres : method = élément à traiter. * +* offset = position physique du code de la méthode. [OUT] * +* size = taille du code de la méthode. [OUT] * +* * +* Description : Retrouve le code binaire correspondant à une méthode. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_java_method_code_part(const java_method *method, off_t *offset, off_t *size) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < method->attributes_count; i++) + if (method->attributes[i].type == JAT_CODE) + { + *offset = method->attributes[i].info.code.content; + *size = method->attributes[i].info.code.code_length; + break; + } + + return (i < method->attributes_count); + +} diff --git a/plugins/java/method.h b/plugins/java/method.h new file mode 100644 index 0000000..35b04e1 --- /dev/null +++ b/plugins/java/method.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * method.h - prototypes pour la gestion des méthodes Java + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_METHOD_H +#define _FORMAT_JAVA_METHOD_H + + +#include "e_java.h" +#include "java-int.h" + + + +/* Charge les méthodes d'un binaire Java. */ +bool load_java_methods(java_format *, off_t *); + +/* Décharge les méthodes d'un binaire Java. */ +void unload_java_methods(java_format *); + +/* Retrouve le code binaire correspondant à une méthode. */ +bool find_java_method_code_part(const java_method *method, off_t *, off_t *); + + + +#endif /* _FORMAT_JAVA_METHOD_H */ diff --git a/plugins/java/pool.c b/plugins/java/pool.c new file mode 100644 index 0000000..625e9cc --- /dev/null +++ b/plugins/java/pool.c @@ -0,0 +1,474 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * pool.c - lecture du réservoir de constantes + * + * Copyright (C) 2009-2017 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 "pool.h" + + +#include <malloc.h> +#include <math.h> +#include <string.h> + +#include "java-int.h" +#include "../../common/endianness.h" +#include "../../common/extstr.h" + + + +/* Charge les propriétés d'une constante du réservoir. */ +bool load_java_pool_entry(GJavaFormat *, constant_pool_entry *, off_t *); + +/* Fournit une entrée donnée du réservoir de constantes. */ +const constant_pool_entry *get_java_pool_entry(const GJavaFormat *, uint16_t, ConstantPoolTag); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge le réservoir de constantes d'un binaire Java. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_pool(GJavaFormat *format, off_t *pos) +{ + bool result; /* Bilan à remonter */ + uint16_t count; /* Nombre d'éléments présents */ + uint16_t i; /* Boucle de parcours */ + + result = false/*read_u16(&count, G_BIN_FORMAT(format)->content, pos, + G_BIN_FORMAT(format)->length, SRE_BIG)*/; +#if 0 + printf("Alloc %hu entries (result=%d)\n", count, result); + + format->header.pool_len = count - 1; + format->header.pool = (constant_pool_entry *)calloc(count - 1, sizeof(constant_pool_entry)); + + for (i = 1; i < count && result; i++) + { + result = load_java_pool_entry(format, &format->header.pool[i - 1], pos); + + if (format->header.pool[i - 1].tag == CONSTANT_LONG + || format->header.pool[i - 1].tag == CONSTANT_DOUBLE) + { + i++; + + /* On n'est jamais trop prudent */ + if (i < count) + format->header.pool[i - 1].tag = CONSTANT_EMPTY; + + } + + } +#endif + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à vider. * +* * +* Description : Décharge le réservoir de constantes d'un binaire Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_pool(GJavaFormat *format) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < format->header.pool_len; i++) + switch (format->header.pool[i].tag) + { + case CONSTANT_EMPTY: + case CONSTANT_CLASS: + case CONSTANT_FIELD_REF: + case CONSTANT_METHOD_REF: + case CONSTANT_INTERFACE_METHOD_REF: + case CONSTANT_STRING: + case CONSTANT_INTEGER: + case CONSTANT_FLOAT: + case CONSTANT_LONG: + case CONSTANT_DOUBLE: + case CONSTANT_NAME_AND_TYPE: + break; + + case CONSTANT_UTF8: + free(format->header.pool[i].info.utf8.bytes); + break; + + } + + free(format->header.pool); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* entry = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'une constante du réservoir. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_pool_entry(GJavaFormat *format, constant_pool_entry *entry, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint8_t tag; /* Type de l'élément */ + uint32_t low_bytes; /* Octets de poids faible */ + uint32_t high_bytes; /* Octets de poids fort */ + uint64_t bits; /* Nombre lu sur 64 bits */ + int sign; /* Signe du nombre lu */ + int exponent; /* Exposant du nombre lu */ + uint64_t mantissa32; /* Mantisse du nombre lu 32b */ + uint64_t mantissa64; /* Mantisse du nombre lu 64b */ + uint16_t length; /* Taille d'une chaîne */ + + result = false/*read_u8(&tag, G_BIN_FORMAT(format)->content, pos, + G_BIN_FORMAT(format)->length, SRE_BIG)*/; +#if 0 + entry->tag = tag; + + switch (entry->tag) + { + case CONSTANT_CLASS: + result = read_u16(&entry->info.class.name_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_FIELD_REF: + case CONSTANT_METHOD_REF: + case CONSTANT_INTERFACE_METHOD_REF: + + result = read_u16(&entry->info.ref.class_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&entry->info.ref.name_and_type_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + break; + + case CONSTANT_STRING: + result = read_u16(&entry->info.string.string_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_INTEGER: + result = read_u32(&entry->info.int_val.val, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_FLOAT: + + result = read_u32(&low_bytes, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + if (result) + { + if (low_bytes == 0x7f800000) + entry->info.float_val.val = INFINITY; + + else if (low_bytes == 0xff800000) + entry->info.float_val.val = /* -1* */INFINITY; + + else if ((low_bytes >= 0x7f800001 && low_bytes <= 0x7fffffff) + || (low_bytes >= 0xff800001 && low_bytes <= 0xffffffff)) + entry->info.float_val.val = NAN; + + else if (low_bytes == 0x00000000 || low_bytes == 0x80000000) + entry->info.float_val.val = 0; + + else + { + sign = (low_bytes & 0x80000000) ? -1 : 1; + exponent = (low_bytes >> 23) & 0xff; + mantissa32 = (exponent == 0 ? + (low_bytes & 0x7fffff) << 1 : + (low_bytes & 0x7fffff) | 0x800000); + + entry->info.float_val.val = pow(2, (exponent - 150)); + entry->info.float_val.val *= mantissa32; + entry->info.float_val.val *= sign; + + } + + } + + break; + + case CONSTANT_LONG: + + result = read_u32(&high_bytes, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + result &= read_u32(&low_bytes, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + if (result) + { + entry->info.double_val.val = (uint64_t)high_bytes << 32; + entry->info.double_val.val += low_bytes; + } + + break; + + case CONSTANT_DOUBLE: + + result = read_u32(&high_bytes, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + result &= read_u32(&low_bytes, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + if (result) + { + bits = (uint64_t)high_bytes << 32 | (uint64_t)low_bytes; + + if (bits == 0x7ff0000000000000ll) + entry->info.double_val.val = INFINITY; + + else if (bits == 0xfff0000000000000ll) + entry->info.double_val.val = /* -1* */INFINITY; + + else if ((bits >= 0x7ff0000000000001ll && bits <= 0x7fffffffffffffffll) + || (bits >= 0xfff0000000000001ll && bits <= 0xffffffffffffffffll)) + entry->info.double_val.val = NAN; + + else if (bits == 0x0000000000000000ll || bits == 0x8000000000000000ll) + entry->info.double_val.val = 0; + + else + { + sign = ((bits >> 63) == 0) ? 1 : -1; + exponent = (bits >> 52) & 0x7ffl; + mantissa64 = (exponent == 0 ? + (bits & 0xfffffffffffffll) << 1 : + (bits & 0xfffffffffffffll) | 0x10000000000000ll); + + entry->info.double_val.val = pow(2, (exponent - 1075)); + entry->info.double_val.val *= mantissa64; + entry->info.double_val.val *= sign; + + } + + } + + break; + + case CONSTANT_NAME_AND_TYPE: + + result = read_u16(&entry->info.name_type.name_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&entry->info.name_type.descriptor_index, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + break; + + case CONSTANT_UTF8: + + result = read_u16(&length, G_BIN_FORMAT(format)->content, + pos, G_BIN_FORMAT(format)->length, SRE_BIG); + + if (result) + { + entry->info.utf8.bytes = (char *)calloc(length + 1, sizeof(char)); + memcpy(entry->info.utf8.bytes, &G_BIN_FORMAT(format)->content[*pos], length); + *pos += length; + } + + break; + + default: + result = false; + break; + + } +#endif + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de l'élément dont la valeur est à recupérer. * +* expected = type de l'élément à trouver à l'indice donné. * +* * +* Description : Fournit une entrée donnée du réservoir de constantes. * +* * +* Retour : Entrée du réservoir de constantes ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const constant_pool_entry *get_java_pool_entry(const GJavaFormat *format, uint16_t index, ConstantPoolTag expected) +{ + const constant_pool_entry *result; /* Entrée à retourner */ + constant_pool_entry *entry; /* Entrée du réservoir visée */ + + result = NULL; + + if (/*index < 0 && FIXME */index <= format->header.pool_len); + { + entry = &format->header.pool[index - 1]; + + if (entry->tag == expected) + result = entry; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de l'élément de la table à recupérer. * +* expected = type de l'élément à trouver à l'indice donné. * +* * +* Description : Construit une version humaine de référence. * +* * +* Retour : Référence construite ou NULL en cas de problème. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *build_reference_from_java_pool(const GJavaFormat *format, uint16_t index, JavaRefType expected) +{ + char *result; /* Chaîne humaine à retourner */ + const constant_pool_entry *entry; /* Entrée du réservoir visée 1 */ + const constant_pool_entry *subentry; /* Entrée du réservoir visée 2 */ + const char *tmp; /* Copie de chaîne intouchable */ + + result = NULL; + + switch (expected) + { + case JRT_FIELD: + entry = get_java_pool_entry(format, index, CONSTANT_FIELD_REF); + break; + case JRT_METHOD: + entry = get_java_pool_entry(format, index, CONSTANT_METHOD_REF); + break; + case JRT_INTERFACE_METHOD: + entry = get_java_pool_entry(format, index, CONSTANT_INTERFACE_METHOD_REF); + break; + default: + entry = NULL; + break; + } + + if (entry == NULL) + goto brfjp_error; + + /* Lieu parent où trouver la référence */ + + subentry = get_java_pool_entry(format, entry->info.ref.class_index, CONSTANT_CLASS); + + if (subentry == NULL) + goto brfjp_error; + + if (!get_java_pool_ut8_string(format, subentry->info.class.name_index, &tmp)) + goto brfjp_error; + + result = strdup(tmp); + + /* Champ proprement dit */ + + subentry = get_java_pool_entry(format, entry->info.ref.name_and_type_index, CONSTANT_NAME_AND_TYPE); + + if (subentry == NULL) + goto brfjp_error; + + if (!get_java_pool_ut8_string(format, subentry->info.name_type.name_index, &tmp)) + goto brfjp_error; + + result = stradd(result, "."); + result = stradd(result, tmp); + + /* Petites retouches finales */ + + result = strrpl(result, "/", "."); + result = strrpl(result, "<", "<"); + result = strrpl(result, ">", ">"); + + return result; + + brfjp_error: + + if (result != NULL) + free(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de l'élément dont la valeur est à recupérer. * +* str = adresse où placer la chaîne de caractères trouvée. * +* * +* Description : Recherche une chaîne de caractères dans le réservoir. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_java_pool_ut8_string(const GJavaFormat *format, uint16_t index, const char **str) +{ + bool result; /* Bilan à renvoyer */ + const constant_pool_entry *entry; /* Entrée du réservoir visée */ + + entry = get_java_pool_entry(format, index, CONSTANT_UTF8); + + result = (entry != NULL); + + if (result) + (*str) = entry->info.utf8.bytes; + + return result; + +} diff --git a/plugins/java/pool.h b/plugins/java/pool.h new file mode 100644 index 0000000..7f1a1db --- /dev/null +++ b/plugins/java/pool.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * pool.h - prototypes pour la lecture du réservoir de constantes + * + * Copyright (C) 2009-2017 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/>. + */ + + +#ifndef _FORMAT_JAVA_POOL_H +#define _FORMAT_JAVA_POOL_H + + +#include "java.h" + + + +/* Types de référence Java */ +typedef enum _JavaRefType +{ + JRT_FIELD, /* Champ */ + JRT_METHOD, /* Méthode */ + JRT_INTERFACE_METHOD /* Méthode d'interface */ + +} JavaRefType; + + +/* Charge le réservoir de constantes d'un binaire Java. xs*/ +bool load_java_pool(GJavaFormat *, off_t *); + +/* Décharge le réservoir de constantes d'un binaire Java. */ +void unload_java_pool(GJavaFormat *); + +/* Construit une version humaine de référence. */ +char *build_reference_from_java_pool(const GJavaFormat *, uint16_t, JavaRefType); + +/* Recherche une chaîne de caractères dans le réservoir. */ +bool get_java_pool_ut8_string(const GJavaFormat *, uint16_t, const char **); + + + +#endif /* _FORMAT_JAVA_POOL_H */ |