diff options
Diffstat (limited to 'plugins')
67 files changed, 12536 insertions, 8 deletions
diff --git a/plugins/gdbrsp/Makefile.am b/plugins/gdbrsp/Makefile.am new file mode 100644 index 0000000..5ee8df6 --- /dev/null +++ b/plugins/gdbrsp/Makefile.am @@ -0,0 +1,29 @@ + +noinst_LTLIBRARIES = libdebuggdbrsp.la + +libdebuggdbrsp_la_SOURCES =				\ +	aops.h								\ +	gdb-int.h							\ +	gdb.h gdb.c							\ +	helpers.h helpers.c					\ +	helpers_arm.h helpers_arm.c			\ +	helpers_arm64.h helpers_arm64.c		\ +	packet.h packet.c					\ +	stream-int.h						\ +	stream.h stream.c					\ +	support.h support.c					\ +	target.h target.c					\ +	tcp.h tcp.c							\ +	utils.h utils.c + +libdebuggdbrsp_la_CFLAGS = $(AM_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=%) + +dev_HEADERS = $(libdebuggdbrsp_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/gdbrsp/aops.h b/plugins/gdbrsp/aops.h new file mode 100644 index 0000000..1599615 --- /dev/null +++ b/plugins/gdbrsp/aops.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * aops.h - prototypes pour les compléments utiles à GDB pour l'architecture ARM + * + * Copyright (C) 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 _DEBUG_GDBRSP_AOPS_H +#define _DEBUG_GDBRSP_AOPS_H + + +#include "gdb.h" + + + +/* Détermine le point d'exécution courant. */ +typedef bool (* get_pc_fc) (GGdbDebugger *, virt_t *); + +/* Remonte la pile d'appels jusqu'au point courant. */ +typedef bool (* compute_call_stack_fc) (const GGdbDebugger *, virt_t **, size_t *); + +/* Complète la commande manipulant des points d'arrêt. */ +typedef const char * (* get_bp_kind_fc) (const GGdbDebugger *, virt_t); + +/* Construit une instruction provoquant un arrêt d'exécution. */ +typedef const uint8_t * (* get_bp_data_fc) (const GGdbDebugger *, virt_t, size_t *); + + +/* Procédures spécifiques pour une architecture */ +typedef struct _gdb_arch_ops +{ +    get_pc_fc get_pc;                       /* Obtention du point d'exéc.  */ +    compute_call_stack_fc compute_cstack;   /* Calcule la pile d'appels    */ +    get_bp_kind_fc get_bp_kind;             /* Fournit le type d'un point  */ +    get_bp_data_fc get_bp_data;             /* Code d'un point d'arrêt     */ + +} gdb_arch_ops; + + + +#endif  /* _DEBUG_GDBRSP_AOPS_H */ diff --git a/plugins/gdbrsp/gdb-int.h b/plugins/gdbrsp/gdb-int.h new file mode 100644 index 0000000..11b4753 --- /dev/null +++ b/plugins/gdbrsp/gdb-int.h @@ -0,0 +1,116 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gdb.h - prototypes pour le débogage à l'aide de gdb. + * + * Copyright (C) 2009-2012 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 _DEBUG_GDBRSP_GDB_INT_H +#define _DEBUG_GDBRSP_GDB_INT_H + + +#include "aops.h" +#include "gdb.h" +#include "stream.h" +#include "support.h" +#include "target.h" +#include "../break-int.h" +#include "../debugger-int.h" + + + + + + + + + + +/* Définition d'un point d'arrêt appliqué */ +typedef struct _gdb_breakpoint +{ +    raw_breakpoint raw;                     /* A laisser en premier        */ + +    bool is_z;                              /* Usage de commande dédiée ?  */ + +    union +    { +        const char *kind;                   /* Précision de taille         */ + +        struct +        { +            uint8_t memory[16];             /* Données d'origine remplacées*/ +            size_t len;                     /* Quantité de ces données     */ +        }; + +    }; + +} gdb_breakpoint; + + + + + + + + + + + + + + +/* Débogueur utilisant un serveur GDB (instance) */ +struct _GGdbDebugger +{ +    GBinaryDebugger parent;                 /* A laisser en premier        */ + +    SourceEndian endian;                    /* Boutisme du format          */ +    MemoryDataSize msize;                   /* Taille des adresses         */ + +    const gdb_arch_ops *ops;                /* Opérations spécifiques      */ + +    GGdbStream *stream;                     /* Flux de communication       */ +    GGdbSupport *support;                   /* Configuration à adopter     */ +    GGdbTarget *target;                     /* Architecture ciblée par GDB */ + +}; + + +/* Débogueur utilisant un serveur GDB (classe) */ +struct _GGdbDebuggerClass +{ +    GBinaryDebuggerClass parent;            /* A laisser en premier        */ + +}; + + + +/* ------------------------ ACCUEIL D'EVENEMENTS ASYNCHRONES ------------------------ */ + + +/* Réagit à la réception d'un signal par le programme étudié. */ +void g_gdb_debugger_receive_signal_reply(GGdbDebugger *, int); + +/* Réagit à la sortie d'exécution d'un programme étudié. */ +void g_gdb_debugger_receive_exit_reply(GGdbDebugger *, int, pid_t); + + + +#endif  /* _DEBUG_GDBRSP_GDB_INT_H */ diff --git a/plugins/gdbrsp/gdb.c b/plugins/gdbrsp/gdb.c new file mode 100644 index 0000000..1d0ffe5 --- /dev/null +++ b/plugins/gdbrsp/gdb.c @@ -0,0 +1,1524 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gdb.c - débogage à l'aide de gdb. + * + * 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 "gdb.h" + + + +#include <assert.h> +#include <malloc.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + + +#include "gdb-int.h" +#include "helpers.h" +#include "helpers_arm.h" +#include "helpers_arm64.h" +#include "tcp.h" +#include "utils.h" +#include "../../common/cpp.h" +#include "../../format/format.h" + + + + + + + + +/* Initialise la classe du débogueur utilisant gdb. */ +static void g_gdb_debugger_class_init(GGdbDebuggerClass *); + +/* Procède à l'initialisation du débogueur utilisant gdb. */ +static void g_gdb_debugger_init(GGdbDebugger *); + +/* Supprime toutes les références externes. */ +static void g_gdb_debugger_dispose(GGdbDebugger *); + +/* Procède à la libération totale de la mémoire. */ +static void g_gdb_debugger_finalize(GGdbDebugger *); + + +/* Met en marche le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_run(GGdbDebugger *); + +/* Remet en marche le débogueur utilisant un serveur GDB. */ +//static bool g_gdb_debugger_resume(GGdbDebugger *); + +/* Tue le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_kill(GGdbDebugger *); + + + + + + +/* --------------------------- ENTREES / SORTIES BASIQUES --------------------------- */ + + +/* Lit une valeur quelconque à une adresse arbitraire.  */ +static bool g_gdb_debugger_read_memory(GGdbDebugger *, virt_t, size_t, ...); + +/* Ecrit une valeur quelconque à une adresse arbitraire.  */ +static bool g_gdb_debugger_write_memory(GGdbDebugger *, virt_t, size_t, ...); + +/* Liste l'ensemble des registres appartenant à un groupe. */ +static char **g_gdb_debugger_get_register_names(const GGdbDebugger *, const char *, size_t *); + +/* Indique la taille associée à un registre donné. */ +static unsigned int g_gdb_debugger_get_register_size(const GGdbDebugger *, const char *); + +/* Effectue la lecture d'un registre donné. */ +static bool g_gdb_debugger_read_register(GGdbDebugger *, const char *, size_t, ...); + +/* Effectue l'écriture d'un registre donné. */ +static bool g_gdb_debugger_write_register(GGdbDebugger *, const char *, size_t, ...); + + + +/* ------------------------- MANIPULATION DE L'ETAT COURANT ------------------------- */ + + +/* Détermine le point d'exécution courant. */ +static bool g_gdb_debugger_get_current_pc(GGdbDebugger *, virt_t *); + +/* Remonte la pile d'appels jusqu'au point courant. */ +static bool g_gdb_debugger_compute_call_stack(GGdbDebugger *, virt_t **, size_t *); + + + +/* --------------------------- GESTION DES POINTS D'ARRET --------------------------- */ + + +/* Ajoute un point d'arrêt basique en mémoire. */ +static gdb_breakpoint *g_gdb_debugger_enable_memory_breakpoint(GGdbDebugger *, virt_t); + +/* Retire un point d'arrêt basique en mémoire. */ +static bool g_gdb_debugger_disable_memory_breakpoint(GGdbDebugger *, gdb_breakpoint *); + + + +/* -------------------------- CONTROLE DU FLOT D'EXECUTION -------------------------- */ + + +/* Redémarre le processus de débogage lié à un serveur GDB. */ +static bool g_gdb_debugger_restart(GGdbDebugger *); + +/* Remet en marche le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_resume(GGdbDebugger *); + + + + + + + + + + + + +/* Détermine l'identifiant du thread principal courant. */ +static char *g_gdb_debugger_get_active_thread(GGdbDebugger *); + + + + + + +/* ------------------------ ACCUEIL D'EVENEMENTS ASYNCHRONES ------------------------ */ + + + + + + + + +/* Indique le type défini par la GLib pour le débogueur gdb. */ +G_DEFINE_TYPE(GGdbDebugger, g_gdb_debugger, G_TYPE_BINARY_DEBUGGER); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe de débogueur à initialiser.                   * +*                                                                             * +*  Description : Initialise la classe du débogueur utilisant gdb.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_debugger_class_init(GGdbDebuggerClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GBinaryDebuggerClass *parent;           /* Version en classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_debugger_dispose; +    object->finalize = (GObjectFinalizeFunc)g_gdb_debugger_finalize; + +    parent = G_BINARY_DEBUGGER_CLASS(klass); + +    parent->read_mem = (read_mem_any_fc)g_gdb_debugger_read_memory; +    parent->write_mem = (write_mem_any_fc)g_gdb_debugger_write_memory; +    parent->get_reg_names = (get_reg_names_fc)g_gdb_debugger_get_register_names; +    parent->get_reg_size = (get_reg_size_fc)g_gdb_debugger_get_register_size; +    parent->read_reg = (read_write_reg_any_fc)g_gdb_debugger_read_register; +    parent->write_reg = (read_write_reg_any_fc)g_gdb_debugger_write_register; + +    parent->get_current_pc = (get_current_pc_fc)g_gdb_debugger_get_current_pc; +    parent->get_call_stack = (get_call_stack_fc)g_gdb_debugger_compute_call_stack; + +    parent->enable_bp = (enable_mem_bp_fc)g_gdb_debugger_enable_memory_breakpoint; +    parent->disable_bp = (disable_mem_bp_fc)g_gdb_debugger_disable_memory_breakpoint; + +    parent->restart = (restart_debugger_fc)g_gdb_debugger_restart; +    parent->resume = (resume_debugger_fc)g_gdb_debugger_resume; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = instance de débogueur à préparer.                 * +*                                                                             * +*  Description : Procède à l'initialisation du débogueur utilisant gdb.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_debugger_init(GGdbDebugger *debugger) +{ +    GBinaryDebugger *parent;                /* Instance parente            */ + +    parent = G_BINARY_DEBUGGER(debugger); + +    parent->run = (basic_debugger_fc)g_gdb_debugger_run; +    //parent->resume = (resume_debugger_fc)g_gdb_debugger_resume; +    parent->kill = (basic_debugger_fc)g_gdb_debugger_kill; + +    //parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger; + +    //debugger->cond = g_cond_new(); +    //debugger->mutex = g_mutex_new(); + + +    // FIXME +    //debugger->compute_cstack = compute_call_stack_for_arm64; +    //debugger->fill_mem_bp = fill_memory_breakpoint_cmd_for_arm64; + + + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = instance d'objet GLib à traiter.                  * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_debugger_dispose(GGdbDebugger *debugger) +{ +    if (debugger->stream != NULL) +        g_object_unref(G_OBJECT(debugger->stream)); + +    if (debugger->support != NULL) +        g_object_unref(G_OBJECT(debugger->support)); + +    if (debugger->target != NULL) +        g_object_unref(G_OBJECT(debugger->target)); + +    G_OBJECT_CLASS(g_gdb_debugger_parent_class)->dispose(G_OBJECT(debugger)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = instance d'objet GLib à traiter.                  * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_debugger_finalize(GGdbDebugger *debugger) +{ +    G_OBJECT_CLASS(g_gdb_debugger_parent_class)->finalize(G_OBJECT(debugger)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = binaire représenter à déboguer.                     * +*                server = nom ou adresse du serveur à contacter.              * +*                port   = port de connexion.                                  * +*                                                                             * +*  Description : Crée un débogueur utilisant un serveur GDB distant.          * +*                                                                             * +*  Retour      : Instance de débogueur mise en place ou NULL.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GBinaryDebugger *g_gdb_debugger_new(GLoadedBinary *binary, const char *server, unsigned short port) +{ +    GGdbDebugger *result;                   /* Débogueur à retourner       */ +    GExeFormat *format;                     /* Format du binaire chargé    */ +    const char *arch;                       /* Architecture d'exécution    */ +    GArchProcessor *proc;                   /* Processeur lié au binaire   */ +    char service[sizeof(XSTR(UINT16_MAX)) + 1]; /* Conversion requise      */ + +    result = g_object_new(G_TYPE_GDB_DEBUGGER, NULL); + +    G_BINARY_DEBUGGER(result)->binary = binary; +    g_object_ref(G_OBJECT(binary)); + +    /* Propriétés de la cible */ + +    format = g_loaded_binary_get_format(binary); + +    result->endian = g_binary_format_get_endianness(G_BIN_FORMAT(format)); + +    arch = g_exe_format_get_target_machine(format); + +    if (strcmp(arch, "armv7") == 0) +        result->ops = get_arm_operations(); +    else +        result->ops = NULL; + +    g_object_unref(G_OBJECT(format)); + +    if (result->ops == NULL) +        goto ggdn_error; + +    proc = g_loaded_binary_get_processor(binary); + +    result->msize = g_arch_processor_get_memory_size(proc); + +    g_object_unref(G_OBJECT(proc)); + +    /* Mise en place des modules auxialiaires */ + +    snprintf(service, sizeof(service), "%hu", port); + +    result->stream = g_gdb_tcp_client_new(server, service, result); +    if (result->stream == NULL) goto ggdn_error; + +    result->support = g_gdb_support_new(result->stream); + +    result->target = g_gdb_target_new(result->stream); +    if (result->target == NULL) goto ggdn_error; + +    return G_BINARY_DEBUGGER(result); + + ggdn_error: + +    g_object_unref(G_OBJECT(result)); + +    return NULL; + +} + + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à lancer.                               * +*                                                                             * +*  Description : Met en marche le débogueur utilisant un serveur GDB.         * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_run(GGdbDebugger *debugger) +{ + + + +    GGdbPacket *packet; + +    bool test; + +    const char *data; +    size_t len; + + +    int sig; +    vmpa_t addr; +    pid_t thread; + + +    debugger->stream = g_gdb_tcp_client_new("127.0.0.1", "6666", NULL); +    if (debugger->stream == NULL) return false; + + +    printf("Connection done !\n"); + + + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "?"); + + +    test = g_gdb_stream_send_packet(debugger->stream, packet); + + + +    printf(" >> Paquet '%s' bien envoyé ? %s\n", "?", test ? "oui" : "non"); + + + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    packet = g_gdb_stream_recv_packet(debugger->stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    printf(" << Réception de '%s'\n", data); + + + + + +    get_stop_reply_sig_info(packet, &sig, &addr, &thread, SRE_LITTLE); + +    g_signal_emit_by_name(debugger, "halted", sig, addr, thread); + + + +    return true; + +} + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à relancer.                             * +*                                                                             * +*  Description : Tue le débogueur utilisant un serveur GDB.                   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_kill(GGdbDebugger *debugger) +{ + + +#if 0 +    int ret;                                /* Bilan de l'appel système    */ + +    ret = kill(debugger->child, SIGKILL); +    if (ret != 0) perror("kill"); + +    debugger->child = 0; + +    g_mutex_lock(debugger->mutex); +    debugger->run_again = TRUE; +    g_cond_signal(debugger->cond); +    g_mutex_unlock(debugger->mutex); +#endif +    return true; + +} + + + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                                                                             * +*  Description : Détermine l'identifiant du thread principal courant.         * +*                                                                             * +*  Retour      : Identifiant du thread actif principal ou NULL en cas d'échec.* +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_gdb_debugger_get_active_thread(GGdbDebugger *debugger) +{ +    char *result;                           /* Identifiant à renvoyer      */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    bool status;                            /* Bilan d'une communication   */ +    const char *data;                       /* Données reçues à analyser   */ +    const char *start;                      /* Début d'identification      */ +    const char *end;                        /* Fin d'identification        */ + +    result = NULL; + +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "?"); + +    status = g_gdb_stream_send_packet(debugger->stream, packet); + +    if (!status) +        goto ggdgat_exit; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(debugger->stream); + +    g_gdb_packet_get_data(packet, &data, NULL, NULL); + +    start = strstr(data, "thread:"); +    if (start == NULL) goto ggdgat_exit; + +    start += sizeof("thread:") - 1 /* '\0' */; + +    end = strstr(start, ";"); +    if (end == NULL) goto ggdgat_exit; + +    result = strndup(start, end - start); + + ggdgat_exit: + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    return result; + +} + + + + + + + + + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                             ENTREES / SORTIES BASIQUES                             */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                addr     = emplacement en mémoire à venir consulter.         * +*                size     = taille des données mises en jeu.                  * +*                ...      = emplacement de la valeur lue à conserver. [OUT]   * +*                                                                             * +*  Description : Lit une valeur quelconque à une adresse arbitraire.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_read_memory(GGdbDebugger *debugger, virt_t addr, size_t size, ...) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    char cmd[1 + VMPA_MAX_LEN + 3];         /* Commande à émettre          */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de données reçues  */ +    va_list ap;                             /* Liste variable d'arguments  */ +    uint8_t *val8;                          /* Valeur sur 8 bits           */ +    uint16_t *val16;                        /* Valeur sur 16 bits          */ +    uint16_t conv16;                        /* Valeur adaptée sur 16 bits  */ +    uint32_t *val32;                        /* Valeur sur 32 bits          */ +    uint32_t conv32;                        /* Valeur adaptée sur 32 bits  */ +    uint64_t *val64;                        /* Valeur sur 64 bits          */ +    uint64_t conv64;                        /* Valeur adaptée sur 64 bits  */ + +    /* Envoi de la requête */ + +    cmd[0] = 'm'; + +    result = translate_virt_to_hex(debugger, addr, &cmd[1]); + +    switch (size) +    { +        case 8: +            strcat(cmd, ",1"); +            break; + +        case 16: +            strcat(cmd, ",2"); +            break; + +        case 32: +            strcat(cmd, ",4"); +            break; + +        case 64: +            strcat(cmd, ",8"); +            break; + +        default: +            assert(false); +            result = false; +            goto ggdrm_exit; +            break; + +    } + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, cmd); + +    result = g_gdb_stream_send_packet(debugger->stream, packet); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    if (!result) +        goto ggdrm_exit; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(debugger->stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    if (is_error_code(data, len)) +    { +        result = false; +        goto ggdrm_error; +    } + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, uint8_t *); +            result = hex_to_u8(data, val8); +            break; + +        case 16: +            val16 = va_arg(ap, uint16_t *); +            result = hex_to_u16(data, &conv16); +            *val16 = from_u16(&conv16, debugger->endian); +            break; + +        case 32: +            val32 = va_arg(ap, uint32_t *); +            result = hex_to_u32(data, &conv32); +            *val32 = from_u32(&conv32, debugger->endian); +            break; + +        case 64: +            val64 = va_arg(ap, uint64_t *); +            result = hex_to_u64(data, &conv64); +            *val64 = from_u64(&conv64, debugger->endian); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    va_end(ap); + + ggdrm_error: + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + + ggdrm_exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler.                            * +*                addr     = emplacement en mémoire à venir consulter.         * +*                size     = taille des données mises en jeu.                  * +*                ...      = emplacement de la valeur lue à conserver. [OUT]   * +*                                                                             * +*  Description : Lit une valeur quelconque à une adresse arbitraire.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_write_memory(GGdbDebugger *debugger, virt_t addr, size_t size, ...) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    char cmd[1 + 3 * VMPA_MAX_LEN + 3];     /* Commande à émettre          */ +    va_list ap;                             /* Liste variable d'arguments  */ +    const uint8_t *val8;                    /* Valeur sur 8 bits           */ +    const uint16_t *val16;                  /* Valeur sur 16 bits          */ +    uint16_t conv16;                        /* Valeur adaptée sur 16 bits  */ +    const uint32_t *val32;                  /* Valeur sur 32 bits          */ +    uint32_t conv32;                        /* Valeur adaptée sur 32 bits  */ +    const uint64_t *val64;                  /* Valeur sur 64 bits          */ +    uint64_t conv64;                        /* Valeur adaptée sur 64 bits  */ +    char hexval[17];                        /* Valeur sous forme hexa      */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de données reçues  */ + +    /* Envoi de la requête */ + +    cmd[0] = 'M'; + +    result = translate_virt_to_hex(debugger, addr, &cmd[1]); + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, uint8_t *); +            result = u8_to_hex(val8, hexval); + +            strcat(cmd, ",1:"); +            strcat(cmd, hexval); +            break; + +        case 16: +            val16 = va_arg(ap, uint16_t *); +            conv16 = to_u16(val16, debugger->endian); +            result = u16_to_hex(&conv16, hexval); + +            strcat(cmd, ",2:"); +            strcat(cmd, hexval); +            break; + +        case 32: +            val32 = va_arg(ap, uint32_t *); +            conv32 = to_u32(val32, debugger->endian); +            result = u32_to_hex(&conv32, hexval); + +            strcat(cmd, ",4:"); +            strcat(cmd, hexval); +            break; + +        case 64: +            val64 = va_arg(ap, uint64_t *); +            conv64 = to_u64(val64, debugger->endian); +            result = u16_to_hex(&conv64, hexval); + +            strcat(cmd, ",8:"); +            strcat(cmd, hexval); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    if (!result) +        goto ggdwm_exit; + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, cmd); + +    result = g_gdb_stream_send_packet(debugger->stream, packet); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    if (!result) +        goto ggdwm_exit; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(debugger->stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    if (len == 3 && data[0] == 'E') +    { +        result = false; +        goto ggdrm_error; +    } + + ggdrm_error: + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + + ggdwm_exit: + +    va_end(ap); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                group    = éventuel groupe de registres ciblé ou NULL.       * +*                count    = nombre d'éléments dans la liste de noms. [OUT]    * +*                                                                             * +*  Description : Liste l'ensemble des registres appartenant à un groupe.      * +*                                                                             * +*  Retour      : Liste de noms à libérer de la mémoire après utilisation.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char **g_gdb_debugger_get_register_names(const GGdbDebugger *debugger, const char *group, size_t *count) +{ +    return g_gdb_target_get_register_names(debugger->target, group, count); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                name     = désignation du registre visé.                     * +*                                                                             * +*  Description : Indique la taille associée à un registre donné.              * +*                                                                             * +*  Retour      : Taille en bits, ou 0 si le registre n'a pas été trouvé.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static unsigned int g_gdb_debugger_get_register_size(const GGdbDebugger *debugger, const char *name) +{ +    return g_gdb_target_get_register_size(debugger->target, name); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                reg      = désignation humaine du register à consulter.      * +*                size     = taille des données mises en jeu.                  * +*                ...      = emplacement de la valeur lue à conserver. [OUT]   * +*                                                                             * +*  Description : Effectue la lecture d'un registre donné.                     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_read_register(GGdbDebugger *debugger, const char *reg, size_t size, ...) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    va_list ap;                             /* Liste variable d'arguments  */ +    uint8_t *val8;                          /* Valeur sur 8 bits           */ +    uint16_t *val16;                        /* Valeur sur 16 bits          */ +    uint32_t *val32;                        /* Valeur sur 32 bits          */ +    uint64_t *val64;                        /* Valeur sur 64 bits          */ + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, uint8_t *); +            result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, +                                                reg, 8, val8); +            break; + +        case 16: +            val16 = va_arg(ap, uint16_t *); +            result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, +                                                reg, 16, val16); +            break; + +        case 32: +            val32 = va_arg(ap, uint32_t *); +            result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, +                                                reg, 32, val32); +            break; + +        case 64: +            val64 = va_arg(ap, uint64_t *); +            result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, +                                                reg, 64, val64); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    va_end(ap); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler.                            * +*                reg      = désignation humaine du register à consulter.      * +*                size     = taille des données mises en jeu.                  * +*                ...      = emplacement de la valeur à écrire.                * +*                                                                             * +*  Description : Effectue l'écriture d'un registre donné.                     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_write_register(GGdbDebugger *debugger, const char *reg, size_t size, ...) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    va_list ap;                             /* Liste variable d'arguments  */ +    const uint8_t *val8;                    /* Valeur sur 8 bits           */ +    const uint16_t *val16;                  /* Valeur sur 16 bits          */ +    const uint32_t *val32;                  /* Valeur sur 32 bits          */ +    const uint64_t *val64;                  /* Valeur sur 64 bits          */ + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, const uint8_t *); +            result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, +                                                 reg, 8, val8); +            break; + +        case 16: +            val16 = va_arg(ap, const uint16_t *); +            result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, +                                                 reg, 16, val16); +            break; + +        case 32: +            val32 = va_arg(ap, const uint32_t *); +            result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, +                                                 reg, 32, val32); +            break; + +        case 64: +            val64 = va_arg(ap, const uint64_t *); +            result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, +                                                 reg, 64, val64); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    va_end(ap); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                           MANIPULATION DE L'ETAT COURANT                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                pc       = adresse de l'instruction courante. [OUT]          * +*                                                                             * +*  Description : Détermine le point d'exécution courant.                      * +*                                                                             * +*  Retour      : Bilan de la récupération.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_get_current_pc(GGdbDebugger *debugger, virt_t *pc) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = debugger->ops->get_pc(debugger, pc); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger  = débogueur à consulter.                           * +*                callstack = pile d'appels reconstituée. [OUT]                * +*                size      = taille de cette pile. [OUT]                      * +*                                                                             * +*  Description : Remonte la pile d'appels jusqu'au point courant.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_compute_call_stack(GGdbDebugger *debugger, virt_t **callstack, size_t *size) +{ +    bool result;                            /* Bilan global à retourner    */ + +    if (debugger->ops->compute_cstack != NULL) +        result = debugger->ops->compute_cstack(debugger, callstack, size); + +    else +        result = false; + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                             GESTION DES POINTS D'ARRET                             */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler ici.                        * +*                addr     = emplacement du point mémoire à traiter.           * +*                                                                             * +*  Description : Ajoute un point d'arrêt basique en mémoire.                  * +*                                                                             * +*  Retour      : Structure de suivi mise en place pour l'occasion, voire NULL.* +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static gdb_breakpoint *g_gdb_debugger_enable_memory_breakpoint(GGdbDebugger *debugger, virt_t addr) +{ +    gdb_breakpoint *result;                 /* Nouveau suivi à retourner   */ +    char cmd[3 + VMPA_MAX_LEN + 3];         /* Commande à émettre          */ +    bool status;                            /* Bilan d'une opération       */ +    const char *kind;                       /* Taille spécifique du point  */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de données reçues  */ +    GBinaryDebugger *dbg;                   /* Autre version du débogueur  */ +    const uint8_t *bp;                      /* Données du point d'arrêt    */ +    size_t bp_len;                          /* Quantité de ces données     */ +    uint8_t memory[16];                     /* Sauvegarde de la mémoire    */ + +    result = NULL; + +    /* Si l'utilisation de la commande dédiée est possible */ +    if (1)  //////// TODO +    { +        /* Envoi de la requête */ + +        strcpy(cmd, "Z0,"); + +        status = translate_virt_to_hex(debugger, addr, &cmd[3]); + +        if (!status) +            goto ggdemb_exit; + +        kind = debugger->ops->get_bp_kind(debugger, addr); + +        if (kind == NULL) +            goto ggdemb_exit; + +        strcat(cmd, kind); + +        packet = g_gdb_stream_get_free_packet(debugger->stream); + +        g_gdb_packet_start_new_command(packet); +        g_gdb_packet_append(packet, cmd); + +        status = g_gdb_stream_send_packet(debugger->stream, packet); + +        g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +        if (!status) +            goto ggdemb_exit; + +        /* Réception de la réponse */ + +        packet = g_gdb_stream_recv_packet(debugger->stream); + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        if (is_error_code(data, len)) +        { +            g_gdb_stream_mark_packet_as_free(debugger->stream, packet); +            goto ggdemb_fallback; +        } + +        if (strcmp(data, "OK") != 0) +        { +            g_gdb_stream_mark_packet_as_free(debugger->stream, packet); +            goto ggdemb_fallback; +        } + +        g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +        /* Constitution d'un dossier de suivi */ + +        result = (gdb_breakpoint *)malloc(sizeof(gdb_breakpoint)); + +        result->is_z = true; + +        result->kind = kind; + +    } + +    else +    { + + ggdemb_fallback: + +        dbg = G_BINARY_DEBUGGER(debugger); + +        /* Détermination du point d'arrêt */ + +        bp = debugger->ops->get_bp_data(debugger, addr, &bp_len); + +        assert(bp_len <= 16); + +        /* Sauvegarde de la mémoire courante */ + +        status = g_binary_debugger_read_memory_data(dbg, addr, memory, bp_len); + +        if (!status) goto ggdemb_exit; + +        /* Application du point d'arrêt */ + +        status = g_binary_debugger_write_memory_data(dbg, addr, bp, bp_len); + +        if (!status) goto ggdemb_exit; + +        /* Constitution d'un dossier de suivi */ + +        result = (gdb_breakpoint *)malloc(sizeof(gdb_breakpoint)); + +        result->is_z = false; + +        memcpy(result->memory, memory, bp_len); +        result->len = bp_len; + +    } + +    init_raw_breakpoint((raw_breakpoint *)result, addr); + + ggdemb_exit: + +    return result; +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler ici.                        * +*                bp       = point d'arrêt à traiter.                          * +*                                                                             * +*  Description : Retire un point d'arrêt basique de la mémoire ciblée.        * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_disable_memory_breakpoint(GGdbDebugger *debugger, gdb_breakpoint *bp) +{ +    bool result;                            /* Bilan à retourner           */ +    char cmd[3 + VMPA_MAX_LEN + 3];         /* Commande à émettre          */ +    bool status;                            /* Bilan d'une opération       */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de données reçues  */ +    GBinaryDebugger *dbg;                   /* Autre version du débogueur  */ + +    result = false; + +    /* Si l'utilisation de la commande dédiée est requise */ +    if (bp->is_z) +    { +        /* Envoi de la requête */ + +        strcpy(cmd, "z0,"); + +        status = translate_virt_to_hex(debugger, bp->raw.addr, &cmd[3]); + +        if (!status) +            goto ggddmb_exit; + +        strcat(cmd, bp->kind); + +        packet = g_gdb_stream_get_free_packet(debugger->stream); + +        g_gdb_packet_start_new_command(packet); +        g_gdb_packet_append(packet, cmd); + +        status = g_gdb_stream_send_packet(debugger->stream, packet); + +        g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +        if (!status) +            goto ggddmb_exit; + +        /* Réception de la réponse */ + +        packet = g_gdb_stream_recv_packet(debugger->stream); + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        if (is_error_code(data, len)) +        { +            g_gdb_stream_mark_packet_as_free(debugger->stream, packet); +            goto ggddmb_exit; +        } + +        if (strcmp(data, "OK") != 0) +        { +            g_gdb_stream_mark_packet_as_free(debugger->stream, packet); +            goto ggddmb_exit; +        } + +        g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +        result = true; + +    } + +    else +    { +        dbg = G_BINARY_DEBUGGER(debugger); + +        result = g_binary_debugger_write_memory_data(dbg, bp->raw.addr, bp->memory, bp->len); + +    } + + ggddmb_exit: + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                            CONTROLE DU FLOT D'EXECUTION                            */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à redémarrer.                           * +*                                                                             * +*  Description : Redémarre le processus de débogage lié à un serveur GDB.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_restart(GGdbDebugger *debugger) +{ +    bool result;                            /* Bilan à retourner           */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    return true; +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "R00"); + +    result = g_gdb_stream_send_packet(debugger->stream, packet); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à relancer.                             * +*                                                                             * +*  Description : Remet en marche le débogueur utilisant un serveur GDB.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_debugger_resume(GGdbDebugger *debugger) +{ +    bool result;                            /* Bilan à retourner           */ +    //char *id;                               /* Identifiant de thread       */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    //const char *data;                       /* Données reçues à analyser   */ + +    static bool _twice = false; + + +    if (!_twice && 0) +    { + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "$QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;2c;4c;"); + +    result = g_gdb_stream_send_packet(debugger->stream, packet); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    if (!result) +        goto ggdhmb_exit; + +    } + + + + + + +    /* Envoi de la requête */ + +    /* +    id = g_gdb_debugger_get_active_thread(debugger); +    if (id == NULL) return false; + +    printf("ID : %s\n", id); +    */ + +    /* +    id = g_gdb_support_get_id(debugger->support); +    if (id == NULL) return false; + +    printf("ID : %s\n", id); +    */ + +    packet = g_gdb_stream_get_free_packet(debugger->stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "vCont;c:-1"); +    //g_gdb_packet_append(packet, "vCont;c:p256f.-1"); + + +    /* +    if (_twice) +    { +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "vCont;c:p"); +    g_gdb_packet_append(packet, id); +    g_gdb_packet_append(packet, "."); +    g_gdb_packet_append(packet, id); +    } +    else +    { +        _twice = true; +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "vCont;c:p"); +    g_gdb_packet_append(packet, id); +    g_gdb_packet_append(packet, ".-1"); +    } +    */ + + + + + +    result = g_gdb_stream_send_packet(debugger->stream, packet); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + +    if (!result) +        goto ggdhmb_exit; + +    /* Réception de la réponse */ +    /* +    packet = g_gdb_stream_recv_packet(debugger->stream); + +    g_gdb_packet_get_data(packet, &data, NULL, NULL); + +    printf("Ack cont...\n"); + +    //result = (strcmp(data, "OK") == 0); + +    g_gdb_stream_mark_packet_as_free(debugger->stream, packet); +    */ + ggdhmb_exit: + +    _twice = true; + +    return result; + +} + + + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                          ACCUEIL D'EVENEMENTS ASYNCHRONES                          */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = instance liée à un débogueur GDB à manipuler.     * +*                signum   = indentifiant du signal concerné.                  * +*                                                                             * +*  Description : Réagit à la réception d'un signal par le programme étudié.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_debugger_receive_signal_reply(GGdbDebugger *debugger, int signum) +{ +    virt_t pc;                              /* Position courante du CPU    */ +    bool status;                            /* Bilan d'une opération       */ +    GBinaryDebugger *base;                  /* Version basique du débogueur*/ + +    base = G_BINARY_DEBUGGER(debugger); + +    status = g_binary_debugger_get_current_pc(base, &pc); + +    if (!status) +        pc = VMPA_NO_VIRTUAL; + +    on_binary_debugger_stopped(base, pc); + +    g_signal_emit_by_name(debugger, "signaled", signum); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = instance liée à un débogueur GDB à manipuler.     * +*                status   = indication d'état à la sortie.                    * +*                pid      = éventuel identifiant de processus concerné ou -1. * +*                                                                             * +*  Description : Réagit à la sortie d'exécution d'un programme étudié.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_debugger_receive_exit_reply(GGdbDebugger *debugger, int status, pid_t pid) +{ +    GBinaryDebugger *base;                  /* Version basique du débogueur*/ + +    base = G_BINARY_DEBUGGER(debugger); + +    on_binary_debugger_finished(base, pid); + +    g_signal_emit_by_name(debugger, "exited", status, pid); + +} diff --git a/plugins/gdbrsp/gdb.h b/plugins/gdbrsp/gdb.h new file mode 100644 index 0000000..a338f98 --- /dev/null +++ b/plugins/gdbrsp/gdb.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gdb.h - prototypes pour le débogage à l'aide de gdb. + * + * 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 _DEBUG_GDBRSP_GDB_H +#define _DEBUG_GDBRSP_GDB_H + + +#include <glib-object.h> + + +#include "../debugger.h" + + + +#define G_TYPE_GDB_DEBUGGER            (g_gdb_debugger_get_type()) +#define G_GDB_DEBUGGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_DEBUGGER, GGdbDebugger)) +#define G_IS_GDB_DEBUGGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_DEBUGGER)) +#define G_GDB_DEBUGGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) +#define G_IS_GDB_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_DEBUGGER)) +#define G_GDB_DEBUGGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) + + +/* Débogueur utilisant un serveur GDB (instance) */ +typedef struct _GGdbDebugger GGdbDebugger; + +/* Débogueur utilisant un serveur GDB (classe) */ +typedef struct _GGdbDebuggerClass GGdbDebuggerClass; + + +/* Indique le type défini par la GLib pour le débogueur gdb. */ +GType g_gdb_debugger_get_type(void); + +/* Crée un débogueur utilisant un serveur GDB distant. */ +GBinaryDebugger *g_gdb_debugger_new(GLoadedBinary *, const char *, unsigned short); + + +void test_gdb(void); + + + +#endif  /* _DEBUG_GDBRSP_GDB_H */ diff --git a/plugins/gdbrsp/helpers.c b/plugins/gdbrsp/helpers.c new file mode 100644 index 0000000..1bdf6f7 --- /dev/null +++ b/plugins/gdbrsp/helpers.c @@ -0,0 +1,224 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers.c - assistanat dans la manipulation des paquets GDB + * + * 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 "helpers.h" + + +#include <regex.h> +#include <string.h> + + +#include "gdb-int.h" +#include "utils.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                addr     = emplacement en mémoire à venir consulter.         * +*                out      = zone d'impression en hexadécimal. [OUT]           * +*                                                                             * +*  Description : Traduit une adresse en chaîne hexadécimale pour GDB.         * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool translate_virt_to_hex(const GGdbDebugger *debugger, virt_t addr, char *out) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    uint8_t conv8;                          /* Valeur adaptée sur 8 bits   */ +    uint16_t conv16;                        /* Valeur adaptée sur 16 bits  */ +    uint32_t conv32;                        /* Valeur adaptée sur 32 bits  */ +    uint64_t conv64;                        /* Valeur adaptée sur 64 bits  */ +    char hexval[17];                        /* Valeur sous forme hexa      */ +    bool got_msn;                           /* Obtention d'un quartet ?    */ +    size_t i;                               /* Boucle de parcours          */ + +    /* Conversion */ + +    switch (debugger->msize) +    { +        case MDS_8_BITS: +            conv8 = addr; +            result = u8_to_hex(&conv8, hexval); +            break; + +        case MDS_16_BITS: +            conv16 = addr; +            conv16 = to_u16(&conv16, SRE_BIG); +            result = u16_to_hex(&conv16, hexval); +            break; + +        case MDS_32_BITS: +            conv32 = addr; +            conv32 = to_u32(&conv32, SRE_BIG); +            result = u32_to_hex(&conv32, hexval); +            break; + +        case MDS_64_BITS: +            conv64 = addr; +            conv64 = to_u64(&conv64, SRE_BIG); +            result = u64_to_hex(&conv64, hexval); +            break; + +        default: +            result = false; +            break; + +    } + +    /* On saute les zéros préliminaires... */ + +    if (result) +    { +        got_msn = false; + +        for (i = 0; i < 17; i++) +        { +            if (!got_msn) +            { +                if (hexval[i] == '0') +                    continue; +                else +                    got_msn = true; +            } + +            *out = hexval[i]; +            out++; + +        } + +        *out = '\0'; + +    } + +    return result; + +} + + + + + + + + +/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */ + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = paquet de deonnées à interpréter.                   * +*                sig    = identifiant du signal source. [OUT]                 * +*                addr   = adresse de l'instruction courante. [OUT]            * +*                thread = identifiant du thread concerné. [OUT]               * +*                endian = boutisme de la plateforme ciblée.                   * +*                                                                             * +*  Description : Récupère les informations liées à un arrêt suite à signal.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : Les données sont la forme :                                  * +*                T0505:00000000;04:a08de6bf;08:505878b7;thread:50dc;          * +*                                                                             * +******************************************************************************/ + +bool get_stop_reply_sig_info(const GGdbPacket *packet, int *sig, vmpa_t *addr, pid_t *thread, SourceEndian endian) +{ +    const char *data;                       /* Données brutes du paquet    */ +    size_t length;                          /* Quantité de ces données     */ +    uint8_t index;                          /* Indice de 8 bits quelconque */ +    size_t pos;                             /* Tête de lecture courante    */ +    regex_t preg;                           /* Expression régulière        */ +    int ret;                                /* Bilan d'un appel            */ +    regmatch_t pmatch[3];                   /* Zones remarquées            */ +    size_t key_len;                         /* Taille de l'indicatif       */ + +    *addr = 0ull; + +    g_gdb_packet_get_data(packet, &data, &length, NULL); + +    pos = 1; + +    /* Lecture du numéro du signal */ + +    if (!strtou8(&index, data, &pos, length, SRE_LITTLE)) +        return false; + +    *sig = index; + +    /* Reste des informations */ + +    ret = regcomp(&preg, "([^:]+):([^;]+);", REG_EXTENDED | REG_ICASE); +    if (ret != 0) return false; + +    for (ret = regexec(&preg, &data[pos], 3, pmatch, 0); +         ret != REG_NOMATCH; +         ret = regexec(&preg, &data[pos], 3, pmatch, 0)) +    { +        key_len = pmatch[1].rm_eo - pmatch[1].rm_so; + +        /* Indication sur le thread */ +        if (key_len == strlen("thread") +            && strncmp(&data[pos + pmatch[1].rm_so], "thread", key_len) == 0) +        { + +            /* TODO printf("Thread found !\n"); */ + +        } + +        /* Valeur de registre ? */ +        else if (key_len == 2) +        { +            if (!strtou8(&index, data, (size_t []) { pos + pmatch[1].rm_so }, length, SRE_LITTLE)) +                return false; + +            if (index != 8 /* FIXME */) +                goto next_field; + +            if (!strtou32(addr, data, (size_t []) { pos + pmatch[2].rm_so }, length, SRE_LITTLE/* FIXME */)) +                return false; + +        } + +    next_field: +        pos += pmatch[0].rm_eo; + +    } + +    regfree(&preg); + +    return (*addr != 0ull); + +} + + + diff --git a/plugins/gdbrsp/helpers.h b/plugins/gdbrsp/helpers.h new file mode 100644 index 0000000..0492ea3 --- /dev/null +++ b/plugins/gdbrsp/helpers.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers.h - prototypes pour un assistanat dans la manipulation des paquets GDB + * + * 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 _DEBUG_GDBRSP_HELPERS_H +#define _DEBUG_GDBRSP_HELPERS_H + + +#include "gdb.h" +#include "packet.h" + + + +/* Traduit une adresse en chaîne hexadécimale pour GDB. */ +bool translate_virt_to_hex(const GGdbDebugger *, virt_t, char *); + + + + + + +/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */ + + +/* Récupère les informations liées à un arrêt suite à signal. */ +bool get_stop_reply_sig_info(const GGdbPacket *, int *, vmpa_t *, pid_t *, SourceEndian); + + + +/* ---------------------------------------------------------------------------------- */ +/*                            PAQUETS DES REPONSES D'ARRET                            */ +/* ---------------------------------------------------------------------------------- */ + + + + + + + + + + +#endif  /* _DEBUG_GDBRSP_HELPERS_H */ diff --git a/plugins/gdbrsp/helpers_arm.c b/plugins/gdbrsp/helpers_arm.c new file mode 100644 index 0000000..4b486d4 --- /dev/null +++ b/plugins/gdbrsp/helpers_arm.c @@ -0,0 +1,252 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers_arm.c - compléments utiles à GDB pour l'architecture ARM + * + * Copyright (C) 2016 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 "helpers_arm.h" + + +#include <malloc.h> +#include <string.h> + + +#include "gdb-int.h" + + + +/* Détermine le point d'exécution courant. */ +static bool get_arm_pc(GGdbDebugger *, virt_t *); + +/* Remonte la pile d'appels jusqu'au point courant. */ +static bool compute_call_stack_for_arm(const GGdbDebugger *, virt_t **, size_t *); + +/* Complète la commande manipulant des points d'arrêt. */ +static const char *get_breakpoint_kind_for_arm(const GGdbDebugger *, virt_t); + +/* Construit une instruction provoquant un arrêt d'exécution. */ +static const uint8_t *get_arm_breakpoint_data(const GGdbDebugger *, virt_t, size_t *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit les fonctions adaptées aux opérations pour ARM.      * +*                                                                             * +*  Retour      : Opérations spécifiques adaptées à ARM.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const gdb_arch_ops *get_arm_operations(void) +{ +    static const gdb_arch_ops arm_ops = { + +        .get_pc = get_arm_pc, +        .compute_cstack = compute_call_stack_for_arm, +        .get_bp_kind = get_breakpoint_kind_for_arm, +        .get_bp_data = get_arm_breakpoint_data + +    }; + +    return &arm_ops; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à consulter.                            * +*                pc       = adresse de l'instruction courante. [OUT]          * +*                                                                             * +*  Description : Détermine le point d'exécution courant.                      * +*                                                                             * +*  Retour      : Bilan de la récupération.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool get_arm_pc(GGdbDebugger *debugger, virt_t *pc) +{ +    bool result;                            /* Bilan à retourner           */ +    uint32_t value; + +    result = g_binary_debugger_read_register_u32(G_BINARY_DEBUGGER(debugger), "pc", &value); + +    if (result) +        *pc = value; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger  = débogueur à consulter.                           * +*                callstack = pile d'appels reconstituée. [OUT]                * +*                size      = taille de cette pile. [OUT]                      * +*                                                                             * +*  Description : Remonte la pile d'appels jusqu'au point courant.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool compute_call_stack_for_arm(const GGdbDebugger *debugger, virt_t **callstack, size_t *size) +{ +    bool result;                            /* Bilan global à retourner    */ +    GBinaryDebugger *base;                  /* Version basique d'instance  */ +    uint32_t lr;                            /* Retour de fonction          */ +    uint32_t fp;                            /* Pointeur de cadre à suivre  */ + +    base = G_BINARY_DEBUGGER(debugger); + +    result = g_binary_debugger_read_register_u32(base, "lr", &lr); + +    if (result && lr != 0) +    { +        *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); + +        (*callstack)[*size - 1] = lr; + +    } + +    result &= g_binary_debugger_read_register_u32(base, "r11", &fp); + +    while (result && fp != 0) +    { +        /** +         * fp[-0] : pc sauvegardé +         * fp[-1] : lr sauvegardé +         * fp[-2] : sp précédent +         * fp[-3] : fp précédent +         */ + +        result = g_binary_debugger_read_memory_u32(base, fp - 2 * sizeof(uint32_t), &lr); +        if (!result) break; + +        if (lr != 0) +        { +            *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); + +            (*callstack)[*size - 1] = lr; + +        } + +        result = g_binary_debugger_read_memory_u32(base, fp - 4 * sizeof(uint32_t), &fp); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler ici.                        * +*                virt     = emplacement du point mémoire à traiter.           * +*                                                                             * +*  Description : Complète la commande manipulant des points d'arrêt.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static const char *get_breakpoint_kind_for_arm(const GGdbDebugger *debugger, virt_t virt) +{ +    const char *result;                     /* Indication à retourner      */ +    GArchProcessor *proc;                   /* Processeur lié au binaire   */ +    vmpa2t addr;                            /* Format d'adresse complet    */ +    GArchInstruction *instr;                /* Instruction ciblée          */ +    const char *encoding;                   /* Encodage de l'instruction   */ + +    proc = g_loaded_binary_get_processor(G_BINARY_DEBUGGER(debugger)->binary); + +    init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); +    instr = g_arch_processor_find_instr_by_address(proc, &addr); + +    if (instr == NULL) +        result = NULL; + +    else +    { +        encoding = g_arch_instruction_get_encoding(instr); + +        if (strcmp(encoding, "Thumb/16") == 0) +            result = ",2"; + +        if (strcmp(encoding, "Thumb/32") == 0) +            result = ",3"; + +        if (strcmp(encoding, "ARM") == 0) +            result = ",4"; + +        else +            result = NULL; + +        g_object_unref(G_OBJECT(instr)); + +    } + +    g_object_unref(G_OBJECT(proc)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler ici.                        * +*                addr     = emplacement du point mémoire à traiter.           * +*                len      = quantité de mémoire à remplacer. [OUT]            * +*                                                                             * +*  Description : Construit une instruction provoquant un arrêt d'exécution.   * +*                                                                             * +*  Retour      : Définition du point d'arrêt à placer à l'adresse donnée.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static const uint8_t *get_arm_breakpoint_data(const GGdbDebugger *debugger, virt_t addr, size_t *len) +{ +    const uint8_t *result;                  /* Données à placer en mémoire */ + +    /* Version point d'arrêt */ +    static const uint32_t bkpt_code[] = { 0xe1200070 }; + +    *len = sizeof(bkpt_code);; + +    result = (const uint8_t *)bkpt_code; + +    return result; + +} diff --git a/plugins/gdbrsp/helpers_arm.h b/plugins/gdbrsp/helpers_arm.h new file mode 100644 index 0000000..ec82b27 --- /dev/null +++ b/plugins/gdbrsp/helpers_arm.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers_arm.h - prototypes pour les compléments utiles à GDB pour l'architecture ARM + * + * Copyright (C) 2016 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 _DEBUG_GDBRSP_HELPERS_ARM_H +#define _DEBUG_GDBRSP_HELPERS_ARM_H + + +#include "aops.h" + + + +/* Fournit les fonctions adaptées aux opérations pour ARM. */ +const gdb_arch_ops *get_arm_operations(void); + + + +#endif  /* _DEBUG_GDBRSP_HELPERS_ARM_H */ diff --git a/plugins/gdbrsp/helpers_arm64.c b/plugins/gdbrsp/helpers_arm64.c new file mode 100644 index 0000000..810c8b3 --- /dev/null +++ b/plugins/gdbrsp/helpers_arm64.c @@ -0,0 +1,97 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers_arm64.c - compléments utiles à GDB pour l'architecture AArch64 + * + * Copyright (C) 2016 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 "helpers_arm64.h" + + +#include <malloc.h> + + +#include "gdb-int.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger  = débogueur à consulter.                           * +*                callstack = pile d'appels reconstituée. [OUT]                * +*                size      = taille de cette pile. [OUT]                      * +*                                                                             * +*  Description : Remonte la pile d'appels jusqu'au point courant.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool compute_call_stack_for_arm64(GGdbDebugger *debugger, virt_t **callstack, size_t *size) +{ +    bool result;                            /* Bilan global à retourner    */ +    GBinaryDebugger *base;                  /* Version basique d'instance  */ +    uint64_t fp;                            /* Pointeur de cadre à suivre  */ +    uint64_t previous;                      /* Appel de fonction précédent */ + +    base = G_BINARY_DEBUGGER(debugger); + +    result = g_binary_debugger_read_register_u64(base, "x29", &fp); + +    while (result && fp != 0) +    { +        result = g_binary_debugger_read_memory_u64(base, fp + sizeof(uint64_t), &previous); +        if (!result) break; + +        *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); + +        (*callstack)[*size - 1] = previous; + +        result = g_binary_debugger_read_memory_u64(base, fp, &fp); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : debugger = débogueur à manipuler ici.                        * +*                addr     = emplacement du point mémoire à traiter.           * +*                cmd      = commande en cours de constitution. [OUT]          * +*                                                                             * +*  Description : Complète la commande manipulant des points d'arrêt.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool fill_memory_breakpoint_cmd_for_arm64(GGdbDebugger *debugger, virt_t addr, char *cmd) +{ +    strcat(cmd, ",4"); + +    return true; + +} diff --git a/plugins/gdbrsp/helpers_arm64.h b/plugins/gdbrsp/helpers_arm64.h new file mode 100644 index 0000000..5e89deb --- /dev/null +++ b/plugins/gdbrsp/helpers_arm64.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers_arm64.h - prototypes pour les compléments utiles à GDB pour l'architecture AArch64 + * + * Copyright (C) 2016 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 _DEBUG_GDBRSP_HELPERS_ARM64_H +#define _DEBUG_GDBRSP_HELPERS_ARM64_H + + +#include "gdb.h" + + + +/* Remonte la pile d'appels jusqu'au point courant. */ +bool compute_call_stack_for_arm64(GGdbDebugger *, virt_t **, size_t *); + +/* Complète la commande manipulant des points d'arrêt. */ +bool fill_memory_breakpoint_cmd_for_arm64(GGdbDebugger *, virt_t, char *); + + + +#endif  /* _DEBUG_GDBRSP_HELPERS_ARM64_H */ diff --git a/plugins/gdbrsp/packet.c b/plugins/gdbrsp/packet.c new file mode 100644 index 0000000..806c6b0 --- /dev/null +++ b/plugins/gdbrsp/packet.c @@ -0,0 +1,389 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * packet.c - manipulation des paquets de données GDB. + * + * 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 "packet.h" + + +#include <malloc.h> +#include <string.h> + + +#include "../../common/dllist.h" + + + +/* Répresentation d'un paquet GDB (instance) */ +struct _GGdbPacket +{ +    GObject parent;                         /* A laisser en premier        */ + +    DL_LIST_ITEM(link);                     /* Lien vers les autres        */ + +    char *buffer;                           /* Données à traiter           */ +    size_t len;                             /* Quantité de ces données     */ +    size_t allocated;                       /* Taille du tampon            */ + +    uint8_t checksum;                       /* Empreinte de contrôle       */ + +}; + + +/* Répresentation d'un paquet GDB (classe) */ +struct _GGdbPacketClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Initialise la classe des représentations des paquets GDB. */ +static void g_gdb_packet_class_init(GGdbPacketClass *); + +/* Initialise une instance de représentation de paquet GDB. */ +static void g_gdb_packet_init(GGdbPacket *); + + + +/* Indique le type défini pour une répresentation de paquet GDB. */ +G_DEFINE_TYPE(GGdbPacket, g_gdb_packet, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des représentations des paquets GDB.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_packet_class_init(GGdbPacketClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une instance de représentation de paquet GDB.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_packet_init(GGdbPacket *packet) +{ +    DL_LIST_ITEM_INIT(&packet->link); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée une représentation de paquet GDB.                       * +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbPacket *g_gdb_packet_new(void) +{ +    GGdbPacket *result;                     /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_GDB_PACKET, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = paquet à préparer pour une émission.                * +*                                                                             * +*  Description : Prépare un paquet pour un envoi prochain.                    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_packet_start_new_command(GGdbPacket *packet) +{ +    if (packet->allocated == 0) +    { +        packet->allocated = 1; +        packet->buffer = (char *)calloc(packet->allocated, sizeof(char)); +    } + +    packet->buffer[0] = '\0'; +    packet->len = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = paquet à préparer pour une émission.                * +*                string = chaîne à inclure dans le paquet.                    * +*                                                                             * +*  Description : Complète un paquet pour un envoi prochain.                   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_packet_append(GGdbPacket *packet, const char *string) +{ +    size_t len;                             /* Taille de la chaîne donnée  */ + +    len = strlen(string); + +    /* Si la place n'est pas assez grande */ +    if ((packet->len + len + 1) > packet->allocated) +    { +        packet->buffer = (char *)realloc(packet->buffer, (packet->len + len + 1) * sizeof(char)); +        packet->allocated = packet->len + len + 1; +    } + + +    memcpy(packet->buffer + packet->len, string, len + 1); +    //strcat(packet->buffer, string); + +    packet->len += len; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = paquet à analyser.                                  * +*                                                                             * +*  Description : Détermine l'empreinte des données d'un paquet GDB.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_packet_compute_checksum(GGdbPacket *packet) +{ +    int sum;                                /* Valeur cumulée des données  */ +    size_t i;                               /* Boucle de parcours          */ + +    sum = 0; + +    for (i = 0; i < packet->len; i++) +        sum += packet->buffer[i]; + +    packet->checksum = sum % 256; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet   = paquet à analyser.                                * +*                checksum = contrôle d'intégrité à retrouver.                 * +*                                                                             * +*  Description : Contrôle l'intégrité des données d'un paquet GDB.            * +*                                                                             * +*  Retour      : Bilan de la vérification.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_gdb_packet_verify_checksum(GGdbPacket *packet, uint8_t checksum) +{ +    g_gdb_packet_compute_checksum(packet); + +    return checksum == packet->checksum; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet = paquet à décoder et/ou décompresser.                * +*                                                                             * +*  Description : Décode et/ou décompresse un paquet GDB.                      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_gdb_packet_decode(GGdbPacket *packet) +{ +    bool result;                            /* Bilan à retourner           */ +    char *buffer;                           /* Données transcrites         */ +    size_t allocated;                       /* Quantité de données gérées  */ +    size_t i;                               /* Boucle de parcours          */ +    size_t k;                               /* Point d'insertion           */ +    size_t repeat;                          /* Nombre de répétitions       */ + +    result = true; + +    allocated = packet->len + 1; +    buffer = (char *)calloc(allocated, sizeof(char)); + +    for (i = 0, k = 0; i < packet->len && result; i++) +        switch (packet->buffer[i]) +        { +            case '#': +            case '$': +                result = false; +                break; + +            case '*': + +                if (++i == packet->len || k == 0) +                { +                    result = false; +                    break; +                } + +                repeat = packet->buffer[i] - ' ' + 3; + +                allocated += repeat; +                buffer = (char *)realloc(buffer, allocated * sizeof(char)); + +                memset(&buffer[k], buffer[k - 1], repeat); +                k += repeat; + +                break; + +            case '}': + +                if (++i == packet->len) +                { +                    result = false; +                    break; +                } + +                buffer[k++] = packet->buffer[i] ^ 0x20; + +                break; + +            default: +                buffer[k++] = packet->buffer[i]; +                break; + +        } + +    if (packet->buffer != NULL) +        free(packet->buffer); + +    buffer[k] = '\0'; + +    packet->buffer = buffer; +    packet->len = k; +    packet->allocated = allocated; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : packet   = paquet à analyser.                                * +*                data     = données contenues dans le paquet. [OUT]           * +*                len      = quantité de ces données ou NULL. [OUT]            * +*                checksum = contrôle d'intégrité des données ou NULL. [OUT]   * +*                                                                             * +*  Description : Fournit le contenu du paquet.                                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_packet_get_data(const GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum) +{ +    *data = packet->buffer; + +    if (len != NULL) +        *len = packet->len; + +    if (checksum != NULL) +        *checksum = packet->checksum; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list = liste de paquets à compléter.                         * +*                item = paquet à ajouter à la liste.                          * +*                                                                             * +*  Description : Ajoute un paquet à une liste de paquets.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_packet_push(GGdbPacket **list, GGdbPacket *item) +{ +    dl_list_push(item, list, GGdbPacket, link); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list = liste de paquets à consulter.                         * +*                                                                             * +*  Description : Retire et fournit le premier élément d'une liste de paquets. * +*                                                                             * +*  Retour      : Elément dépilé de la liste de paquets.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbPacket *g_gdb_packet_pop(GGdbPacket **list) +{ +    return dl_list_pop(list, GGdbPacket, link); + +} diff --git a/plugins/gdbrsp/packet.h b/plugins/gdbrsp/packet.h new file mode 100644 index 0000000..7f362bd --- /dev/null +++ b/plugins/gdbrsp/packet.h @@ -0,0 +1,82 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * packet.h - prototypes pour la manipulation des paquets de données GDB. + * + * 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 _DEBUG_GDBRSP_PACKET_H +#define _DEBUG_GDBRSP_PACKET_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <stdint.h> + + + +#define G_TYPE_GDB_PACKET               g_gdb_packet_get_type() +#define G_GDB_PACKET(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_packet_get_type(), GGdbPacket)) +#define G_IS_GDB_PACKET(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_packet_get_type())) +#define G_GDB_PACKET_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_PACKET, GGdbPacketClass)) +#define G_IS_GDB_PACKET_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_PACKET)) +#define G_GDB_PACKET_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_PACKET, GGdbPacketClass)) + + +/* Répresentation d'un paquet GDB (instance) */ +typedef struct _GGdbPacket GGdbPacket; + +/* Répresentation d'un paquet GDB (classe) */ +typedef struct _GGdbPacketClass GGdbPacketClass; + + + +/* Indique le type défini pour une répresentation de paquet GDB. */ +GType g_gdb_packet_get_type(void); + +/* Crée une représentation de paquet GDB. */ +GGdbPacket *g_gdb_packet_new(void); + +/* Prépare un paquet pour un envoi prochain. */ +void g_gdb_packet_start_new_command(GGdbPacket *); + +/* Complète un paquet pour un envoi prochain. */ +void g_gdb_packet_append(GGdbPacket *, const char *); + +/* Détermine l'empreinte des données d'un paquet GDB. */ +void g_gdb_packet_compute_checksum(GGdbPacket *); + +/* Contrôle l'intégrité des données d'un paquet GDB. */ +bool g_gdb_packet_verify_checksum(GGdbPacket *, uint8_t); + +/* Décode et/ou décompresse un paquet GDB. */ +bool g_gdb_packet_decode(GGdbPacket *); + +/* Fournit le contenu du paquet. */ +void g_gdb_packet_get_data(const GGdbPacket *, const char **, size_t *, uint8_t *); + +/* Ajoute un paquet à une liste de paquets. */ +void g_gdb_packet_push(GGdbPacket **, GGdbPacket *); + +/* Retire et fournit le premier élément d'une liste de paquets. */ +GGdbPacket *g_gdb_packet_pop(GGdbPacket **); + + + +#endif  /* _DEBUG_GDBRSP_PACKET_H */ diff --git a/plugins/pychrysalide/debug/gdbrsp/Makefile.am b/plugins/gdbrsp/python/Makefile.am index 8ece12b..8ece12b 100644 --- a/plugins/pychrysalide/debug/gdbrsp/Makefile.am +++ b/plugins/gdbrsp/python/Makefile.am diff --git a/plugins/pychrysalide/debug/gdbrsp/gdb.c b/plugins/gdbrsp/python/gdb.c index 77b72b0..77b72b0 100644 --- a/plugins/pychrysalide/debug/gdbrsp/gdb.c +++ b/plugins/gdbrsp/python/gdb.c diff --git a/plugins/pychrysalide/debug/gdbrsp/gdb.h b/plugins/gdbrsp/python/gdb.h index 057a38d..057a38d 100644 --- a/plugins/pychrysalide/debug/gdbrsp/gdb.h +++ b/plugins/gdbrsp/python/gdb.h diff --git a/plugins/pychrysalide/debug/gdbrsp/module.c b/plugins/gdbrsp/python/module.c index c077aa7..c077aa7 100644 --- a/plugins/pychrysalide/debug/gdbrsp/module.c +++ b/plugins/gdbrsp/python/module.c diff --git a/plugins/pychrysalide/debug/gdbrsp/module.h b/plugins/gdbrsp/python/module.h index 0ed3719..0ed3719 100644 --- a/plugins/pychrysalide/debug/gdbrsp/module.h +++ b/plugins/gdbrsp/python/module.h diff --git a/plugins/gdbrsp/stream-int.h b/plugins/gdbrsp/stream-int.h new file mode 100644 index 0000000..ab26dc2 --- /dev/null +++ b/plugins/gdbrsp/stream-int.h @@ -0,0 +1,89 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * stream-int.h - prototypes internes pour la gestion des connexions aux serveurs GDB. + * + * 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 _DEBUG_GDBRSP_STREAM_INT_H +#define _DEBUG_GDBRSP_STREAM_INT_H + + +#include "gdb.h" +#include "stream.h" + + + +/* Envoie des données à un serveur GDB. */ +typedef bool (* send_gdb_data_fc) (GGdbStream *, const char *, size_t); + +/* Réceptionne un octet de donnée d'un serveur GDB. */ +typedef bool (* recv_gdb_byte_fc) (GGdbStream *, char *); + + +/* Flux de communication avec un serveur GDB (instance) */ +struct _GGdbStream +{ +    GObject parent;                         /* A laisser en premier        */ + +    int fd;                                 /* Flux ouvert en L./E.        */ + +    GGdbDebugger *owner;                    /* Propriétaire du flux        */ + +    send_gdb_data_fc send_data;             /* Envoi d'un paquet GDB       */ +    recv_gdb_byte_fc recv_byte;             /* Réception d'un paquet GDB   */ + +    GThread *listening;                     /* Thread pour les réceptions  */ + +    GGdbPacket *free_packets;               /* Liste des disponibles       */ +    GMutex free_mutex;                      /* Accès à la liste            */ + +    GGdbPacket *recv_packets;               /* Liste des paquets reçus     */ +    GCond recv_cond;                        /* Attente de disponibilité    */ +    GMutex recv_mutex;                      /* Accès à la liste            */ + +    GGdbPacket *status_packets;             /* Liste des paquets d'état    */ +    GCond status_cond;                      /* Attente de disponibilité    */ +    GMutex status_mutex;                    /* Accès à la liste            */ + + + + +    bool skip_ack; + +    bool want_status; + + +}; + + +/* Flux de communication avec un serveur GDB (classe) */ +struct _GGdbStreamClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Lance l'écoute d'un flux de communication avec GDB. */ +bool g_gdb_stream_listen(GGdbStream *); + + + +#endif  /* _DEBUG_GDBRSP_STREAM_INT_H */ diff --git a/plugins/gdbrsp/stream.c b/plugins/gdbrsp/stream.c new file mode 100644 index 0000000..f86f630 --- /dev/null +++ b/plugins/gdbrsp/stream.c @@ -0,0 +1,696 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * stream.c - gestion des connexions aux serveurs GDB. + * + * 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 "stream.h" + + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <glib/gthread.h> +#include <sys/select.h> + + +#include "gdb-int.h" +#include "stream-int.h" +#include "utils.h" +#include "../../common/dllist.h" +#include "../../core/logs.h" + + + +/* Initialise la classe des flux de communication avec GDB. */ +static void g_gdb_stream_class_init(GGdbStreamClass *); + +/* Initialise une instance de flux de communication avec GDB. */ +static void g_gdb_stream_init(GGdbStream *); + +/* Supprime toutes les références externes. */ +static void g_gdb_stream_dispose(GGdbStream *); + +/* Procède à la libération totale de la mémoire. */ +static void g_gdb_stream_finalize(GGdbStream *); + +/* Envoie un acquittement pour la dernière réception. */ +static bool gdb_stream_ack(GGdbStream *); + +/* Ecoute une connexion à un serveur GDB. */ +static void *gdb_stream_thread(GGdbStream *); + +/* Reste en alerte quant au changement de statut de l'exécution. */ +static void *gdb_stream_status_thread(GGdbStream *); + +/* Réceptionne un paquet d'un serveur GDB. */ +static bool g_gdb_stream_read_packet(GGdbStream *, GGdbPacket *); + + + +/* Indique le type défini pour un flux de communication avec un serveur GDB. */ +G_DEFINE_TYPE(GGdbStream, g_gdb_stream, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des flux de communication avec GDB.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_stream_class_init(GGdbStreamClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_stream_dispose; +    object->finalize = (GObjectFinalizeFunc)g_gdb_stream_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une instance de flux de communication avec GDB.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_stream_init(GGdbStream *stream) +{ +    g_mutex_init(&stream->free_mutex); + +    g_cond_init(&stream->recv_cond); +    g_mutex_init(&stream->recv_mutex); + +    g_cond_init(&stream->status_cond); +    g_mutex_init(&stream->status_mutex); + +    stream->skip_ack = false; + +    stream->want_status = false; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_stream_dispose(GGdbStream *stream) +{ +    g_object_unref(G_OBJECT(stream->owner)); + + +    /* TODO... */ + + +    G_OBJECT_CLASS(g_gdb_stream_parent_class)->dispose(G_OBJECT(stream)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_stream_finalize(GGdbStream *stream) +{ + +    /* TODO */ + + +    G_OBJECT_CLASS(g_gdb_stream_parent_class)->finalize(G_OBJECT(stream)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = instance à modifier.                                * +*                                                                             * +*  Description : Ne participe plus aux acquitements de paquets.               * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_stream_do_not_ack(GGdbStream *stream) +{ +    stream->skip_ack = true; + +} + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = instance à réellement lancer.                       * +*                                                                             * +*  Description : Lance l'écoute d'un flux de communication avec GDB.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_gdb_stream_listen(GGdbStream *stream) +{ +    bool result;                            /* Bilan final à retourner     */ + +    result = true; + +    if (!g_thread_new("chrysalide_gdb_stream", (GThreadFunc)gdb_stream_thread, stream)) +        result = false; + +    if (!g_thread_new("chrysalide_gdb_status", (GThreadFunc)gdb_stream_status_thread, stream)) +        result = false; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = encadrement associée à l'opération.                 * +*                                                                             * +*  Description : Envoie un acquittement pour la dernière réception.           * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool gdb_stream_ack(GGdbStream *stream) +{ +    /// +    //return true; + +    bool result;                            /* Bilan à retourner           */ +    GGdbPacket *packet;                     /* Paquet à envoyer            */ + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "+"); + +    result = g_gdb_stream_send_packet(stream, packet); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = encadrement associée à l'opération.                 * +*                                                                             * +*  Description : Ecoute une connexion à un serveur GDB.                       * +*                                                                             * +*  Retour      : ???                                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void *gdb_stream_thread(GGdbStream *stream) +{ +    fd_set rfds;                            /* Liste des flux à surveiller */ +    int ret;                                /* Bilan d'un appel            */ +    GGdbPacket *packet;                     /* Nouveau paquet reçu         */ + + +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de ces données     */ + + + +    while (1) +    { +        FD_ZERO(&rfds); +        FD_SET(stream->fd, &rfds); + +        ret = select(stream->fd + 1, &rfds, NULL, NULL, NULL); + +        switch (ret) +        { +            case -1: +                perror("select()"); +                break; + +            case 0: +                break; + +            default: + +                packet = g_gdb_stream_get_free_packet(stream); + +                g_gdb_packet_start_new_command(packet); + +                if (g_gdb_stream_read_packet(stream, packet)) +                { +                    /* Acquittement ? */ +                    if (!stream->skip_ack) +                    { +                        if (!gdb_stream_ack(stream)) goto bad_recv; +                    } + + +                    /* On conserve le résultat ? */ + + +                    g_gdb_packet_get_data(packet, &data, &len, NULL); + + +                    //printf("---------------------------\n"); +                    //printf(">> want status ? %d\n", stream->want_status); +                    //printf(">> got '%s'\n", data); + + +                    if (len >= 1) +                    { +                        if (stream->want_status) +                            stream->want_status = false; + +                        else if (index("STWX", data[0]) != NULL) +                        { +                            g_mutex_lock(&stream->status_mutex); +                            g_gdb_packet_push(&stream->status_packets, packet); +                            g_mutex_unlock(&stream->status_mutex); + +                            g_cond_signal(&stream->status_cond); + +                            break; +                        } + +                        // else message inconnu -> log_message() ! + +                    } + + + + +                    g_mutex_lock(&stream->recv_mutex); +                    g_gdb_packet_push(&stream->recv_packets, packet); +                    g_mutex_unlock(&stream->recv_mutex); + +                    g_cond_signal(&stream->recv_cond); + +                } + +                else +                    g_gdb_stream_mark_packet_as_free(stream, packet); + +                break; + + bad_recv: + +                printf("bad things happend...\n"); + +                g_gdb_stream_mark_packet_as_free(stream, packet); + +                break; + +        } + +    } + + +    printf("Oh noes....\n"); + + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = encadrement associée à l'opération.                 * +*                                                                             * +*  Description : Reste en alerte quant au changement de statut de l'exécution.* +*                                                                             * +*  Retour      : ???                                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void *gdb_stream_status_thread(GGdbStream *stream) +{ +    GGdbPacket *packet;                     /* Nouveau paquet reçu         */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de ces données     */ +    bool malformed;                         /* Echec d'interprétation      */ +    uint8_t byte;                           /* Valeur quelconque sur 8 bits*/ +    bool ret;                               /* Bilan d'un appel            */ + +    while (1) +    { +        /* Réception d'un nouveau paquet de statut */ + +        g_mutex_lock(&stream->status_mutex); + +        if (dl_list_empty(stream->status_packets)) +            g_cond_wait(&stream->status_cond, &stream->status_mutex); + +        packet = g_gdb_packet_pop(&stream->status_packets); + +        g_mutex_unlock(&stream->status_mutex); + +        /* Traitement du paquet reçu */ + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        malformed = false; + +        switch (data[0]) +        { +            case 'S': + +                ret = read_fixed_byte(data + 1, len - 1, &byte); + +                if (!ret) +                { +                    malformed = true; +                    goto gsst_processed; +                } + +                g_gdb_debugger_receive_signal_reply(stream->owner, byte); +                break; + +            case 'T': +                assert(false);  // TODO +                break; + +            case 'W': + +                ret = read_fixed_byte(data + 1, len - 1, &byte); + +                if (!ret) +                { +                    malformed = true; +                    goto gsst_processed; +                } + + +                // TODO : ";process:pid" + + +                printf("Program exited (status=%hhu)\n", byte); + + +                g_gdb_debugger_receive_exit_reply(stream->owner, byte, -1); + + +                // log_message en cas de mauvais format... + + +                break; + + +            default: +                assert(false); +                break; + +        } + + gsst_processed: + +        if (malformed && true/* TODO : config->show_... */) +            log_variadic_message(LMT_WARNING, "Malformed GDB status reply: '%s'", data); + +        g_gdb_stream_mark_packet_as_free(stream, packet); + +    } + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux de communication avec GDB à consulter.         * +*                                                                             * +*  Description : Fournit un paquet prêt à emploi.                             * +*                                                                             * +*  Retour      : Paquet prêt à emploi.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *stream) +{ +    GGdbPacket *result;                     /* Paquet à retourner          */ + +    g_mutex_lock(&stream->free_mutex); + +    if (dl_list_empty(stream->free_packets)) +        result = g_gdb_packet_new(); + +    else +        result = g_gdb_packet_pop(&stream->free_packets); + +    g_mutex_unlock(&stream->free_mutex); + +    // ??? +    //g_gdb_packet_start_new_command(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux de communication avec GDB à mettre à jour.     * +*                packet = paquet à considérer comme disponible.               * +*                                                                             * +*  Description : Place un paquet en attente d'une future utilisation.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_gdb_stream_mark_packet_as_free(GGdbStream *stream, GGdbPacket *packet) +{ +    //// Utile ? +    g_gdb_packet_start_new_command(packet); + + +    g_mutex_lock(&stream->free_mutex); + +    g_gdb_packet_push(&stream->free_packets, packet); + +    g_mutex_unlock(&stream->free_mutex); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux ouvert en lecture  à utiliser.                 * +*                packet = données à recevoir.                                 * +*                                                                             * +*  Description : Réceptionne un paquet d'un serveur GDB.                      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_stream_read_packet(GGdbStream *stream, GGdbPacket *packet) +{ +    bool result;                            /* Bilan à renvoyer            */ +    char tmp[3];                            /* Tampon de réception         */ +    uint8_t checksum;                       /* Contrôle d'intégrité        */ + +    do +    { +        result = stream->recv_byte(stream, tmp); +        if (tmp[0] != '+') break; +    } +    while (0); + +    if (tmp[0] != '$') return false; + +    tmp[1] = '\0'; + +    while ((result = stream->recv_byte(stream, tmp))) +    { +        //printf(" .. '%c'\n", tmp[0]); + +        if (tmp[0] == '#') break; +        else g_gdb_packet_append(packet, tmp); +    } + +    if (result) +    { +        result = stream->recv_byte(stream, &tmp[0]); +        result &= stream->recv_byte(stream, &tmp[1]); + +        tmp[2] = 0; +        checksum = strtol(tmp, NULL, 16); + +    } + +    if (result) +        result = g_gdb_packet_verify_checksum(packet, checksum); + +    if (result) +        result = g_gdb_packet_decode(packet); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux ouvert en écriture à mettre à jour.            * +*                packet = données à transmettre.                              * +*                                                                             * +*  Description : Envoie un paquet à un serveur GDB.                           * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +#include <string.h> +bool g_gdb_stream_send_packet(GGdbStream *stream, GGdbPacket *packet) +{ +    bool result;                            /* Bilan à renvoyer            */ +    const char *data;                       /* Données à envoyer           */ +    size_t len;                             /* Quantité de ces données     */ +    uint8_t checksum;                       /* Contrôle d'intégrité        */ +    char tmp[3];                            /* Impression du checksum      */ + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +#if 1 +    /* Ack ? */ +    if (len == 1 && data[0] == '+') +        result = stream->send_data(stream, "+", 1); + +    else +#endif +    { + +    result = stream->send_data(stream, "$", 1); +    //result = stream->send_data(stream, "+$", 2); + +    g_gdb_packet_compute_checksum(packet); +    g_gdb_packet_get_data(packet, &data, &len, &checksum); + + +    if (len == 1 && data[0] == '?') +        stream->want_status = true; + +    /* +    if (memcmp(data, "vCont;c", strlen("vCont;c")) == 0) +        stream->want_status = true; +    */ + + + +    result &= stream->send_data(stream, data, len); + +    result = stream->send_data(stream, "#", 1); + +    snprintf(tmp, 3, "%02hhx", checksum); +    result &= stream->send_data(stream, tmp, 2); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux de communication avec GDB à consulter.         * +*                                                                             * +*  Description : Fournit un paquet reçu d'un serveur GDB.                     * +*                                                                             * +*  Retour      : Paquet GDB.                                                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *stream) +{ +    GGdbPacket *result;                     /* Paquet à retourner          */ + +    g_mutex_lock(&stream->recv_mutex); + +    if (dl_list_empty(stream->recv_packets)) +        g_cond_wait(&stream->recv_cond, &stream->recv_mutex); + +    result = g_gdb_packet_pop(&stream->recv_packets); + +    g_mutex_unlock(&stream->recv_mutex); + +    return result; + +} diff --git a/plugins/gdbrsp/stream.h b/plugins/gdbrsp/stream.h new file mode 100644 index 0000000..a64485a --- /dev/null +++ b/plugins/gdbrsp/stream.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * stream.h - prototypes pour la gestion des connexions aux serveurs GDB. + * + * 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 _DEBUG_GDBRSP_STREAM_H +#define _DEBUG_GDBRSP_STREAM_H + + +#include "packet.h" + + + +#define G_TYPE_GDB_STREAM               g_gdb_stream_get_type() +#define G_GDB_STREAM(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_stream_get_type(), GGdbStream)) +#define G_IS_GDB_STREAM(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_stream_get_type())) +#define G_GDB_STREAM_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_STREAM, GGdbStreamClass)) +#define G_IS_GDB_STREAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_STREAM)) +#define G_GDB_STREAM_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_STREAM, GGdbStreamClass)) + + +/* Flux de communication avec un serveur GDB (instance) */ +typedef struct _GGdbStream GGdbStream; + +/* Flux de communication avec un serveur GDB (classe) */ +typedef struct _GGdbStreamClass GGdbStreamClass; + + + +/* Indique le type défini pour un flux de communication avec un serveur GDB. */ +GType g_gdb_stream_get_type(void); + +/* Ne participe plus aux acquitements de paquets. */ +void g_gdb_stream_do_not_ack(GGdbStream *); + +/* Fournit un paquet prêt à emploi. */ +GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *); + +/* Place un paquet en attente d'une future utilisation. */ +void g_gdb_stream_mark_packet_as_free(GGdbStream *, GGdbPacket *); + +/* Envoie un paquet à un serveur GDB. */ +bool g_gdb_stream_send_packet(GGdbStream *, GGdbPacket *); + +/* Fournit un paquet reçu d'un serveur GDB. */ +GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *); + + + +#endif  /* _DEBUG_GDBRSP_STREAM_H */ diff --git a/plugins/gdbrsp/support.c b/plugins/gdbrsp/support.c new file mode 100644 index 0000000..3d27c06 --- /dev/null +++ b/plugins/gdbrsp/support.c @@ -0,0 +1,598 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * support.c - conformité dans l'interfaçage client/serveur + * + * Copyright (C) 2016 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 "support.h" + + +#include <stdlib.h> +#include <string.h> + + + +/* Indications quant à l'interfaçage client/serveur GDB (instance) */ +struct _GGdbSupport +{ +    GObject parent;                         /* A laisser en premier        */ + +    unsigned long packet_size;              /* Taille maximale d'un paquet */ + +    bool os_data; + + +    bool extended_mode;                     /* Mode étendu présent & actif */ + + +    char *id; + +}; + +/* Indications quant à l'interfaçage client/serveur GDB (classe) */ +struct _GGdbSupportClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Initialise la classe des détails d'interfaçage GDB. */ +static void g_gdb_support_class_init(GGdbSupportClass *); + +/* Procède à l'initialisation des détails d'interfaçage GDB. */ +static void g_gdb_support_init(GGdbSupport *); + +/* Supprime toutes les références externes. */ +static void g_gdb_support_dispose(GGdbSupport *); + +/* Procède à la libération totale de la mémoire. */ +static void g_gdb_support_finalize(GGdbSupport *); + +/* Lit une valeur booléenne à partir des détails du serveur. */ +static bool g_gdb_support_read_bool(GGdbSupport *, const char *, const char *, bool *); + +/* Lit une valeur longue à partir des détails du serveur. */ +static bool g_gdb_support_read_ulong(GGdbSupport *, const char *, const char *, unsigned long *); + + + +/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ +G_DEFINE_TYPE(GGdbSupport, g_gdb_support, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe de débogueur à initialiser.                   * +*                                                                             * +*  Description : Initialise la classe des détails d'interfaçage GDB.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_support_class_init(GGdbSupportClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_support_dispose; +    object->finalize = (GObjectFinalizeFunc)g_gdb_support_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : support = instance de débogueur à préparer.                  * +*                                                                             * +*  Description : Procède à l'initialisation des détails d'interfaçage GDB.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_support_init(GGdbSupport *support) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : support = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_support_dispose(GGdbSupport *support) +{ +    G_OBJECT_CLASS(g_gdb_support_parent_class)->dispose(G_OBJECT(support)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : support = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_support_finalize(GGdbSupport *support) +{ +    G_OBJECT_CLASS(g_gdb_support_parent_class)->finalize(G_OBJECT(support)); + +} + + + + + + + + + + + + + + +#include <string.h> + +static char *build_id(GGdbStream *stream) +{ +    char *result;                           /* Identifiant à renvoyer      */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    bool status;                            /* Bilan d'une communication   */ +    const char *data;                       /* Données reçues à analyser   */ +    const char *start;                      /* Début d'identification      */ +    const char *end;                        /* Fin d'identification        */ + +    result = NULL; + +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "?"); + +    status = g_gdb_stream_send_packet(stream, packet); + +    if (!status) +        goto ggdgat_exit; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, NULL, NULL); + +    start = strstr(data, "thread:"); +    if (start == NULL) goto ggdgat_exit; + +    start += sizeof("thread:") - 1 /* '\0' */; + +    end = strstr(start, ";"); +    if (end == NULL) goto ggdgat_exit; + +    result = strndup(start, end - start); + + ggdgat_exit: + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    return result; + +} + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux de communication ouvert avec le débogueur.     * +*                                                                             * +*  Description : Crée une définition des détails d'interfaçage GDB.           * +*                                                                             * +*  Retour      : Instance de détails mise en place ou NULL.                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbSupport *g_gdb_support_new(GGdbStream *stream) +{ +    GGdbSupport *result;                    /* Débogueur à retourner       */ +    GGdbPacket *packet;                     /* Paquet de communication GDB */ + + +    //goto end; + +    //goto skip; + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); +    g_gdb_packet_append(packet, "qSupported"); + +    g_gdb_packet_append(packet, "qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+"); + + +    bool test; + +    const char *data;                       /* Données reçues à analyser   */ +    size_t len; + +    test = g_gdb_stream_send_packet(stream, packet); + + + +    printf(" >> Paquet '%s' bien envoyé ? %s\n", "qSupported", test ? "oui" : "non"); + + + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    printf(" << Réception de '%s'\n", data); + + + + +    result = g_object_new(G_TYPE_GDB_SUPPORT, NULL); + + + +    /* Découpage des éléments de réponse */ + +    char *answer;                           /* Réponse modifiable          */ +    char *save;                             /* Sauvegarde de position      */ +    char *token;                            /* Elément de réponse cerné    */ + +    answer = strdup(data); + +    for (token = strtok_r(answer, ";", &save); +         token != NULL; +         token = strtok_r(NULL, ";", &save)) +    { + + +        printf("TOKEN :: %s\n", token); + +        if (g_gdb_support_read_ulong(result, token, "PacketSize", &result->packet_size)) +            continue; + +        if (g_gdb_support_read_bool(result, token, "qXfer:osdata:read", &result->os_data)) +        { +            printf(" -->> %d\n", result->os_data); +            continue; +        } + + + + +    } + +    free(answer); + + + +    /** +     * Première chose : plus d'acquitement ! +     * +     * Dans les faits, c'est impossible à gérer en asynchrone. Par exemple : +     * +     *  C> vCont;c +     *  C> g           Txx... <S +     * +     * Si le client envoie une commande en même temps que le serveur envoie +     * quelque chose, le serveur attend dans tous les cas un acquitement. +     * Donc il va consommer les données envoyées par le client jusqu'à y +     * trouver ce qu'il cherche. +     */ + +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "QStartNoAckMode"); + +    test = g_gdb_stream_send_packet(stream, packet); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    if (!test) +        goto ggsn_error; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, NULL, NULL); + +    if (strcmp(data, "OK") != 0) +        goto ggsn_error; + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    /* Désactivation des acquitements */ + +    g_gdb_stream_do_not_ack(stream); + +    /** +     * Passage en mode étendu. C'est obligatoire pour pouvoir redémarrer un +     * programme débogué. +     */ + +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "!"); + +    test = g_gdb_stream_send_packet(stream, packet); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    if (!test) +        goto ggsn_error; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, NULL, NULL); + +    result->extended_mode = (strcmp(data, "OK") == 0); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + + + + +    result->id = build_id(stream); + + + +#if 0 +    //end: + +#define CMD "?" + + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); +    g_gdb_packet_append(packet, CMD); + + +    test = g_gdb_stream_send_packet(stream, packet); + + + +    printf(" >> Paquet '%s' bien envoyé ? %s\n", CMD, test ? "oui" : "non"); + + + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    printf(" << [pkt = %p ] Réception de '%s' (len=%d)\n", packet, data, (int)len); + + +#endif + + + +    // qfThreadInfo + + +#undef CMD + +    //#define CMD "qXfer:threads:read::0,1fff" +    //#define CMD "qXfer:btrace:read:all:0,1fff" +    //#define CMD "g" +    //#define CMD "m400000,8" +#define CMD "qsThreadInfo" + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); +    g_gdb_packet_append(packet, CMD); + + +    test = g_gdb_stream_send_packet(stream, packet); + + + +    printf(" >> Paquet '%s' bien envoyé ? %s\n", CMD, test ? "oui" : "non"); + + + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    printf(" << [pkt = %p ] Réception de '%s' (len=%d)\n", packet, data, (int)len); + + + + + + + + + + + +    return result; + + ggsn_error: + + + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : support = ensemble de détails à préciser.                    * +*                raw     = données brutes à parcourir.                        * +*                name    = désignation de la valeur recherchée.               * +*                value   = emplacement de la valeur à inscrire.               * +*                                                                             * +*  Description : Lit une valeur booléenne à partir des détails du serveur.    * +*                                                                             * +*  Retour      : true en cas d'affectation, false dans tous les autres cas.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_support_read_bool(GGdbSupport *support, const char *raw, const char *name, bool *value) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t rlen;                            /* Taille de l'ensemble        */ +    size_t nlen;                            /* Taille du nom               */ + +    rlen = strlen(raw); +    nlen = strlen(name); + +    if ((nlen + 1) != rlen) +        return false; + +    if (strncmp(raw, name, nlen) != 0) +        return false; + +    switch (raw[nlen]) +    { +        case '+': +            *value = true; +            result = true; +            break; + +        case '-': +        case '?': +            *value = false; +            result = true; +            break; + +        default: +            result = false; +            break; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : support = ensemble de détails à préciser.                    * +*                raw     = données brutes à parcourir.                        * +*                name    = désignation de la valeur recherchée.               * +*                value   = emplacement de la valeur à inscrire.               * +*                                                                             * +*  Description : Lit une valeur longue à partir des détails du serveur.       * +*                                                                             * +*  Retour      : true en cas d'affectation, false dans tous les autres cas.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_support_read_ulong(GGdbSupport *support, const char *raw, const char *name, unsigned long *value) +{ +    size_t rlen;                            /* Taille de l'ensemble        */ +    size_t nlen;                            /* Taille du nom               */ +    unsigned long v;                        /* Valeur récupérée à assigner */ + +    rlen = strlen(raw); +    nlen = strlen(name); + +    if (strncmp(raw, name, nlen) != 0) +        return false; + +    if (raw[nlen] != '=') +        return false; + +    v = strtoul(raw + nlen + 1, NULL, 16); + +    if (v == ULONG_MAX/* && errno == ERANGE*/) +        return false; + +    *value = v; + +    return true; + +} + + + + + + +char *g_gdb_support_get_id(const GGdbSupport *support) +{ +    return support->id; + +} + + + + + diff --git a/plugins/gdbrsp/support.h b/plugins/gdbrsp/support.h new file mode 100644 index 0000000..2f6259c --- /dev/null +++ b/plugins/gdbrsp/support.h @@ -0,0 +1,73 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * support.h - prototypes pour la conformité dans l'interfaçage client/serveur + * + * Copyright (C) 2016 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 _DEBUG_GDBRSP_SUPPORT_H +#define _DEBUG_GDBRSP_SUPPORT_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "stream.h" + + + +#define G_TYPE_GDB_SUPPORT            (g_gdb_support_get_type()) +#define G_GDB_SUPPORT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_SUPPORT, GGdbSupport)) +#define G_IS_GDB_SUPPORT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_SUPPORT)) +#define G_GDB_SUPPORT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_SUPPORT, GGdbSupportClass)) +#define G_IS_GDB_SUPPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_SUPPORT)) +#define G_GDB_SUPPORT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_SUPPORT, GGdbSupportClass)) + + +/* Indications quant à l'interfaçage client/serveur GDB (instance) */ +typedef struct _GGdbSupport GGdbSupport; + +/* Indications quant à l'interfaçage client/serveur GDB (classe) */ +typedef struct _GGdbSupportClass GGdbSupportClass; + + +/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ +GType g_gdb_support_get_type(void); + +/* Crée une définition des détails d'interfaçage GDB. */ +GGdbSupport *g_gdb_support_new(GGdbStream *); + + + + + + + +char *g_gdb_support_get_id(const GGdbSupport *support); + + + + + + + + + +#endif  /* _DEBUG_GDBRSP_SUPPORT_H */ diff --git a/plugins/gdbrsp/target.c b/plugins/gdbrsp/target.c new file mode 100644 index 0000000..cf28a49 --- /dev/null +++ b/plugins/gdbrsp/target.c @@ -0,0 +1,950 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.c - gestion des éléments propres à l'architecture reconnue par GDB + * + * Copyright (C) 2016 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 "target.h" + + +#include <assert.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#include "utils.h" +#include "../../common/cpp.h" +#include "../../common/extstr.h" +#include "../../common/xml.h" + + + +/* Définitions de registres */ + +typedef struct _arch_register_t +{ +    char *name;                             /* Nom de registre             */ +    unsigned int size;                      /* Taille en bits              */ + +} arch_register_t; + +typedef struct _target_cpu_t +{ +    char *label;                            /* Désignation de l'ensemble   */ + +    arch_register_t *regs;                  /* Définition des registres    */ +    unsigned int count;                     /* Quantité de ces définitions */ + +} target_cpu_t; + + +/* Indications quant à l'interfaçage client/serveur GDB (instance) */ +struct _GGdbTarget +{ +    GObject parent;                         /* A laisser en premier        */ + +    target_cpu_t **defs;                    /* Liste de définitions        */ +    size_t count;                           /* Taille de cette même liste  */ + +    bool read_single_register;              /* Lecture spécifique permise ?*/ +    bool write_single_register;             /* Ecriture spécifique valide ?*/ + +}; + +/* Indications quant à l'interfaçage client/serveur GDB (classe) */ +struct _GGdbTargetClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Initialise la classe des détails d'interfaçage GDB. */ +static void g_gdb_target_class_init(GGdbTargetClass *); + +/* Procède à l'initialisation des détails d'interfaçage GDB. */ +static void g_gdb_target_init(GGdbTarget *); + +/* Supprime toutes les références externes. */ +static void g_gdb_target_dispose(GGdbTarget *); + +/* Procède à la libération totale de la mémoire. */ +static void g_gdb_target_finalize(GGdbTarget *); + +/* Charge la définition d'un groupe de registres. */ +static bool g_gdb_target_load_register_definition(GGdbTarget *, GGdbStream *, const char *); + +/* Recherche l'indice correspondant à un registre donné. */ +static bool g_gdb_target_find_register_index(const GGdbTarget *, const char *, unsigned int *); + +/* Recherche la position correspondant à un registre donné. */ +static bool g_gdb_target_find_register_offset(const GGdbTarget *, unsigned int, size_t *); + + + +/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ +G_DEFINE_TYPE(GGdbTarget, g_gdb_target, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe de débogueur à initialiser.                   * +*                                                                             * +*  Description : Initialise la classe des détails d'interfaçage GDB.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_target_class_init(GGdbTargetClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_target_dispose; +    object->finalize = (GObjectFinalizeFunc)g_gdb_target_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = instance de débogueur à préparer.                   * +*                                                                             * +*  Description : Procède à l'initialisation des détails d'interfaçage GDB.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_target_init(GGdbTarget *target) +{ +    target->defs = NULL; +    target->count = 0; + +    target->read_single_register = true; +    target->write_single_register = true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_target_dispose(GGdbTarget *target) +{ +    G_OBJECT_CLASS(g_gdb_target_parent_class)->dispose(G_OBJECT(target)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_target_finalize(GGdbTarget *target) +{ +    G_OBJECT_CLASS(g_gdb_target_parent_class)->finalize(G_OBJECT(target)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stream = flux de communication ouvert avec le débogueur.     * +*                                                                             * +*  Description : Crée une définition des détails d'interfaçage GDB.           * +*                                                                             * +*  Retour      : Instance de détails mise en place ou NULL.                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbTarget *g_gdb_target_new(GGdbStream *stream) +{ +    GGdbTarget *result;                     /* Débogueur à retourner       */ +    GGdbPacket *packet;                     /* Paquet de communication GDB */ +    bool status;                            /* Bilan d'une communication   */ + +    const char *data;                       /* Données reçues du serveur   */ +    size_t len;                             /* Quantité de ces données     */ +    char *xmldata;                          /* Données modifiables         */ +    xmlDocPtr xdoc;                         /* Document XML récupéré       */ +    xmlXPathContextPtr context;             /* Contexte d'analyse associé  */ +    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */ +    unsigned int i;                         /* Boucle de parcours          */ +    char *access;                           /* Chemin d'accès à un élément */ +    char *xmlref;                           /* Référence de définitions    */ + + + + +    result = NULL; + + +    //goto end; + +    //goto skip; + + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    //g_gdb_packet_append(packet, "qTargeted:multiprocess+;xmlRegisters"); +    g_gdb_packet_append(packet, "qXfer:features:read:target.xml:0,3fff"); + +    //g_gdb_packet_append(packet, "qTargeted:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContTargeted+;QThreadEvents+;no-resumed+"); + + + +    status = g_gdb_stream_send_packet(stream, packet); +    if (!status) goto ggtn_failed; + + + + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    printf(" << Réception de '%s'\n", data); + +    /* Marqueur de fin placé au début ?! */ +    if (data[0] != 'l') +        goto ggtn_failed; + +    xmldata = strdup(data + 1); + +    /** +     * On cherche à éviter la déconvenue suivante avec la libxml2 : +     * +     *    noname.xml:12: namespace error : Namespace prefix xi on include is not defined +     *      <xi:include href="aarch64-core.xml"/> +     */ + +    xmldata = strrpl(xmldata, "xi:include", "include"); + +    if (!load_xml_from_memory(xmldata, len - 1, &xdoc, &context)) +        goto ggtn_failed; + + +    result = g_object_new(G_TYPE_GDB_TARGET, NULL); + + +    xobject = get_node_xpath_object(context, "/target/include"); + +    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) +    { +        asprintf(&access, "/target/include[position()=%u]", i + 1); + +        xmlref = get_node_prop_value(context, access, "href"); + +        free(access); + +        if (xmlref != NULL) +        { +            printf("REF>> %s\n", xmlref); +            /*static bool */g_gdb_target_load_register_definition(result, stream, xmlref); + +            free(xmlref); + +        } + +    } + +    if(xobject != NULL) +        xmlXPathFreeObject(xobject); + +    close_xml_file(xdoc, context); + +    free(xmldata); + + + + + + + + + + +    //result = g_object_new(G_TYPE_GDB_TARGET, NULL); + + + ggtn_failed: + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                stream = flux de communication ouvert avec le débogueur.     * +*                name   = désignation des définitions de registres à charger. * +*                                                                             * +*  Description : Charge la définition d'un groupe de registres.               * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_target_load_register_definition(GGdbTarget *target, GGdbStream *stream, const char *name) +{ +    bool result;                            /* Bilan à retourner           */ +    GGdbPacket *packet;                     /* Paquet de communication GDB */ +    bool status;                            /* Bilan d'une communication   */ +    const char *data;                       /* Données reçues du serveur   */ +    size_t len;                             /* Quantité de ces données     */ +    xmlDocPtr xdoc;                         /* Document XML récupéré       */ +    xmlXPathContextPtr context;             /* Contexte d'analyse associé  */ +    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */ +    target_cpu_t *def;                      /* Nouvelle définition à lire  */ +    unsigned int i;                         /* Boucle de parcours          */ +    char *access;                           /* Chemin d'accès à un élément */ +    char *type;                             /* Espèce de définition        */ + +    result = false; + +    /* Envoi de la requête */ + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); + +    g_gdb_packet_append(packet, "qXfer:features:read:"); +    g_gdb_packet_append(packet, name); +    g_gdb_packet_append(packet, ":0,3fff"); + +    status = g_gdb_stream_send_packet(stream, packet); +    if (!status) goto ggtlrd_failed; + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    //printf(">>>> '%s'\n", data); + +    /* Marqueur de fin placé au début ?! */ +    if (data[0] != 'l') +        goto ggtlrd_failed; + +    if (!load_xml_from_memory(data + 1, len - 1, &xdoc, &context)) +        goto ggtlrd_failed; + +    /* Chargement des définitions */ + +    xobject = get_node_xpath_object(context, "/feature/*"); + +    def = (target_cpu_t *)calloc(1, sizeof(target_cpu_t)); + +    def->count = XPATH_OBJ_NODES_COUNT(xobject); +    def->regs = (arch_register_t *)calloc(def->count, sizeof(arch_register_t)); + +    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) +    { +        asprintf(&access, "/feature/*[position()=%u]", i + 1); + +        type = get_node_name(context, access); + +        if (strcmp(type, "reg") == 0) +        { +            def->regs[i].name = get_node_prop_value(context, access, "name"); +            def->regs[i].size = atoi(get_node_prop_value(context, access, "bitsize")); + +            //printf("load reg '%s' (%u)\n", def->regs[i].name, def->regs[i].size); + +        } + +        free(type); + +        free(access); + +    } + +    if(xobject != NULL) +        xmlXPathFreeObject(xobject); + +    close_xml_file(xdoc, context); + +    /* Intégration finale */ + +    target->defs = (target_cpu_t **)realloc(target->defs, ++target->count * sizeof(target_cpu_t *)); + +    target->defs[target->count - 1] = def; + + ggtlrd_failed: + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                group  = éventuel groupe de registres ciblé ou NULL.         * +*                count  = nombre d'éléments dans la liste de noms. [OUT]      * +*                                                                             * +*  Description : Liste l'ensemble des registres appartenant à un groupe.      * +*                                                                             * +*  Retour      : Liste de noms à libérer de la mémoire après utilisation.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char **g_gdb_target_get_register_names(const GGdbTarget *target, const char *group, size_t *count) +{ +    char **result;                          /* Désignations à retourner    */ +    unsigned int i;                         /* Boucle de parcours #1       */ +    const target_cpu_t *rgrp;               /* Groupe de registres         */ +    unsigned int j;                         /* Boucle de parcours #2       */ + +    result = NULL; + +    for (i = 0; i < target->count && result == NULL; i++) +    { +        rgrp = target->defs[i]; + +        if (group != NULL) +        { +            if (strcmp(rgrp->label, group) != 0) +                continue; +        } + +        *count = rgrp->count; + +        result = (char **)calloc(*count, sizeof(char *)); + +        for (j = 0; j < *count; j++) +            result[j] = strdup(rgrp->regs[j].name); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                name   = désignation du registre visé.                       * +*                                                                             * +*  Description : Indique la taille associée à un registre donné.              * +*                                                                             * +*  Retour      : Taille en bits, ou 0 si le registre n'a pas été trouvé.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +unsigned int g_gdb_target_get_register_size(const GGdbTarget *target, const char *name) +{ +    unsigned int result;                    /* Taille en bits  à retourner */ +    unsigned int i;                         /* Boucle de parcours #1       */ +    const target_cpu_t *rgrp;               /* Groupe de registres         */ +    unsigned int j;                         /* Boucle de parcours #2       */ + +    result = 0; + +    for (i = 0; i < target->count && result == 0; i++) +    { +        rgrp = target->defs[i]; + +        for (j = 0; j < rgrp->count; j++) +            if (strcmp(rgrp->regs[j].name, name) == 0) +                result = rgrp->regs[j].size; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                reg    = désignation humaine du register à consulter.        * +*                index  = indice correspondant au registre pour GDB. [OUT]    * +*                                                                             * +*  Description : Recherche l'indice correspondant à un registre donné.        * +*                                                                             * +*  Retour      : Bilan de l'opération : trouvaille ou échec ?                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_target_find_register_index(const GGdbTarget *target, const char *reg, unsigned int *index) +{ +    bool result;                            /* Bilan à retourner           */ +    unsigned int i;                         /* Boucle de parcours #1       */ +    unsigned int j;                         /* Boucle de parcours #2       */ + +    result = false; + +    *index = 0; + +    for (i = 0; i < target->count && !result; i++) +        for (j = 0; j < target->defs[i]->count && !result; j++) +        { +            if (strcmp(target->defs[i]->regs[j].name, reg) == 0) +                result = true; +            else +                (*index)++; +        } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                index  = indice correspondant au registre pour GDB.          * +*                offset = position de valeur du registre dans du texte. [OUT] * +*                                                                             * +*  Description : Recherche la position correspondant à un registre donné.     * +*                                                                             * +*  Retour      : Bilan de l'opération : trouvaille ou échec ?                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_target_find_register_offset(const GGdbTarget *target, unsigned int index, size_t *offset) +{ +    unsigned int i;                         /* Boucle de parcours #1       */ +    unsigned int j;                         /* Boucle de parcours #2       */ + +    *offset = 0; + +    for (i = 0; i < target->count && index > 0; i++) +        for (j = 0; j < target->defs[i]->count && index > 0; j++) +        { +            assert(target->defs[i]->regs[j].size % 4 == 0); + +            *offset += target->defs[i]->regs[j].size / 4; + +            index--; + +        } + +    return (index == 0); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                stream = flux de communication ouvert avec le débogueur.     * +*                endian = boutisme de la cible.                               * +*                reg    = désignation humaine du register à consulter.        * +*                size   = taille des données mises en jeu.                    * +*                ...    = emplacement de la valeur lue à conserver. [OUT]     * +*                                                                             * +*  Description : Effectue la lecture d'un registre donné.                     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_gdb_target_read_register(GGdbTarget *target, GGdbStream *stream, SourceEndian endian, const char *reg, size_t size, ...) +{ +    bool result;                            /* Bilan à retourner           */ +    unsigned int index;                     /* Indice du registre ciblé    */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    char cmd[sizeof(XSTR(UINT_MAX)) + 1];   /* Elément de requête          */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de ces données     */ +    const char *raw;                        /* Début de zone à relire      */ +    size_t offset;                          /* Position dans la masse      */ +    va_list ap;                             /* Liste variable d'arguments  */ +    uint8_t *val8;                          /* Valeur sur 8 bits           */ +    uint16_t *val16;                        /* Valeur sur 16 bits          */ +    uint16_t conv16;                        /* Valeur adaptée sur 16 bits  */ +    uint32_t *val32;                        /* Valeur sur 32 bits          */ +    uint32_t conv32;                        /* Valeur adaptée sur 32 bits  */ +    uint64_t *val64;                        /* Valeur sur 64 bits          */ +    uint64_t conv64;                        /* Valeur adaptée sur 64 bits  */ + +    result = g_gdb_target_find_register_index(target, reg, &index); +    if (!result) goto ggtrr_error; + +    /** +     * Essai avec la méthode précise. +     */ + +    if (!target->read_single_register) +        goto read_all_register_fallback; + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "p"); + +    snprintf(cmd, sizeof(cmd), "%x", index); +    g_gdb_packet_append(packet, cmd); + +    result = g_gdb_stream_send_packet(stream, packet); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    if (!result) +        goto ggtrr_error; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    if (len != 0 && !is_error_code(data, len)) +        raw = data; + +    else +    { +        target->read_single_register = false; + +        g_gdb_stream_mark_packet_as_free(stream, packet); + + read_all_register_fallback: + +        /** +         * Utilisation de la méthode de masse au besoin... +         */ + +        packet = g_gdb_stream_get_free_packet(stream); + +        g_gdb_packet_start_new_command(packet); +        g_gdb_packet_append(packet, "g"); + +        result = g_gdb_stream_send_packet(stream, packet); + +        g_gdb_stream_mark_packet_as_free(stream, packet); + +        if (!result) +            goto ggtrr_error; + +        /* Réception de la réponse */ + +        packet = g_gdb_stream_recv_packet(stream); + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        result = g_gdb_target_find_register_offset(target, index, &offset); + +        if (!result || offset > len) +            goto ggtrr_exit; + +        raw = data + offset; +        len -= offset; + +    } + +    /* Lecture finale de la valeur recherchée */ + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, uint8_t *); +            result = hex_to_u8(raw, val8); +            break; + +        case 16: +            val16 = va_arg(ap, uint16_t *); +            result = hex_to_u16(raw, &conv16); +            *val16 = from_u16(&conv16, endian); +            break; + +        case 32: +            val32 = va_arg(ap, uint32_t *); +            result = hex_to_u32(raw, &conv32); +            *val32 = from_u32(&conv32, endian); +            break; + +        case 64: +            val64 = va_arg(ap, uint64_t *); +            result = hex_to_u64(raw, &conv64); +            *val64 = from_u64(&conv64, endian); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    va_end(ap); + + ggtrr_exit: + +    g_gdb_stream_mark_packet_as_free(stream, packet); + + ggtrr_error: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : target = ensemble d'informations liées à l'architecture.     * +*                stream = flux de communication ouvert avec le débogueur.     * +*                endian = boutisme de la cible.                               * +*                reg    = désignation humaine du register à consulter.        * +*                size   = taille des données mises en jeu.                    * +*                ...    = emplacement de la valeur à écrire.                  * +*                                                                             * +*  Description : Effectue l'écriture d'un registre donné.                     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_gdb_target_write_register(GGdbTarget *target, GGdbStream *stream, SourceEndian endian, const char *reg, size_t size, ...) +{ +    bool result;                            /* Bilan d'opération à renvoyer*/ +    va_list ap;                             /* Liste variable d'arguments  */ +    const uint8_t *val8;                    /* Valeur sur 8 bits           */ +    const uint16_t *val16;                  /* Valeur sur 16 bits          */ +    uint16_t conv16;                        /* Valeur adaptée sur 16 bits  */ +    const uint32_t *val32;                  /* Valeur sur 32 bits          */ +    uint32_t conv32;                        /* Valeur adaptée sur 32 bits  */ +    const uint64_t *val64;                  /* Valeur sur 64 bits          */ +    uint64_t conv64;                        /* Valeur adaptée sur 64 bits  */ +    char hexval[17];                        /* Valeur sous forme hexa      */ +    unsigned int index;                     /* Indice du registre ciblé    */ +    GGdbPacket *packet;                     /* Paquet de communication     */ +    char cmd[sizeof(XSTR(UINT_MAX)) + 1];   /* Elément de requête          */ +    const char *data;                       /* Données reçues à analyser   */ +    size_t len;                             /* Quantité de ces données     */ +    char *new;                              /* Nouvelles valeurs générales */ +    size_t offset;                          /* Position dans la masse      */ + +    /* Tronc commun : récupération de la valeur */ + +    va_start(ap, size); + +    switch (size) +    { +        case 8: +            val8 = va_arg(ap, uint8_t *); +            result = u8_to_hex(val8, hexval); +            break; + +        case 16: +            val16 = va_arg(ap, uint16_t *); +            conv16 = to_u16(val16, endian); +            result = u16_to_hex(&conv16, hexval); +            break; + +        case 32: +            val32 = va_arg(ap, uint32_t *); +            conv32 = to_u32(val32, endian); +            result = u32_to_hex(&conv32, hexval); +            break; + +        case 64: +            val64 = va_arg(ap, uint64_t *); +            conv64 = to_u64(val64, endian); +            result = u16_to_hex(&conv64, hexval); +            break; + +        default: +            assert(false); +            result = false; +            break; + +    } + +    va_end(ap); + +    if (!result) +        goto ggtwr_error; + +    /* Préparation de la suite */ + +    result = g_gdb_target_find_register_index(target, reg, &index); +    if (!result) goto ggtwr_error; + +    /** +     * Essai avec la méthode précise. +     */ + +    if (!target->write_single_register) +        goto write_all_register_fallback; + +    packet = g_gdb_stream_get_free_packet(stream); + +    g_gdb_packet_start_new_command(packet); +    g_gdb_packet_append(packet, "P"); + +    snprintf(cmd, sizeof(cmd), "%x", index); +    g_gdb_packet_append(packet, cmd); + +    g_gdb_packet_append(packet, "="); + +    g_gdb_packet_append(packet, hexval); + +    result = g_gdb_stream_send_packet(stream, packet); + +    g_gdb_stream_mark_packet_as_free(stream, packet); + +    if (!result) +        goto ggtwr_error; + +    /* Réception de la réponse */ + +    packet = g_gdb_stream_recv_packet(stream); + +    g_gdb_packet_get_data(packet, &data, &len, NULL); + +    if (is_error_code(data, len) || strcmp(data, "OK") != 0) +    { +        target->write_single_register = false; + +        g_gdb_stream_mark_packet_as_free(stream, packet); + + write_all_register_fallback: + +        /** +         * Utilisation de la méthode de masse au besoin... +         */ + +        /* Lecture de l'ensemble des registres */ + +        packet = g_gdb_stream_get_free_packet(stream); + +        g_gdb_packet_start_new_command(packet); +        g_gdb_packet_append(packet, "g"); + +        result = g_gdb_stream_send_packet(stream, packet); + +        g_gdb_stream_mark_packet_as_free(stream, packet); + +        if (!result) +            goto ggtwr_error; + +        /* Réception de la réponse et mise à jour */ + +        packet = g_gdb_stream_recv_packet(stream); + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        result = g_gdb_target_find_register_offset(target, index, &offset); + +        if (!result || offset > len) +            goto ggtwr_exit; + +        new = (char *)malloc(len); + +        memcpy(new, data, len); +        memcpy(new + offset, hexval, strlen(hexval)); + +        g_gdb_stream_mark_packet_as_free(stream, packet); + +        /* Ecrasement de tous les registres */ + +        packet = g_gdb_stream_get_free_packet(stream); + +        g_gdb_packet_start_new_command(packet); +        g_gdb_packet_append(packet, "G"); + +        g_gdb_packet_append(packet, new); +        free(new); + +        result = g_gdb_stream_send_packet(stream, packet); + +        g_gdb_stream_mark_packet_as_free(stream, packet); + +        if (!result) +            goto ggtwr_error; + +        /* Réception de la réponse */ + +        packet = g_gdb_stream_recv_packet(stream); + +        g_gdb_packet_get_data(packet, &data, &len, NULL); + +        result = (!is_error_code(data, len) && strcmp(data, "OK") == 0); + +    } + + ggtwr_exit: + +    g_gdb_stream_mark_packet_as_free(stream, packet); + + ggtwr_error: + +    return result; + +} diff --git a/plugins/gdbrsp/target.h b/plugins/gdbrsp/target.h new file mode 100644 index 0000000..bbdbec1 --- /dev/null +++ b/plugins/gdbrsp/target.h @@ -0,0 +1,72 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.h - prototypes pour la gestion des éléments propres à l'architecture reconnue par GDB + * + * Copyright (C) 2016 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 _DEBUG_GDBRSP_TARGET_H +#define _DEBUG_GDBRSP_TARGET_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "stream.h" +#include "../../common/endianness.h" + + + +#define G_TYPE_GDB_TARGET            (g_gdb_target_get_type()) +#define G_GDB_TARGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_TARGET, GGdbTarget)) +#define G_IS_GDB_TARGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_TARGET)) +#define G_GDB_TARGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_TARGET, GGdbTargetClass)) +#define G_IS_GDB_TARGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_TARGET)) +#define G_GDB_TARGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_TARGET, GGdbTargetClass)) + + +/* Indications quant à l'interfaçage client/serveur GDB (instance) */ +typedef struct _GGdbTarget GGdbTarget; + +/* Indications quant à l'interfaçage client/serveur GDB (classe) */ +typedef struct _GGdbTargetClass GGdbTargetClass; + + +/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ +GType g_gdb_target_get_type(void); + +/* Crée une définition des détails d'interfaçage GDB. */ +GGdbTarget *g_gdb_target_new(GGdbStream *); + +/* Liste l'ensemble des registres appartenant à un groupe. */ +char **g_gdb_target_get_register_names(const GGdbTarget *, const char *, size_t *); + +/* Indique la taille associée à un registre donné. */ +unsigned int g_gdb_target_get_register_size(const GGdbTarget *, const char *); + +/* Effectue la lecture d'un registre donné. */ +bool g_gdb_target_read_register(GGdbTarget *, GGdbStream *, SourceEndian, const char *, size_t, ...); + +/* Effectue l'écriture d'un registre donné. */ +bool g_gdb_target_write_register(GGdbTarget *, GGdbStream *, SourceEndian, const char *, size_t, ...); + + + +#endif  /* _DEBUG_GDBRSP_TARGET_H */ diff --git a/plugins/gdbrsp/tcp.c b/plugins/gdbrsp/tcp.c new file mode 100644 index 0000000..8458dc6 --- /dev/null +++ b/plugins/gdbrsp/tcp.c @@ -0,0 +1,280 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tcp.c - gestion des connexions TCP aux serveurs GDB. + * + * 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 "tcp.h" + + +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/types.h> + + +#include "stream-int.h" + + +#include "../../common/net.h" + + +/* Flux de communication TCP avec un serveur GDB (instance) */ +struct _GGdbTcpClient +{ +    GGdbStream parent;                      /* A laisser en premier        */ + +}; + + +/* Flux de communication TCP avec un serveur GDB (classe) */ +struct _GGdbTcpClientClass +{ +    GGdbStreamClass parent;                 /* A laisser en premier        */ + +}; + + +/* Initialise la classe des flux de communication TCP avec GDB. */ +static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *); + +/* Initialise une instance de flux de communication avec GDB. */ +static void g_gdb_tcp_client_init(GGdbTcpClient *); + +/* Ouvre une connexion TCP à un serveur GDB. */ +//static int connect_via_tcp(const char *, const char *); + +/* Envoie des données à un serveur GDB. */ +static bool g_gdb_tcp_client_send_data(GGdbTcpClient *, const char *, size_t); + +/* Réceptionne un octet de donnée d'un serveur GDB. */ +static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *, char *); + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ +G_DEFINE_TYPE(GGdbTcpClient, g_gdb_tcp_client, G_TYPE_GDB_STREAM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des flux de communication TCP avec GDB. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : client = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une instance de flux de communication avec GDB.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_gdb_tcp_client_init(GGdbTcpClient *client) +{ +    GGdbStream *stream;                     /* Version parente             */ + +    stream = G_GDB_STREAM(client); + +    stream->send_data = (send_gdb_data_fc)g_gdb_tcp_client_send_data; +    stream->recv_byte = (recv_gdb_byte_fc)g_gdb_tcp_client_recv_byte; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : server = nom ou adresse du serveur à contacter.              * +*                port   = port de connexion.                                  * +*                                                                             * +*  Description : Ouvre une connexion TCP à un serveur GDB.                    * +*                                                                             * +*  Retour      : Flux ouvert en lecture/écriture ou -1 en cas d'échec.        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +#if 0 +static int connect_via_tcp(const char *server, const char *port) +{ +    int result;                             /* Bilan à retourner           */ +    struct addrinfo hints;                  /* Type de connexion souhaitée */ +    struct addrinfo *infos;                 /* Informations disponibles    */ +    int ret;                                /* Bilan d'un appel            */ +    struct addrinfo *iter;                  /* Boucle de parcours          */ +    struct sockaddr_in addr;                /* Infos de connexion distante */ + +    memset(&hints, 0, sizeof(struct addrinfo)); + +    hints.ai_family = AF_UNSPEC;        /* IPv4 ou IPv6 */ +    hints.ai_socktype = SOCK_STREAM; +    hints.ai_flags = 0; +    hints.ai_protocol = 0;              /* N'importe quel protocole */ + +    ret = getaddrinfo(server, port, &hints, &infos); +    if (ret != 0) +    { +        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); +        return -1; +    } + +    for (iter = infos; iter != NULL; iter = iter->ai_next) +    { +        result = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol); +        if (result == -1) continue; + +        ret = connect(result, iter->ai_addr, iter->ai_addrlen); +        if (ret == 0) break; + +        perror("connect"); +        close(result); + +    } + +    freeaddrinfo(infos); + +    if (iter == NULL) return -1; + +    ret = getpeername(result, (struct sockaddr *)&addr, (socklen_t []){ sizeof(struct sockaddr_in) }); +    if (ret == -1) +    { +        perror("getpeername"); +        close(result); +        return -1; +    } + +    printf("Connecté à %s:%hd\n", server, ntohs(addr.sin_port)); + +    return result; + +} +#endif + +/****************************************************************************** +*                                                                             * +*  Paramètres  : server = nom ou adresse du serveur à contacter.              * +*                port   = port de connexion.                                  * +*                owner  = débogueur tributaire du canal de communication.     * +*                                                                             * +*  Description : Crée une nouvelle connexion TCP à un serveur GDB.            * +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGdbStream *g_gdb_tcp_client_new(const char *server, const char *port, GGdbDebugger *owner) +{ +    GGdbTcpClient *result;                  /* Structure à retourner       */ +    int sock;                               /* Flux ouvert à construire    */ + +    sock = connect_via_tcp(server, port, NULL); +    if (sock == -1) return NULL; + +    result = g_object_new(G_TYPE_GDB_TCP_CLIENT, NULL); + +    G_GDB_STREAM(result)->fd = sock; + +    G_GDB_STREAM(result)->owner = owner; +    g_object_ref(G_OBJECT(owner)); + +    if (!g_gdb_stream_listen(G_GDB_STREAM(result))) +        goto ggtcn_error; + +    return G_GDB_STREAM(result); + + ggtcn_error: + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : client = flux ouvert en écriture à utiliser.                 * +*                data   = données à envoyer.                                  * +*                len    = quantité de ces données.                            * +*                                                                             * +*  Description : Envoie des données à un serveur GDB.                         * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_tcp_client_send_data(GGdbTcpClient *client, const char *data, size_t len) +{ +    ssize_t sent;                           /* Quantité de données envoyée */ + +    sent = send(G_GDB_STREAM(client)->fd, data, len, 0); + +    //printf("  sent '%s'\n", data); +    //printf("  sent ? %d vs %d\n", (int)sent, (int)len); + +    return (sent == len); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : client = flux ouvert en lecture à utiliser.                  * +*                data   = donnée à recevoir.                                  * +*                                                                             * +*  Description : Réceptionne un octet de donnée d'un serveur GDB.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *client, char *data) +{ +    ssize_t got;                            /* Quantité de données reçue   */ + +    got = recv(G_GDB_STREAM(client)->fd, data, 1, 0); + +    //printf("  got ? %d vs %d -> %c (0x%02hhx\n", (int)got, (int)1, *data, *data); + +    return (got == 1); + +} diff --git a/plugins/gdbrsp/tcp.h b/plugins/gdbrsp/tcp.h new file mode 100644 index 0000000..3472fd2 --- /dev/null +++ b/plugins/gdbrsp/tcp.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tcp.h - prototypes pour la gestion des connexions TCP aux serveurs GDB. + * + * 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 _DEBUG_GDBRSP_TCP_H +#define _DEBUG_GDBRSP_TCP_H + + +#include "gdb.h" +#include "stream.h" + + + +#define G_TYPE_GDB_TCP_CLIENT               g_gdb_tcp_client_get_type() +#define G_GDB_TCP_CLIENT(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_tcp_client_get_type(), GGdbTcpClient)) +#define G_IS_GDB_TCP_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_tcp_client_get_type())) +#define G_GDB_TCP_CLIENT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) +#define G_IS_GDB_TCP_CLIENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_TCP_CLIENT)) +#define G_GDB_TCP_CLIENT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) + + +/* Flux de communication TCP avec un serveur GDB (instance) */ +typedef struct _GGdbTcpClient GGdbTcpClient; + +/* Flux de communication TCP avec un serveur GDB (classe) */ +typedef struct _GGdbTcpClientClass GGdbTcpClientClass; + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ +GType g_gdb_tcp_client_get_type(void); + +/* Crée une nouvelle connexion TCP à un serveur GDB. */ +GGdbStream *g_gdb_tcp_client_new(const char *, const char *, GGdbDebugger *); + + + +#endif  /* _DEBUG_GDBRSP_TCP_H */ diff --git a/plugins/gdbrsp/utils.c b/plugins/gdbrsp/utils.c new file mode 100644 index 0000000..1088e51 --- /dev/null +++ b/plugins/gdbrsp/utils.c @@ -0,0 +1,354 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * utils.h - fonctions qui simplifient la vie dans les interactions avec un serveur GDB + * + * Copyright (C) 2016 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 "utils.h" + + +#include <assert.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> +#include <sys/param.h> +#include <sys/types.h> + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = données à inspecter.                                  * +*                len  = quantité de ces données.                              * +*                                                                             * +*  Description : Indique si les données correspondent à un code d'erreur.     * +*                                                                             * +*  Retour      : Bilan de l'analyse.                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool is_error_code(const char *data, size_t len) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = (len == 3); + +    if (result) +        result = (data[0] == 'E' && isdigit(data[1]) && isdigit(data[2])); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = données à analyser.                                   * +*                size = taille de ces données.                                * +*                byte = statut de sortie d'un programme. [OUT]                * +*                                                                             * +*  Description : Relit une valeur sur 8 bits et deux lettres.                 * +*                                                                             * +*  Retour      : Bilan de la lecture.                                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool read_fixed_byte(const char *data, size_t len, uint8_t *byte) +{ +    bool result;                            /* Bilan à retourner           */ +    const char *iter;                       /* Boucle de parcours #1       */ +    size_t i;                               /* Boucle de parcours #2       */ +    uint8_t nibble;                         /* Valeur affichée             */ + +    result = true; + +    len = MIN(2, len); + +    for (i = 0, iter = data; i < len; i++, iter++) +    { +        switch (*iter) +        { +            case '0' ... '9': +                nibble = *iter - '0'; +                break; + +            case 'a' ... 'f': +                nibble = *iter - 'a' + 10; +                break; + +            case 'A' ... 'F': +                nibble = *iter - 'A' + 10; +                break; + +            default: +                result = false; +                break; + +        } + +        if (!result) +            break; + +        if (i == 0) +            *byte = (nibble << 4); +        else +            *byte |= nibble; + +    } + +    if (result) +        result = (i == 2); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : hex   = tampon d'origine assez grand.                        * +*                size  = taille de la valeur à considérer pour les travaux.   * +*                value = valeur sur XX bits à transcrire. [OUT]               * +*                                                                             * +*  Description : Traduit en valeur sur XX bits une forme textuelle.           * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool hex_to_any_u(const char *hex, size_t size, ...) +{ +    bool result;                            /* Bilan à retourner           */ +    va_list ap;                             /* Gestion de l'inconnue       */ +    uint8_t *value8;                        /* Valeur sur 8 bits           */ +    uint16_t *value16;                      /* Valeur sur 16 bits          */ +    uint32_t *value32;                      /* Valeur sur 32 bits          */ +    uint64_t *value64;                      /* Valeur sur 64 bits          */ +    uint8_t *iter;                          /* Boucle de parcours #1       */ +    size_t i;                               /* Boucle de parcours #2       */ +    char nibble;                            /* Valeur à afficher           */ + +    result = false; + +    /* Récupération de la destination */ + +    va_start(ap, size); + +    switch (size) +    { +        case 1: +            value8 = va_arg(ap, uint8_t *); +            iter = value8; +            break; + +        case 2: +            value16 = va_arg(ap, uint16_t *); +            iter = (uint8_t *)value16; +            break; + +        case 4: +            value32 = va_arg(ap, uint32_t *); +            iter = (uint8_t *)value32; +            break; + +        case 8: +            value64 = va_arg(ap, uint64_t *); +            iter = (uint8_t *)value64; +            break; + +        default: +            goto done; +            break; + +    } + +    /* Lecture de la valeur */ + +    for (i = 0; i < size; i++, iter++) +    { +        *iter = 0; + +        nibble = hex[i * 2]; + +        switch (nibble) +        { +            case '0' ... '9': +                *iter = (nibble - '0') << 4; +                break; + +            case 'a' ... 'f': +                *iter = (nibble - 'a' + 0xa) << 4; +                break; + +            case 'A' ... 'F': +                *iter = (nibble - 'A' + 0xa) << 4; +                break; + +            default: +                goto done; +                break; + +        } + +        nibble = hex[i * 2 + 1]; + +        switch (nibble) +        { +            case '0' ... '9': +                *iter |= (nibble - '0'); +                break; + +            case 'a' ... 'f': +                *iter |= (nibble - 'a' + 0xa); +                break; + +            case 'A' ... 'F': +                *iter |= (nibble - 'A' + 0xa); +                break; + +            default: +                goto done; +                break; + +        } + +    } + +    result = (i == size); + + done: + +    va_end(ap); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : size  = taille de la valeur à considérer pour les travaux.   * +*                hex   = tampon de destination assez grand.                   * +*                value = valeur sur XX bits à transcrire. [OUT]               * +*                                                                             * +*  Description : Traduit une valeur sur XX bits en forme textuelle.           * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool any_u_to_hex(size_t size, char hex[17], ...) +{ +    bool result;                            /* Bilan à retourner           */ +    va_list ap;                             /* Gestion de l'inconnue       */ +    uint8_t *value8;                        /* Valeur sur 8 bits           */ +    uint16_t *value16;                      /* Valeur sur 16 bits          */ +    uint32_t *value32;                      /* Valeur sur 32 bits          */ +    uint64_t *value64;                      /* Valeur sur 64 bits          */ +    size_t i;                               /* Boucle de parcours #1       */ +    const uint8_t *iter;                    /* Boucle de parcours #2       */ +    uint8_t nibble;                         /* Valeur à retenir            */ + +    result = true; + +    /* Récupération de la destination */ + +    va_start(ap, hex); + +    switch (size) +    { +        case 1: +            value8 = va_arg(ap, uint8_t *); +            iter = (const uint8_t *)value8; +            break; + +        case 2: +            value16 = va_arg(ap, uint16_t *); +            iter = (const uint8_t *)value16; +            break; + +        case 4: +            value32 = va_arg(ap, uint32_t *); +            iter = (const uint8_t *)value32; +            break; + +        case 8: +            value64 = va_arg(ap, uint64_t *); +            iter = (const uint8_t *)value64; +            break; + +        default: +            result = false; +            goto done; +            break; + +    } + +    /* Lecture de la valeur */ + +    for (i = 0; i < size; i++, iter++) +    { +        nibble = (*iter & 0xf0) >> 4; + +        switch (nibble) +        { +            case 0x0 ... 0x9: +                hex[i * 2] = '0' + nibble; +                break; + +            case 0xa ... 0xf: +                hex[i * 2] = 'A' + nibble - 0xa; +                break; + +        } + +        nibble = (*iter & 0x0f); + +        switch (nibble) +        { +            case 0x0 ... 0x9: +                hex[i * 2 + 1] = '0' + nibble; +                break; + +            case 0xa ... 0xf: +                hex[i * 2 + 1] = 'A' + nibble - 0xa; +                break; + +        } + +    } + +    hex[size * 2] = '\0'; + + done: + +    va_end(ap); + +    return result; + +} diff --git a/plugins/gdbrsp/utils.h b/plugins/gdbrsp/utils.h new file mode 100644 index 0000000..833fe69 --- /dev/null +++ b/plugins/gdbrsp/utils.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * utils.h - prototypes pour les fonctions qui simplifient la vie dans les interactions avec un serveur GDB + * + * Copyright (C) 2016 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 _DEBUG_GDBRSP_UTILS_H +#define _DEBUG_GDBRSP_UTILS_H + + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + + + +/* Indique si les données correspondent à un code d'erreur. */ +bool is_error_code(const char *, size_t); + +/* Relit une valeur sur 8 bits et deux lettres. */ +bool read_fixed_byte(const char *, size_t, uint8_t *); + +/* Traduit en valeur sur XX bits une forme textuelle. */ +bool hex_to_any_u(const char *, size_t, ...); + +#define hex_to_u8(h, v)  hex_to_any_u(h, 1, v) +#define hex_to_u16(h, v) hex_to_any_u(h, 2, v) +#define hex_to_u32(h, v) hex_to_any_u(h, 4, v) +#define hex_to_u64(h, v) hex_to_any_u(h, 8, v) + +/* Traduit une valeur sur XX bits en forme textuelle. */ +bool any_u_to_hex(size_t, char [17], ...); + +#define u8_to_hex(v, h)  any_u_to_hex(1, h, v) +#define u16_to_hex(v, h) any_u_to_hex(2, h, v) +#define u32_to_hex(v, h) any_u_to_hex(4, h, v) +#define u64_to_hex(v, h) any_u_to_hex(8, h, v) + + + +#endif  /* _DEBUG_GDBRSP_UTILS_H */ 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 */ diff --git a/plugins/jvm/Makefile.am b/plugins/jvm/Makefile.am new file mode 100644 index 0000000..fc4ee0b --- /dev/null +++ b/plugins/jvm/Makefile.am @@ -0,0 +1,35 @@ + +noinst_LTLIBRARIES = libarchjvm.la + +libarchjvm_la_SOURCES =					\ +	instruction.h instruction.c			\ +	op_add.c							\ +	op_const.c							\ +	op_convert.c						\ +	op_dup.c							\ +	op_getput.c							\ +	op_invoke.c							\ +	op_load.c							\ +	op_monitor.c						\ +	op_nop.c							\ +	op_pop.c							\ +	op_store.c							\ +	op_ret.c							\ +	opcodes.h							\ +	operand.h operand.c					\ +	processor.h processor.c + +libarchjvm_la_CFLAGS = $(AM_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=%) + +dev_HEADERS = $(libarchjvm_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS =  diff --git a/plugins/jvm/instruction.c b/plugins/jvm/instruction.c new file mode 100644 index 0000000..c7a9bfb --- /dev/null +++ b/plugins/jvm/instruction.c @@ -0,0 +1,299 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions JVM + * + * 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 "instruction.h" + + +#include "../instruction-int.h"  + + + +/* Définition générique d'une instruction d'architecture JVM (instance) */ +struct _GJvmInstruction +{ +    GArchInstruction parent;                /* A laisser en premier        */ + +    JvmOpcodes type;                        /* Position dans la liste      */ + +}; + +/* Définition générique d'une instruction d'architecture JVM (classe) */ +struct _GJvmInstructionClass +{ +    GArchInstructionClass parent;           /* A laisser en premier        */ + +}; + + +/* Initialise la classe des instructions pour JVM. */ +static void g_jvm_instruction_class_init(GJvmInstructionClass *); + +/* Initialise une instance d'opérande d'architecture JVM. */ +static void g_jvm_instruction_init(GJvmInstruction *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions JVM */ +typedef struct _jvm_instruction +{ +    bool care_of_data;                      /* Devinette = repas ?         */ +    bool can_wide;                          /* Instruction étendue ?       */ +    bin_t opcode;                           /* Opcode de l'instruction     */ + +    const char *keyword;                    /* Mot clef de la commande     */ + +} jvm_instruction; + + +static jvm_instruction _instructions[JOP_COUNT] = { + +    [JOP_NOP] =             { false, false, 0x00, "nop" }, +    [JOP_ACONST_NULL] =     { false, false, 0x01, "aconst_null" }, +    [JOP_ICONST_M1] =       { true, false, 0x02, "iconst_m1" }, +    [JOP_ICONST_0] =        { true, false, 0x03, "iconst_0" }, +    [JOP_ICONST_1] =        { true, false, 0x04, "iconst_1" }, +    [JOP_ICONST_2] =        { true, false, 0x05, "iconst_2" }, +    [JOP_ICONST_3] =        { true, false, 0x06, "iconst_3" }, +    [JOP_ICONST_4] =        { true, false, 0x07, "iconst_4" }, +    [JOP_ICONST_5] =        { true, false, 0x08, "iconst_5" }, + + + +    [JOP_POP] =             { false, false, 0x57, "pop" }, +    [JOP_POP2] =            { false, false, 0x58, "pop2" }, +    [JOP_DUP] =             { false, false, 0x59, "dup" }, +    [JOP_DUP_X1] =          { false, false, 0x5a, "dup_x1" }, +    [JOP_DUP_X2] =          { false, false, 0x5b, "dup_x2" }, +    [JOP_DUP2] =            { false, false, 0x5c, "dup2" }, +    [JOP_DUP2_X1] =         { false, false, 0x5d, "dup2_x1" }, +    [JOP_DUP2_X2] =         { false, false, 0x5e, "dup2_x2" }, + + +    [JOP_IADD] =            { false, false, 0x60, "iadd" }, + + +    [JOP_I2L] =             { false, false, 0x85, "i2l" }, +    [JOP_I2F] =             { false, false, 0x86, "i2f" }, +    [JOP_I2D] =             { false, false, 0x87, "i2d" }, +    [JOP_L2I] =             { false, false, 0x88, "l2i" }, +    [JOP_L2F] =             { false, false, 0x89, "l2f" }, +    [JOP_L2D] =             { false, false, 0x8a, "l2d" }, +    [JOP_F2I] =             { false, false, 0x8b, "f2i" }, +    [JOP_F2L] =             { false, false, 0x8c, "f2l" }, +    [JOP_F2D] =             { false, false, 0x8d, "f2d" }, +    [JOP_D2I] =             { false, false, 0x8e, "d2i" }, +    [JOP_D2L] =             { false, false, 0x8f, "d2l" }, +    [JOP_D2F] =             { false, false, 0x90, "d2f" }, +    [JOP_I2B] =             { false, false, 0x91, "i2b" }, +    [JOP_I2C] =             { false, false, 0x92, "i2c" }, +    [JOP_I2S] =             { false, false, 0x93, "i2s" }, + + +    [JOP_ILOAD_0] =         { true, false, 0x1a, "iload_0" }, +    [JOP_ILOAD_1] =         { true, false, 0x1b, "iload_1" }, +    [JOP_ILOAD_2] =         { true, false, 0x1c, "iload_2" }, +    [JOP_ILOAD_3] =         { true, false, 0x1d, "iload_3" }, + + + +    [JOP_ALOAD_0] =         { true, false, 0x2a, "aload_0" }, +    [JOP_ALOAD_1] =         { true, false, 0x2b, "aload_1" }, +    [JOP_ALOAD_2] =         { true, false, 0x2c, "aload_2" }, +    [JOP_ALOAD_3] =         { true, false, 0x2d, "aload_3" }, + +    [JOP_ISTORE_0] =        { true, false, 0x3b, "istore_0" }, +    [JOP_ISTORE_1] =        { true, false, 0x3c, "istore_1" }, +    [JOP_ISTORE_2] =        { true, false, 0x3d, "istore_2" }, +    [JOP_ISTORE_3] =        { true, false, 0x3e, "istore_3" }, + +    [JOP_IRETURN] =         { false, false, 0xac, "ireturn" }, +    [JOP_LRETURN] =         { false, false, 0xad, "lreturn" }, +    [JOP_FRETURN] =         { false, false, 0xae, "freturn" }, +    [JOP_DRETURN] =         { false, false, 0xaf, "dreturn" }, +    [JOP_ARETURN] =         { false, false, 0xb0, "areturn" }, +    [JOP_RETURN] =          { false, false, 0xb1, "return" }, +    [JOP_GETSTATIC] =       { false, false, 0xb2, "getstatic" }, + +    [JOP_INVOKE_VIRTUAL] =  { false, false, 0xb6, "invokevirtual" }, +    [JOP_INVOKE_SPECIAL] =  { false, false, 0xb7, "invokespecial" }, +    [JOP_INVOKE_STATIC] =   { false, false, 0xb8, "invokestatic" }, + + +    [JOP_MONITOR_ENTER] =   { false, false, 0xc2, "monitorenter" }, +    [JOP_MONITOR_EXIT] =    { false, false, 0xc3, "monitorexit" } + + + +}; + + +/* Traduit une instruction en version humainement lisible. */ +static const char *jvm_get_instruction_text(const GJvmInstruction *, const GExeFormat *); + + + + + + +/* Indique le type défini pour une instruction d'architecture JVM. */ +G_DEFINE_TYPE(GJvmInstruction, g_jvm_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des instructions pour JVM.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_instruction_class_init(GJvmInstructionClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instance à initialiser.                              * +*                                                                             * +*  Description : Initialise une instance d'instruction d'architecture JVM.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_instruction_init(GJvmInstruction *instr) +{ +    GArchInstruction *parent;               /* Instance parente            */ + +    parent = G_ARCH_INSTRUCTION(instr); + +    //parent->get_text = (get_instruction_text_fc)jvm_get_instruction_text; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type d'instruction à représenter.                     * +*                                                                             * +*  Description : Crée une instruction pour l'architecture JVM.                * +*                                                                             * +*  Retour      : Architecture mise en place.                                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *g_jvm_instruction_new(JvmOpcodes type) +{ +    GArchInstruction *result;               /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_JVM_INSTRUCTION, NULL); + +    G_JVM_INSTRUCTION(result)->type = type; + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       AIDE A LA MISE EN PLACE D'INSTRUCTIONS                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux.                       * +*                len  = taille totale des données à analyser.                 * +*                wide = étendue de la future instruction. [OUT]               * +*                care = la lecture de l'instr. veut-elle les opcodes ? [OUT]  * +*                                                                             * +*  Description : Recherche l'identifiant de la prochaine instruction.         * +*                                                                             * +*  Retour      : Identifiant de la prochaine instruction à tenter de charger. * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +JvmOpcodes jvm_guess_next_instruction(const bin_t *data, off_t pos, off_t len, bool *wide, bool *care) +{ +    JvmOpcodes result;                      /* Identifiant à retourner     */ +    bin_t opcode;                           /* Opcode à trouver            */ + +    *wide = (data[pos] == 0xc4); + +    if (*wide && (pos + 1) == len) return JOP_COUNT; + +    opcode = data[pos + (*wide ? 1 : 0)]; + +    for (result = 0; result < JOP_COUNT; result++) +    { +        if (*wide && !_instructions[result].can_wide) continue; + +        if (_instructions[result].opcode == opcode) +        { +            *care = _instructions[result].care_of_data; +            break; +        } + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr  = instruction à traiter.                              * +*                format = format du binaire manipulé.                         * +*                                                                             * +*  Description : Traduit une instruction en version humainement lisible.      * +*                                                                             * +*  Retour      : Chaîne de caractères à libérer de la mémoire.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static const char *jvm_get_instruction_text(const GJvmInstruction *instr, const GExeFormat *format) +{ +    return _instructions[instr->type].keyword; + +} diff --git a/plugins/jvm/instruction.h b/plugins/jvm/instruction.h new file mode 100644 index 0000000..8ec9c48 --- /dev/null +++ b/plugins/jvm/instruction.h @@ -0,0 +1,151 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions JVM + * + * 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 _ARCH_JVM_INSTRUCTION_H +#define _ARCH_JVM_INSTRUCTION_H + + +#include "../instruction.h" + + + + + +/* Enumération de tous les opcodes */ +typedef enum _JvmOpcodes +{ +    JOP_NOP,                                /* nop (0x00)                  */ +    JOP_ACONST_NULL,                        /* aconst_null (0x01)          */ +    JOP_ICONST_M1,                          /* iconst_m1 (0x02)            */ +    JOP_ICONST_0,                           /* iconst_0 (0x03)             */ +    JOP_ICONST_1,                           /* iconst_1 (0x04)             */ +    JOP_ICONST_2,                           /* iconst_2 (0x05)             */ +    JOP_ICONST_3,                           /* iconst_3 (0x06)             */ +    JOP_ICONST_4,                           /* iconst_4 (0x07)             */ +    JOP_ICONST_5,                           /* iconst_5 (0x08)             */ + + +    JOP_POP,                                /* pop (0x57)                  */ +    JOP_POP2,                               /* pop2 (0x58)                 */ +    JOP_DUP,                                /* dup (0x59)                  */ +    JOP_DUP_X1,                             /* dup_x1 (0x5a)               */ +    JOP_DUP_X2,                             /* dup_x2 (0x5b)               */ +    JOP_DUP2,                               /* dup2 (0x5c)                 */ +    JOP_DUP2_X1,                            /* dup2_x1 (0x5d)              */ +    JOP_DUP2_X2,                            /* dup2_x2 (0x5e)              */ + + +    JOP_IADD,                               /* iadd (0x60)                 */ + + +    JOP_I2L,                                /* i2l (0x85)                  */ +    JOP_I2F,                                /* i2f (0x86)                  */ +    JOP_I2D,                                /* i2d (0x87)                  */ +    JOP_L2I,                                /* l2i (0x88)                  */ +    JOP_L2F,                                /* l2f (0x89)                  */ +    JOP_L2D,                                /* l2d (0x8a)                  */ +    JOP_F2I,                                /* f2i (0x8b)                  */ +    JOP_F2L,                                /* f2l (0x8c)                  */ +    JOP_F2D,                                /* f2d (0x8d)                  */ +    JOP_D2I,                                /* d2i (0x8e)                  */ +    JOP_D2L,                                /* d2l (0x8f)                  */ +    JOP_D2F,                                /* d2f (0x90)                  */ +    JOP_I2B,                                /* i2b (0x91)                  */ +    JOP_I2C,                                /* i2c (0x92)                  */ +    JOP_I2S,                                /* i2s (0x93)                  */ + + + + +    JOP_ILOAD_0,                            /* iload_0 (0x1a)              */ +    JOP_ILOAD_1,                            /* iload_1 (0x1b)              */ +    JOP_ILOAD_2,                            /* iload_2 (0x1c)              */ +    JOP_ILOAD_3,                            /* iload_3 (0x1d)              */ + + + + +    JOP_ALOAD_0,                            /* aload_0 (0x2a)              */ +    JOP_ALOAD_1,                            /* aload_1 (0x2b)              */ +    JOP_ALOAD_2,                            /* aload_2 (0x2c)              */ +    JOP_ALOAD_3,                            /* aload_3 (0x2d)              */ + + +    JOP_ISTORE_0,                           /* istore_0 (0x3b)             */ +    JOP_ISTORE_1,                           /* istore_1 (0x3c)             */ +    JOP_ISTORE_2,                           /* istore_2 (0x3d)             */ +    JOP_ISTORE_3,                           /* istore_3 (0x3e)             */ + + +    JOP_IRETURN,                            /* ireturn (0xac)              */ +    JOP_LRETURN,                            /* lreturn (0xad)              */ +    JOP_FRETURN,                            /* freturn (0xae)              */ +    JOP_DRETURN,                            /* dreturn (0xaf)              */ +    JOP_ARETURN,                            /* areturn (0xb0)              */ +    JOP_RETURN,                             /* return (0xb1)               */ +    JOP_GETSTATIC,                          /* getstatic (0xb2)            */ + +    JOP_INVOKE_VIRTUAL,                     /* invokevirtual (0xb6)        */ +    JOP_INVOKE_SPECIAL,                     /* invokespecial (0xb7)        */ +    JOP_INVOKE_STATIC,                      /* invokestatic (0xb8)         */ + +    JOP_MONITOR_ENTER,                      /* monitorenter (0xc2)         */ +    JOP_MONITOR_EXIT,                       /* monitorexit (0xc3)          */ + +    JOP_COUNT + +} JvmOpcodes; + + +#define G_TYPE_JVM_INSTRUCTION            g_jvm_instruction_get_type() +#define G_JVM_INSTRUCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_JVM_INSTRUCTION, GJvmInstruction)) +#define G_IS_JVM_INSTRUCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_JVM_INSTRUCTION)) +#define G_JVM_INSTRUCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JVM_INSTRUCTION, GJvmInstructionClass)) +#define G_IS_JVM_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JVM_INSTRUCTION)) +#define G_JVM_INSTRUCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JVM_INSTRUCTION, GJvmInstructionClass)) + + +/* Définition générique d'une instruction d'architecture JVM (instance) */ +typedef struct _GJvmInstruction GJvmInstruction; + +/* Définition générique d'une instruction d'architecture JVM (classe) */ +typedef struct _GJvmInstructionClass GJvmInstructionClass; + + +/* Indique le type défini pour une instruction d'architecture JVM. */ +GType g_jvm_instruction_get_type(void); + +/* Crée une instruction pour l'architecture JVM. */ +GArchInstruction *g_jvm_instruction_new(JvmOpcodes); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Recherche l'identifiant de la prochaine instruction. */ +JvmOpcodes jvm_guess_next_instruction(const bin_t *, off_t, off_t, bool *, bool *); + + + +#endif  /* _ARCH_JVM_INSTRUCTION_H */ diff --git a/plugins/jvm/op_add.c b/plugins/jvm/op_add.c new file mode 100644 index 0000000..fbcc682 --- /dev/null +++ b/plugins/jvm/op_add.c @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_add.c - décodage des additions + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'iadd'.                       * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_iadd(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_IADD); + +    return result; + +} diff --git a/plugins/jvm/op_const.c b/plugins/jvm/op_const.c new file mode 100644 index 0000000..fc7075c --- /dev/null +++ b/plugins/jvm/op_const.c @@ -0,0 +1,87 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_const.c - décodage des empilements de valeurs prédéfinies + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'aconst_null'.                * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_aconst_null(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_ACONST_NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'iconst_n'.                   * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_iconst_n(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    JvmOpcodes opcode;                      /* Instruction effective       */ + +    opcode = JOP_ICONST_M1 + (data[*pos] - 0x02); + +    (*pos)++; + +    result = g_jvm_instruction_new(opcode); + +    return result; + +} diff --git a/plugins/jvm/op_convert.c b/plugins/jvm/op_convert.c new file mode 100644 index 0000000..43d9d20 --- /dev/null +++ b/plugins/jvm/op_convert.c @@ -0,0 +1,433 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_convert.c - décodage des conversions entre types de base + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'd2f'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_d2f(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_D2F); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'd2i'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_d2i(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_D2I); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'd2l'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_d2l(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_D2L); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'f2d'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_f2d(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_F2D); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'f2i'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_f2i(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_F2I); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'f2l'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_f2l(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_F2L); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2b'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2b(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2B); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2c'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2c(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2C); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2d'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2d(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2D); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2f'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2f(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2F); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2l'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2l(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2L); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'i2s'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_i2s(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_I2S); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'l2d'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_l2d(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_L2D); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'l2i'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_l2i(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_L2I); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'l2f'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_l2f(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_L2F); + +    return result; + +} diff --git a/plugins/jvm/op_dup.c b/plugins/jvm/op_dup.c new file mode 100644 index 0000000..a42acd8 --- /dev/null +++ b/plugins/jvm/op_dup.c @@ -0,0 +1,190 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_dup.c - décodage des duplications d'étages de la pile + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup_x1'.                     * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup_x1(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP_X1); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup_x2'.                     * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup_x2(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP_X2); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup2'.                       * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup2(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP2); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup2_x1'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup2_x1(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP2_X1); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dup2_x2'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dup2_x2(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DUP2_X2); + +    return result; + +} diff --git a/plugins/jvm/op_getput.c b/plugins/jvm/op_getput.c new file mode 100644 index 0000000..c4d2b26 --- /dev/null +++ b/plugins/jvm/op_getput.c @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_getput.c - décodage des fonctions (get|put)* + * + * 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'getstatic'.                  * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_getstatic(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_GETSTATIC); + +    if (!jvm_read_one_operand(result, data, pos, len, JOT_FIELD_REF)) +    { +        /*free(result); FIXME */ +        return NULL; +    } + +    return result; + +} diff --git a/plugins/jvm/op_invoke.c b/plugins/jvm/op_invoke.c new file mode 100644 index 0000000..118f3a5 --- /dev/null +++ b/plugins/jvm/op_invoke.c @@ -0,0 +1,128 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_invoke.c - décodage des fonctions (get|put)* + * + * 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'invokespecial'.              * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_invokespecial(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_INVOKE_SPECIAL); + +    if (!jvm_read_one_operand(result, data, pos, len, JOT_METHOD_REF)) +    { +        /*free(result); FIXME */ +        return NULL; +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'invokestatic'.               * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_invokestatic(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_INVOKE_STATIC); + +    if (!jvm_read_one_operand(result, data, pos, len, JOT_METHOD_REF)) +    { +        /*free(result); FIXME */ +        return NULL; +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'invokevirtual'.              * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_invokevirtual(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_INVOKE_VIRTUAL); + +    if (!jvm_read_one_operand(result, data, pos, len, JOT_METHOD_REF)) +    { +        /*free(result); FIXME */ +        return NULL; +    } + +    return result; + +} diff --git a/plugins/jvm/op_load.c b/plugins/jvm/op_load.c new file mode 100644 index 0000000..faea478 --- /dev/null +++ b/plugins/jvm/op_load.c @@ -0,0 +1,92 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_load.c - décodage des instructions de chargement + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'aload_n'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_aload_n(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    JvmOpcodes opcode;                      /* Instruction effective       */ + +    opcode = JOP_ALOAD_0 + (data[*pos] - 0x2a); + +    (*pos)++; + +    result = g_jvm_instruction_new(opcode); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'iload_n'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_iload_n(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    JvmOpcodes opcode;                      /* Instruction effective       */ + +    opcode = JOP_ILOAD_0 + (data[*pos] - 0x1a); + +    (*pos)++; + +    result = g_jvm_instruction_new(opcode); + +    return result; + +} diff --git a/plugins/jvm/op_monitor.c b/plugins/jvm/op_monitor.c new file mode 100644 index 0000000..3e0b61a --- /dev/null +++ b/plugins/jvm/op_monitor.c @@ -0,0 +1,82 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_monitor.c - décodage des outils pour réaliser des sémaphores sur les objets + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'monitorenter'.               * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_monitorenter(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_MONITOR_ENTER); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'monitorexit'.                * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_monitorexit(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_MONITOR_EXIT); + +    return result; + +} diff --git a/plugins/jvm/op_nop.c b/plugins/jvm/op_nop.c new file mode 100644 index 0000000..ff2f58b --- /dev/null +++ b/plugins/jvm/op_nop.c @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_nop.c - décodage des absences d'opération + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'nop'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_nop(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_NOP); + +    return result; + +} diff --git a/plugins/jvm/op_pop.c b/plugins/jvm/op_pop.c new file mode 100644 index 0000000..a9f98f1 --- /dev/null +++ b/plugins/jvm/op_pop.c @@ -0,0 +1,82 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_pop.c - décodage des dépilements de pile dans le vide + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'pop'.                        * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_pop(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_POP); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'pop2'.                       * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_pop2(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_POP); + +    return result; + +} diff --git a/plugins/jvm/op_ret.c b/plugins/jvm/op_ret.c new file mode 100644 index 0000000..6ab6df3 --- /dev/null +++ b/plugins/jvm/op_ret.c @@ -0,0 +1,184 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_ret.c - décodage des ordres de retour + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'areturn'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_areturn(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_ARETURN); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'dreturn'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_dreturn(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_DRETURN); + +    return result; + +} +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'freturn'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_freturn(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_FRETURN); + +    return result; + +} +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'ireturn'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_ireturn(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_IRETURN); + +    return result; + +} +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'lreturn'.                    * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_lreturn(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_LRETURN); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'return'.                     * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_return(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    result = g_jvm_instruction_new(JOP_RETURN); + +    return result; + +} diff --git a/plugins/jvm/op_store.c b/plugins/jvm/op_store.c new file mode 100644 index 0000000..1804049 --- /dev/null +++ b/plugins/jvm/op_store.c @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * op_store.c - décodage des instructions d'enregistrement + * + * 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 "opcodes.h" + + +#include "instruction.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                proc = architecture ciblée par le désassemblage.             * +*                                                                             * +*  Description : Décode une instruction de type 'istore_n'.                   * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *jvm_read_instr_istore_n(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GJvmProcessor *proc) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    JvmOpcodes opcode;                      /* Instruction effective       */ + +    opcode = JOP_ISTORE_0 + (data[*pos] - 0x3b); + +    (*pos)++; + +    result = g_jvm_instruction_new(opcode); + +    return result; + +} diff --git a/plugins/jvm/opcodes.h b/plugins/jvm/opcodes.h new file mode 100644 index 0000000..7251fed --- /dev/null +++ b/plugins/jvm/opcodes.h @@ -0,0 +1,160 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * opcodes.h - prototypes pour la liste de tous les opcodes de l'architecture JVM + * + * 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 _ARCH_JVM_OPCODES_H +#define _ARCH_JVM_OPCODES_H + + +#include "processor.h" + + + +/* Décode une instruction de type 'aconst_null'. */ +GArchInstruction *jvm_read_instr_aconst_null(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'aload_n'. */ +GArchInstruction *jvm_read_instr_aload_n(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'areturn'. */ +GArchInstruction *jvm_read_instr_areturn(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'd2f'. */ +GArchInstruction *jvm_read_instr_d2f(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'd2i'. */ +GArchInstruction *jvm_read_instr_d2i(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'd2l'. */ +GArchInstruction *jvm_read_instr_d2l(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dreturn'. */ +GArchInstruction *jvm_read_instr_dreturn(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup'. */ +GArchInstruction *jvm_read_instr_dup(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup_x1'. */ +GArchInstruction *jvm_read_instr_dup_x1(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup_x2'. */ +GArchInstruction *jvm_read_instr_dup_x2(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup2'. */ +GArchInstruction *jvm_read_instr_dup2(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup2_x1'. */ +GArchInstruction *jvm_read_instr_dup2_x1(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'dup2_x2'. */ +GArchInstruction *jvm_read_instr_dup2_x2(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'f2d'. */ +GArchInstruction *jvm_read_instr_f2d(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'f2i'. */ +GArchInstruction *jvm_read_instr_f2i(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'f2l'. */ +GArchInstruction *jvm_read_instr_f2l(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'freturn'. */ +GArchInstruction *jvm_read_instr_freturn(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'getstatic'. */ +GArchInstruction *jvm_read_instr_getstatic(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2b'. */ +GArchInstruction *jvm_read_instr_i2b(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2c'. */ +GArchInstruction *jvm_read_instr_i2c(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2d'. */ +GArchInstruction *jvm_read_instr_i2d(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2f'. */ +GArchInstruction *jvm_read_instr_i2f(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2l'. */ +GArchInstruction *jvm_read_instr_i2l(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'i2s'. */ +GArchInstruction *jvm_read_instr_i2s(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'iadd'. */ +GArchInstruction *jvm_read_instr_iadd(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'iconst_n'. */ +GArchInstruction *jvm_read_instr_iconst_n(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'iload_n'. */ +GArchInstruction *jvm_read_instr_iload_n(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'invokespecial'. */ +GArchInstruction *jvm_read_instr_invokespecial(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'invokestatic'. */ +GArchInstruction *jvm_read_instr_invokestatic(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'invokevirtual'. */ +GArchInstruction *jvm_read_instr_invokevirtual(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'istore_n'. */ +GArchInstruction *jvm_read_instr_istore_n(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'ireturn'. */ +GArchInstruction *jvm_read_instr_ireturn(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'lreturn'. */ +GArchInstruction *jvm_read_instr_lreturn(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'l2d'. */ +GArchInstruction *jvm_read_instr_l2d(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'l2i'. */ +GArchInstruction *jvm_read_instr_l2i(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'l2f'. */ +GArchInstruction *jvm_read_instr_l2f(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'monitorenter'. */ +GArchInstruction *jvm_read_instr_monitorenter(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'monitorexit'. */ +GArchInstruction *jvm_read_instr_monitorexit(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'nop'. */ +GArchInstruction *jvm_read_instr_nop(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'pop'. */ +GArchInstruction *jvm_read_instr_pop(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'pop2'. */ +GArchInstruction *jvm_read_instr_pop2(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + +/* Décode une instruction de type 'return'. */ +GArchInstruction *jvm_read_instr_return(const bin_t *, off_t *, off_t, vmpa_t, const GJvmProcessor *); + + + +#endif  /* _ARCH_JVM_OPCODES_H */ diff --git a/plugins/jvm/operand.c b/plugins/jvm/operand.c new file mode 100644 index 0000000..4168bcf --- /dev/null +++ b/plugins/jvm/operand.c @@ -0,0 +1,325 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand.c - gestion des operandes de l'architecture JVM + * + * 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 "operand.h" + + +#include "../operand-int.h" +#include "../../common/endianness.h" +#include "../../format/java/pool.h" + + +#include "../../format/exe_format.h" /* FIXME : remme */ + + +/* ---------------------- COQUILLE VIDE POUR LES OPERANDES JVM ---------------------- */ + + +/* Définition d'un opérande de la JVM (instance) */ +struct _GJvmOperand +{ +    GArchOperand parent;                    /* Instance parente            */ + +}; + + +/* Définition d'un opérande de la JVM (classe) */ +struct _GJvmOperandClass +{ +    GArchOperandClass parent;               /* Classe parente              */ + +}; + + +/* Initialise la classe des opérandes JVM de base. */ +static void g_jvm_operand_class_init(GJvmOperandClass *); + +/* Initialise une instance d'opérande de base pour la JVM. */ +static void g_jvm_operand_init(GJvmOperand *); + + + +/* --------------------- OPERANDES RENVOYANT VERS UNE REFERENCE --------------------- */ + + +/* Définition d'un opérande de référence de la JVM (instance) */ +struct _GJvmRefOperand +{ +    GJvmOperand parent;                     /* Instance parente            */ + +    JvmOperandType type;                    /* Type de référence attendue  */ +    uint16_t index;                         /* Indice dans la table Java   */ + +}; + + +/* Définition d'un opérande de référence de la JVM (classe) */ +struct _GJvmRefOperandClass +{ +    GJvmOperandClass parent;                /* Classe parente              */ + +}; + + +/* Initialise la classe des opérandes de référence JVM. */ +static void g_jvm_ref_operand_class_init(GJvmRefOperandClass *); + +/* Initialise une instance d'opérande de référence pour la JVM. */ +static void g_jvm_ref_operand_init(GJvmRefOperand *); + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                        COQUILLE VIDE POUR LES OPERANDES JVM                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de JVM. */ +G_DEFINE_TYPE(GJvmOperand, g_jvm_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des opérandes JVM de base.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_operand_class_init(GJvmOperandClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand = instance à initialiser.                            * +*                                                                             * +*  Description : Initialise une instance d'opérande de base pour la JVM.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_operand_init(GJvmOperand *operand) +{ + +} + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                       OPERANDES RENVOYANT VERS UNE REFERENCE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de référence de JVM. */ +G_DEFINE_TYPE(GJvmRefOperand, g_jvm_ref_operand, G_TYPE_JVM_OPERAND); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des opérandes de référence JVM.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_ref_operand_class_init(GJvmRefOperandClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance d'opérande de référence pour la JVM. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_ref_operand_init(GJvmRefOperand *operand) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                type = type de l'opérande.                                   * +*                                                                             * +*  Description : Crée un opérande de référence pour la JVM.                   * +*                                                                             * +*  Retour      : Opérande mis en place.                                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchOperand *g_jvm_ref_operand_new(const bin_t *data, off_t *pos, off_t len, JvmOperandType type) +{ +    GJvmRefOperand *result;                 /* Structure à retourner       */ +    uint16_t index;                         /* Indice dans la table Java   */ + +    if (!read_u16(&index, data, pos, len, SRE_BIG)) +        result = NULL; + +    else +    { +        result = g_object_new(G_TYPE_JVM_REF_OPERAND, NULL); + +        /* FIXME : faire attention au type */ + +        result->type = type; +        result->index = index; + +    } + +    return G_ARCH_OPERAND(result); + +} + + +#if 0 +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand = opérande à traiter.                                * +*                format  = format du binaire manipulé.                        * +*                                                                             * +*  Description : Traduit un opérande en version humainement lisible.          * +*                                                                             * +*  Retour      : Chaîne de caractères à libérer de la mémoire.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_jvm_ref_operand_get_text(const GJvmRefOperand *operand, const exe_format *format) +{ +    char *result;                           /* Chaîne à retourner          */ + +    switch (operand->type) +    { +        case JOT_FIELD_REF: +            result = NULL;//build_reference_from_java_pool((const java_format *)format, operand->index, JRT_FIELD); +            break; +        case JOT_METHOD_REF: +            result = NULL;//build_reference_from_java_pool((const java_format *)format, operand->index, JRT_METHOD); +            break; +        default: +            result = NULL; +            break; +    } + +    if (result == NULL) +        result = strdup("<bad_reference>"); + +    return result; + +} +#endif + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                           AIDE A LA CREATION D'OPERANDES                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instruction dont la définition est à compléter. [OUT]* +*                data  = flux de données à analyser.                          * +*                pos   = position courante dans ce flux. [OUT]                * +*                len   = taille totale des données à analyser.                * +*                type  = type de l'opérande.                                  * +*                ...   = éventuelle(s) information(s) complémentaire(s).      * +*                                                                             * +*  Description : Procède à la lecture d'un opérande donné.                    * +*                                                                             * +*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool jvm_read_one_operand(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, JvmOperandType type, ...) +{ +    va_list ap;                             /* Liste des compléments       */ +    GArchOperand *op;                       /* Opérande unique décodé      */ + +    va_start(ap, type); + +    switch (type) +    { +        case JOT_FIELD_REF: +        case JOT_METHOD_REF: +            op = g_jvm_ref_operand_new(data, pos, len, type); +            break; + +        default: +            op = NULL; +            break; +    } + +    va_end(ap); + +    if (op == NULL) return false; + +    g_arch_instruction_attach_extra_operand(instr, op); + +    return true; + +} diff --git a/plugins/jvm/operand.h b/plugins/jvm/operand.h new file mode 100644 index 0000000..8f4288d --- /dev/null +++ b/plugins/jvm/operand.h @@ -0,0 +1,109 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand.h - prototypes pour la gestion des operandes de l'architecture JVM + * + * 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 _ARCH_JVM_OPERAND_H +#define _ARCH_JVM_OPERAND_H + + +#include "../instruction.h" + + + +/* Types d'opérandes supportés */ +typedef enum _JvmOperandType JvmOperandType; + + + +/* ---------------------- COQUILLE VIDE POUR LES OPERANDES JVM ---------------------- */ + + +#define G_TYPE_JVM_OPERAND            g_jvm_operand_get_type() +#define G_JVM_OPERAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_JVM_OPERAND, GJvmOperand)) +#define G_IS_JVM_OPERAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_JVM_OPERAND)) +#define G_JVM_OPERAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JVM_OPERAND, GJvmOperandClass)) +#define G_IS_JVM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JVM_OPERAND)) +#define G_JVM_OPERAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JVM_OPERAND, GJvmOperandClass)) + + +/* Définition d'un opérande de la JVM (instance) */ +typedef struct _GJvmOperand GJvmOperand; + +/* Définition d'un opérande de la JVM (classe) */ +typedef struct _GJvmOperandClass GJvmOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de JVM. */ +GType g_jvm_operand_get_type(void); + + + + + + + +/* --------------------- OPERANDES RENVOYANT VERS UNE REFERENCE --------------------- */ + + +#define G_TYPE_JVM_REF_OPERAND                  g_jvm_ref_operand_get_type() +#define G_JVM_REF_OPERAND(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), g_jvm_ref_operand_get_type(), GJvmRefOperand)) +#define G_IS_JVM_REF_OPERAND(obj)               (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_jvm_ref_operand_get_type())) +#define G_JVM_REF_OPERAND_GET_IFACE(inst)       (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_jvm_ref_operand_get_type(), GJvmRefOperandIface)) + + +/* Définition d'un opérande de référence de la JVM (instance) */ +typedef struct _GJvmRefOperand GJvmRefOperand; + +/* Définition d'un opérande de référence de la JVM (classe) */ +typedef struct _GJvmRefOperandClass GJvmRefOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de référence de JVM. */ +GType g_jvm_ref_operand_get_type(void); + +/* Crée un opérande de référence pour la JVM. */ +GArchOperand *g_jvm_ref_operand_new(const bin_t *, off_t *, off_t, JvmOperandType); + + + + + +/* ------------------------- AIDE A LA CREATION D'OPERANDES ------------------------- */ + + +/* Types d'opérandes supportés */ +enum _JvmOperandType +{ +    JOT_FIELD_REF,                          /* Référence vers un champ     */ +    JOT_METHOD_REF,                         /* Référence vers une méthode  */ + +    JOT_COUNT + +}; + + +/* Procède à la lecture d'un opérande donné. */ +bool jvm_read_one_operand(GArchInstruction *, const bin_t *, off_t *, off_t, JvmOperandType, ...); + + + +#endif  /* _ARCH_JVM_OPERAND_H */ diff --git a/plugins/jvm/processor.c b/plugins/jvm/processor.c new file mode 100644 index 0000000..f25dabc --- /dev/null +++ b/plugins/jvm/processor.c @@ -0,0 +1,400 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.c - manipulation du processeur de la JVM + * + * 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 "processor.h" + + +#include "instruction.h" +#include "opcodes.h" +#include "../processor-int.h" + + + +/* Définition du processeur de la JVM (instance) */ +struct _GJvmProcessor +{ +    GArchProcessor parent;                  /* Instance parente            */ + +}; + + +/* Définition du processeur de la JVM (classe) */ +struct _GJvmProcessorClass +{ +    GArchProcessorClass parent;             /* Classe parente              */ + +}; + + +/* Initialise la classe des processeurs de JVM. */ +static void g_jvm_processor_class_init(GJvmProcessorClass *); + +/* Initialise une instance de processeur de JVM. */ +static void g_jvm_processor_init(GJvmProcessor *); + +/* Supprime toutes les références externes. */ +static void g_jvm_processor_dispose(GJvmProcessor *); + +/* Procède à la libération totale de la mémoire. */ +static void g_jvm_processor_finalize(GJvmProcessor *); + +/* Décode une instruction dans un flux de données. */ +static GArchInstruction *g_jvm_processor_decode_instruction(const GJvmProcessor *, const bin_t *, off_t *, off_t, vmpa_t); + + +/* Indique le type défini par la GLib pour le processeur JVM. */ +G_DEFINE_TYPE(GJvmProcessor, g_jvm_processor, G_TYPE_ARCH_PROCESSOR); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des processeurs de JVM.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_processor_class_init(GJvmProcessorClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GArchProcessorClass *proc;              /* Encore une autre vision...  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_jvm_processor_dispose; +    object->finalize = (GObjectFinalizeFunc)g_jvm_processor_finalize; + +    proc = G_ARCH_PROCESSOR_CLASS(klass); + +    proc->decode = (decode_instruction_fc)g_jvm_processor_decode_instruction; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de processeur de JVM.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_processor_init(GJvmProcessor *proc) +{ +    GArchProcessor *parent;                 /* Instance parente            */ + +    parent = G_ARCH_PROCESSOR(proc); + +    parent->endianness = SRE_BIG; +    parent->memsize = MDS_32_BITS; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_processor_dispose(GJvmProcessor *proc) +{ +    G_OBJECT_CLASS(g_jvm_processor_parent_class)->dispose(G_OBJECT(proc)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : bookmark = instance d'objet GLib à traiter.                  * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_jvm_processor_finalize(GJvmProcessor *proc) +{ +    G_OBJECT_CLASS(g_jvm_processor_parent_class)->finalize(G_OBJECT(proc)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée le support de l'architecture JVM.                       * +*                                                                             * +*  Retour      : Architecture mise en place.                                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchProcessor *g_jvm_processor_new(void) +{ +    GArchProcessor *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_JVM_PROCESSOR, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = architecture visée par la procédure.                  * +*                data = flux de données à analyser.                           * +*                pos  = position courante dans ce flux. [OUT]                 * +*                len  = taille totale des données à analyser.                 * +*                addr = adresse virtuelle de l'instruction.                   * +*                                                                             * +*  Description : Décode une instruction dans un flux de données.              * +*                                                                             * +*  Retour      : Instruction mise en place.                                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GArchInstruction *g_jvm_processor_decode_instruction(const GJvmProcessor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) +{ +    GArchInstruction *result;               /* Instruction à renvoyer      */ +    bool wide;                              /* Utilisation d'étendues      */ +    bool care;                              /* Traitement des opcodes      */ +    JvmOpcodes id;                          /* Identifiant d'instruction   */ + +    id = jvm_guess_next_instruction(data, *pos, len, &wide, &care); + +    if (id != JOP_COUNT && !care) +    { +        if (wide) (*pos)++; +        (*pos)++; +    } + +    switch (id) +    { +        case JOP_NOP: +            result = jvm_read_instr_nop(data, pos, len, addr, proc); +            break; + +        case JOP_ACONST_NULL: +            result = jvm_read_instr_aconst_null(data, pos, len, addr, proc); +            break; + +        case JOP_ICONST_M1: +        case JOP_ICONST_0: +        case JOP_ICONST_1: +        case JOP_ICONST_2: +        case JOP_ICONST_3: +        case JOP_ICONST_4: +        case JOP_ICONST_5: +            result = jvm_read_instr_iconst_n(data, pos, len, addr, proc); +            break; + +        case JOP_POP: +            result = jvm_read_instr_pop(data, pos, len, addr, proc); +            break; + +        case JOP_POP2: +            result = jvm_read_instr_pop2(data, pos, len, addr, proc); +            break; + +        case JOP_DUP: +            result = jvm_read_instr_dup(data, pos, len, addr, proc); +            break; + +        case JOP_DUP_X1: +            result = jvm_read_instr_dup_x1(data, pos, len, addr, proc); +            break; + +        case JOP_DUP_X2: +            result = jvm_read_instr_dup_x2(data, pos, len, addr, proc); +            break; + +        case JOP_DUP2: +            result = jvm_read_instr_dup2(data, pos, len, addr, proc); +            break; + +        case JOP_DUP2_X1: +            result = jvm_read_instr_dup2_x1(data, pos, len, addr, proc); +            break; + +        case JOP_DUP2_X2: +            result = jvm_read_instr_dup2_x2(data, pos, len, addr, proc); +            break; + +        case JOP_IADD: +            result = jvm_read_instr_iadd(data, pos, len, addr, proc); +            break; + +        case JOP_I2L: +            result = jvm_read_instr_i2l(data, pos, len, addr, proc); +            break; + +        case JOP_I2F: +            result = jvm_read_instr_i2f(data, pos, len, addr, proc); +            break; + +        case JOP_I2D: +            result = jvm_read_instr_i2d(data, pos, len, addr, proc); +            break; + +        case JOP_L2I: +            result = jvm_read_instr_l2i(data, pos, len, addr, proc); +            break; + +        case JOP_L2F: +            result = jvm_read_instr_l2f(data, pos, len, addr, proc); +            break; + +        case JOP_L2D: +            result = jvm_read_instr_l2d(data, pos, len, addr, proc); +            break; + +        case JOP_F2I: +            result = jvm_read_instr_f2i(data, pos, len, addr, proc); +            break; + +        case JOP_F2L: +            result = jvm_read_instr_f2l(data, pos, len, addr, proc); +            break; + +        case JOP_F2D: +            result = jvm_read_instr_f2d(data, pos, len, addr, proc); +            break; + +        case JOP_D2I: +            result = jvm_read_instr_d2i(data, pos, len, addr, proc); +            break; + +        case JOP_D2L: +            result = jvm_read_instr_d2l(data, pos, len, addr, proc); +            break; + +        case JOP_D2F: +            result = jvm_read_instr_d2f(data, pos, len, addr, proc); +            break; + +        case JOP_I2B: +            result = jvm_read_instr_i2b(data, pos, len, addr, proc); +            break; + +        case JOP_I2C: +            result = jvm_read_instr_i2c(data, pos, len, addr, proc); +            break; + +        case JOP_I2S: +            result = jvm_read_instr_i2s(data, pos, len, addr, proc); +            break; + +        case JOP_ILOAD_0: +        case JOP_ILOAD_1: +        case JOP_ILOAD_2: +        case JOP_ILOAD_3: +            result = jvm_read_instr_iload_n(data, pos, len, addr, proc); +            break; + +        case JOP_ALOAD_0: +        case JOP_ALOAD_1: +        case JOP_ALOAD_2: +        case JOP_ALOAD_3: +            result = jvm_read_instr_aload_n(data, pos, len, addr, proc); +            break; + +        case JOP_ISTORE_0: +        case JOP_ISTORE_1: +        case JOP_ISTORE_2: +        case JOP_ISTORE_3: +            result = jvm_read_instr_istore_n(data, pos, len, addr, proc); +            break; + +        case JOP_IRETURN: +            result = jvm_read_instr_ireturn(data, pos, len, addr, proc); +            break; + +        case JOP_LRETURN: +            result = jvm_read_instr_lreturn(data, pos, len, addr, proc); +            break; + +        case JOP_FRETURN: +            result = jvm_read_instr_freturn(data, pos, len, addr, proc); +            break; + +        case JOP_DRETURN: +            result = jvm_read_instr_dreturn(data, pos, len, addr, proc); +            break; + +        case JOP_ARETURN: +            result = jvm_read_instr_areturn(data, pos, len, addr, proc); +            break; + +        case JOP_RETURN: +            result = jvm_read_instr_return(data, pos, len, addr, proc); +            break; + +        case JOP_GETSTATIC: +            result = jvm_read_instr_getstatic(data, pos, len, addr, proc); +            break; + +        case JOP_INVOKE_VIRTUAL: +            result = jvm_read_instr_invokevirtual(data, pos, len, addr, proc); +            break; + +        case JOP_INVOKE_SPECIAL: +            result = jvm_read_instr_invokespecial(data, pos, len, addr, proc); +            break; + +        case JOP_INVOKE_STATIC: +            result = jvm_read_instr_invokestatic(data, pos, len, addr, proc); +            break; + +        default: +            result = NULL; +            break; + +    } + +    return result; + +} diff --git a/plugins/jvm/processor.h b/plugins/jvm/processor.h new file mode 100644 index 0000000..7123d0c --- /dev/null +++ b/plugins/jvm/processor.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.h - prototypes pour la manipulation du processeur de la JVM + * + * 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 _ARCH_JVM_PROCESSOR_H +#define _ARCH_JVM_PROCESSOR_H + + +#include "../processor.h" + + + +#define G_TYPE_JVM_PROCESSOR            g_jvm_processor_get_type() +#define G_JVM_PROCESSOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_JVM_PROCESSOR, GJvmProcessor)) +#define G_IS_JVM_PROCESSOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_JVM_PROCESSOR)) +#define G_JVM_PROCESSOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JVM_PROCESSOR, GJvmProcessorClass)) +#define G_IS_JVM_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JVM_PROCESSOR)) +#define G_JVM_PROCESSOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JVM_PROCESSOR, GJvmProcessorClass)) + + +/* Définition du processeur de la JVM (instance) */ +typedef struct _GJvmProcessor GJvmProcessor; + +/* Définition du processeur de la JVM (classe) */ +typedef struct _GJvmProcessorClass GJvmProcessorClass; + + +/* Indique le type défini par la GLib pour le processeur JVM. */ +GType g_jvm_processor_get_type(void); + +/* Crée le support de l'architecture JVM. */ +GArchProcessor *g_jvm_processor_new(void); + + + +#endif  /* _ARCH_JVM_PROCESSOR_H */ diff --git a/plugins/pychrysalide/debug/Makefile.am b/plugins/pychrysalide/debug/Makefile.am index a5d7da3..3586321 100644 --- a/plugins/pychrysalide/debug/Makefile.am +++ b/plugins/pychrysalide/debug/Makefile.am @@ -5,8 +5,7 @@ libpychrysadebug_la_SOURCES =		\  	debugger.h debugger.c			\  	module.h module.c -libpychrysadebug_la_LIBADD =		\ -	gdbrsp/libpychrysadebuggdbrsp.la +libpychrysadebug_la_LIBADD =   libpychrysadebug_la_LDFLAGS =  @@ -21,4 +20,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJE  AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = gdbrsp +SUBDIRS =  diff --git a/plugins/pychrysalide/debug/module.c b/plugins/pychrysalide/debug/module.c index a2df8bf..1ce4fe8 100644 --- a/plugins/pychrysalide/debug/module.c +++ b/plugins/pychrysalide/debug/module.c @@ -26,7 +26,6 @@  #include "debugger.h" -#include "gdbrsp/module.h"  #include "../helpers.h" @@ -63,8 +62,6 @@ bool add_debug_module(PyObject *super)      result = (module != NULL); -    if (result) result = add_debug_gdbresp_module(module); -      if (!result)          Py_XDECREF(module); @@ -93,8 +90,6 @@ bool populate_debug_module(void)      if (result) result = ensure_python_binary_debugger_is_registered(); -    if (result) result = populate_debug_gdbresp_module(); -      assert(result);      return result;  | 
