diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | plugins/govm/Makefile.am | 43 | ||||
-rw-r--r-- | plugins/govm/build.c | 633 | ||||
-rw-r--r-- | plugins/govm/build.h | 65 | ||||
-rw-r--r-- | plugins/govm/goas.c | 266 | ||||
-rw-r--r-- | plugins/govm/gram.y | 174 | ||||
-rw-r--r-- | plugins/govm/instruction.c | 109 | ||||
-rw-r--r-- | plugins/govm/instruction.h | 97 | ||||
-rw-r--r-- | plugins/govm/samples/test.asm | 26 | ||||
-rw-r--r-- | plugins/govm/tok.l | 63 |
11 files changed, 1491 insertions, 0 deletions
@@ -1,3 +1,17 @@ +09-11-07 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + * plugins/govm/build.c: + * plugins/govm/build.h: + * plugins/govm/goas.c: + * plugins/govm/gram.y: + * plugins/govm/instruction.c: + * plugins/govm/instruction.h: + * plugins/govm/Makefile.am: + * plugins/govm/samples/test.asm: + * plugins/govm/tok.l: + Provide a small assembler for the GoVM architecture. + 09-10-31 Cyrille Bagard <nocbos@gmail.com> * plugins/pyoida/analysis/py_binary.c: diff --git a/configure.ac b/configure.ac index 18be62a..d340b3c 100644 --- a/configure.ac +++ b/configure.ac @@ -232,6 +232,7 @@ AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64,UINT64\nVOID:OBJECT\nVOID:OB AC_CONFIG_FILES([Makefile pixmaps/Makefile plugins/Makefile + plugins/govm/Makefile plugins/pyoida/Makefile plugins/pyoida/analysis/Makefile plugins/stackvars/Makefile diff --git a/plugins/govm/Makefile.am b/plugins/govm/Makefile.am new file mode 100644 index 0000000..7d3e212 --- /dev/null +++ b/plugins/govm/Makefile.am @@ -0,0 +1,43 @@ + +BUILT_SOURCES = gram.h + +AM_YFLAGS = -d + +lib_LTLIBRARIES = libarchgovm.la + +bin_PROGRAMS = goas + + +#--- liboidadisas + +libarchgovm_la_SOURCES = \ + instruction.h instruction.c + +libarchgovm_la_LDFLAGS = + +libarchgovm_la_LIBADD = + + +#--- goas + +goas_SOURCES = \ + build.h build.c \ + goas.c \ + gram.y \ + tok.l + + +INCLUDES = + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +goas_LDFLAGS = -L.libs + +goas_LDADD = $(LIBINTL) -larchgovm + + +# Automake fait les choses à moitié +CLEANFILES = gram.h gram.c tok.c diff --git a/plugins/govm/build.c b/plugins/govm/build.c new file mode 100644 index 0000000..3a70905 --- /dev/null +++ b/plugins/govm/build.c @@ -0,0 +1,633 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * build.c - collecte des informations à enregistrer + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "build.h" + + +#include <malloc.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + + + +/* ----------------------------- GESTION DES ETIQUETTES ----------------------------- */ + + +/* Empreinte d'une étiquette */ +typedef struct _govm_label +{ + char *name; /* Désignation humaine */ + + uint16_t offset; /* Position dans le code */ + + uint16_t *references; /* Emplacement d'utilisations */ + size_t ref_count; /* Quantité d'emplacements */ + +} govm_label; + + +#define INVALID_OFFSET 0xffff + + +/* Met en place une mémoire destinée à une étiquette. */ +static govm_label *create_govm_label(const char *); + +/* Libère la mémoire occupée par une étiquette. */ +static void delete_govm_label(govm_label *); + +/* Recherche une étiquette correspondant à un nom donné. */ +static govm_label *find_govm_label_in_list(govm_label **, size_t, const char *); + +/* Inscrit un nouvel emplacement à modifier après coup. */ +static void attach_new_ref_to_govm_label(govm_label *, uint16_t); + +/* Met à jour tous les détournements de flot liés à l'étiquette. */ +static bool resolve_all_refs_of_govm_label(const govm_label *, uint16_t *, govm_info *); + + + +/* -------------------------- PROCEDURES POUR L'ASSEMBLAGE -------------------------- */ + + +/* Regroupement des informations à enregistrer */ +struct _govm_info +{ + bool little; /* Architecture choisie */ + + uint16_t csize; /* Taille du code */ + uint16_t dsize; /* Taille des données */ + uint16_t isize; /* ??? */ + uint16_t bsize; /* ??? */ + + uint16_t start; /* Position de départ */ + + bin_t *code; /* Code binaire */ + size_t allocated; /* Taille allouée en mémoire */ + + govm_label **labels; /* Nombre d'étiquettes utiles */ + size_t labels_count; /* Quantité de ces étiquettes */ + + bool warn; /* Affichage d'avertissements */ + +}; + + +#define ALLOC_CHUCK 20 + + +/* Ajoute une instruction aux informations à enregistrer. */ +static bool add_govm_instruction_code(govm_info *, bin_t); + +/* Inscrit une nouvelle étiquette vierge. */ +static govm_label *insert_new_govm_label(govm_info *, const char *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION DES ETIQUETTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : name = désignation humaine de l'étiquette. * +* * +* Description : Met en place une mémoire destinée à une étiquette. * +* * +* Retour : Structure de représentation initialisée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static govm_label *create_govm_label(const char *name) +{ + govm_label *result; /* Structure à retourner */ + size_t len; /* Taille du nom pour analyse */ + + result = (govm_label *)calloc(1, sizeof(govm_label)); + + result->name = strdup(name); + + len = strlen(name); + if (name[len - 1] == ':') result->name[len - 1] = '\0'; + + result->offset = INVALID_OFFSET; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : label = étiquette à supprimer de la mémoire. * +* * +* Description : Libère la mémoire occupée par une étiquette. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void delete_govm_label(govm_label *label) +{ + free(label->name); + + if (label->references != NULL) + free(label->references); + + free(label); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'éléments à parcourir. * +* count = taille de la liste. * +* name = nom de l'étiquette à chercher. * +* * +* Description : Recherche une étiquette correspondant à un nom donné. * +* * +* Retour : Adresse de l'étiquette trouvée ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static govm_label *find_govm_label_in_list(govm_label **list, size_t count, const char *name) +{ + govm_label *result; /* Résultat à renvoyer */ + size_t len; /* Longueur de comparaison */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + len = strlen(name); + if (name[len - 1] == ':') len--; + + for (i = 0; i < count && result == NULL; i++) + { + if (list[i]->name == NULL) continue; + + if (strncmp(list[i]->name, name, len) == 0) + result = list[i]; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : label = élément à compléter. * +* count = taille de la liste. * +* name = nom de l'étiquette à chercher. * +* * +* Description : Inscrit un nouvel emplacement à modifier après coup. * +* * +* Retour : Adresse de l'étiquette trouvée ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void attach_new_ref_to_govm_label(govm_label *label, uint16_t ref) +{ + label->references = (uint16_t *)realloc(label->references, + ++label->ref_count * sizeof(uint16_t)); + + label->references[label->ref_count - 1] = ref; + +} + + +/****************************************************************************** +* * +* Paramètres : label = élément à manipuler. * +* pc = emplacement de la tête d'écriture à modifier. * +* info = informations globales pour l'ajout. * +* * +* Description : Met à jour tous les détournements de flot liés à l'étiquette.* +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool resolve_all_refs_of_govm_label(const govm_label *label, uint16_t *pc, govm_info *info) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = true; + + if (label->offset == INVALID_OFFSET) + { + fprintf(stderr, "Label '%s' used, but never defined !\n", label->name); + return false; + } + + if (label->ref_count == 0 && info->warn && strcmp(label->name, "start") != 0) + fprintf(stderr, "Label '%s' defined, but never used !\n", label->name); + + for (i = 0; i < label->ref_count && result; i++) + { + *pc = label->references[i]; + result = encode_govm_number(info, label->offset); + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* PROCEDURES POUR L'ASSEMBLAGE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : little = architecture en petit boutisme ? * +* warn = affichage des avertissements ? * +* * +* Description : Met en place une future collecte d'informations. * +* * +* Retour : Ensemble d'informations initialisées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +govm_info *create_govm_info(bool little, bool warn) +{ + govm_info *result; /* Structure à retourner */ + + result = (govm_info *)calloc(1, sizeof(govm_info)); + + result->little = little; + result->warn = warn; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations à libérer de la mémoire. * +* * +* Description : Supprime de la mémoire toutes les informations collectées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_govm_info(govm_info *info) +{ + size_t i; /* Boucle de parcours */ + + if (info->allocated > 0) + free(info->code); + + if (info->labels_count > 0) + { + for (i = 0; i < info->labels_count; i++) + delete_govm_label(info->labels[i]); + + free(info->labels); + + } + + free(info); + +} + + + + + + + + +bool write_u16(int fd, uint16_t val); + +bool write_u16(int fd, uint16_t val) +{ + ssize_t len; /* Quantité de données écrites */ + + len = write(fd, &val, 2); + + return (len == 2); + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* value = valeur à ajouter à la section de code. * +* * +* Description : Ajoute une instruction aux informations à enregistrer. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool add_govm_instruction_code(govm_info *info, bin_t value) +{ + bool even; /* Zone pour le demi-octet */ + + if (info->csize / 2 == info->allocated) + { + info->allocated += ALLOC_CHUCK; + info->code = (bin_t *)realloc(info->code, info->allocated * sizeof(bin_t)); + memset(&info->code[info->csize / 2], 0, ALLOC_CHUCK * sizeof(bin_t)); + } + + even = (info->csize % 2 == 0); + if (info->little) even = !even; + + if (even) + info->code[info->csize / 2] |= (value & 0x0f) << 4; + else + info->code[info->csize / 2] |= (value & 0x0f); + + info->csize++; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* id = identifiant de l'instruction à exporter. * +* * +* Description : Ajoute une instruction aux informations à enregistrer. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool encode_govm_instruction(govm_info *info, GoVMOpcodes id) +{ + bool result; /* Bilan à renvoyer */ + bin_t opcode; /* Octet d'encodage à écrire */ + + opcode = get_govm_instruction_opcode(id); + + if (opcode >= 0x08) + { + result = add_govm_instruction_code(info, (opcode & 0x0f) | 0x08); + result &= add_govm_instruction_code(info, opcode >> 3); + } + else + result = add_govm_instruction_code(info, opcode); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* value = valeur à placer directement dans le code. * +* * +* Description : Ajoute une valeur entière dans le code même. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool encode_govm_number(govm_info *info, uint16_t value) +{ + bool result; /* Bilan à renvoyer */ + size_t i; /* Boucle de parcours */ + + result = true; + + if (info->little) + for (i = 0; i < 16 && result; i += 4) + result = add_govm_instruction_code(info, (value >> i) & 0x0f); + else + for (i = 16; i > 0 && result; i -= 4) + result = add_govm_instruction_code(info, (value >> (i - 4)) & 0x0f); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* name = désignation humaine de la nouvelle étiquette. * +* * +* Description : Inscrit une nouvelle étiquette vierge. * +* * +* Retour : Adresse de l'étiquette créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static govm_label *insert_new_govm_label(govm_info *info, const char *name) +{ + govm_label *result; /* Etiquette à retourner */ + + result = create_govm_label(name); + + info->labels = (govm_label **)realloc(info->labels, ++info->labels_count * sizeof(govm_label *)); + info->labels[info->labels_count - 1] = result; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* name = désignation humaine de la nouvelle étiquette. * +* * +* Description : Enregistre un nouvel emplacement d'étiquette. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_govm_label(govm_info *info, const char *name) +{ + govm_label *label; /* Etiquette à créer */ + + label = find_govm_label_in_list(info->labels, info->labels_count, name); + + if (label == NULL) + label = insert_new_govm_label(info, name); + + if (label->offset != INVALID_OFFSET) + { + fprintf(stderr, "Label '%s' already defined !", label->name); + return false; + } + + label->offset = info->csize; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à mettre à jour. * +* id = identifiant de l'instruction à utiliser. * +* name = désignation humaine de l'étiquette visée. * +* * +* Description : Exécute un détournement de flot via une étiquette. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool encode_reference_to_govm_label(govm_info *info, GoVMOpcodes id, const char *name) +{ + govm_label *label; /* Etiquette à modifier */ + + if (!encode_govm_instruction(info, GOP_LI)) + return false; + + label = find_govm_label_in_list(info->labels, info->labels_count, name); + + if (label == NULL) + label = insert_new_govm_label(info, name); + + attach_new_ref_to_govm_label(label, info->csize); + + if (!encode_govm_number(info, 0x0000)) + return false; + + return encode_govm_instruction(info, id); + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble à initialiser. * +* fd = flux ouvert en écriture. * +* * +* Description : Procède à l'enregistrement d'un shellcode pour GoVM. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_govm_info(govm_info *info, int fd) +{ + bool result; /* Bilan à retourner */ + uint16_t tmp; /* Sauvegarde de la quantité */ + size_t i; /* Boucle de parcours */ + ssize_t len; /* Quantité de données écrites */ + uint16_t expected; /* Quantité de données à écrire*/ + govm_label *label; /* Etiquette pour le début */ + + result = true; + + tmp = info->csize; + + for (i = 0; i < info->labels_count && result; i++) + result = resolve_all_refs_of_govm_label(info->labels[i], &info->csize, info); + + info->csize = tmp; + + if (!result) return false; + + len = write(fd, "GOVM", 4); + result = (len != 4); + + if (info->little) len = write(fd, "\x10", 1); + else len = write(fd, "\x11", 1); + + result = (len != 1); + + /* Egalisation */ + if (info->csize % 2 != 0) + { + encode_govm_instruction(info, GOP_LI); + encode_govm_number(info, 0xffff); + encode_govm_instruction(info, GOP_POP); + } + + expected = (info->csize % 2 == 0 ? info->csize / 2 : info->csize / 2 + 1); + expected *= sizeof(bin_t); + + result &= write_u16(fd, expected); + result &= write_u16(fd, info->dsize); + result &= write_u16(fd, info->isize); + result &= write_u16(fd, info->bsize); + + label = find_govm_label_in_list(info->labels, info->labels_count, "start"); + if (label != NULL) info->start = label->offset; + + result &= write_u16(fd, info->start); + + len = write(fd, info->code, expected); + result = (len != expected); + + return result; + +} diff --git a/plugins/govm/build.h b/plugins/govm/build.h new file mode 100644 index 0000000..5753de4 --- /dev/null +++ b/plugins/govm/build.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * build.h - prototypes pour la collecte des informations à enregistrer + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_GOVM_BUILD_H +#define _PLUGINS_GOVM_BUILD_H + + +#include <stdbool.h> + + +#include "instruction.h" + + + +/* -------------------------- PROCEDURES POUR L'ASSEMBLAGE -------------------------- */ + + +/* Regroupement des informations à enregistrer */ +typedef struct _govm_info govm_info; + + +/* Met en place une future collecte d'informations. */ +govm_info *create_govm_info(bool, bool); + +/* Supprime de la mémoire toutes les informations collectées. */ +void delete_govm_info(govm_info *); + +/* Ajoute une instruction aux informations à enregistrer. */ +bool encode_govm_instruction(govm_info *, GoVMOpcodes); + +/* Ajoute une valeur entière dans le code même. */ +bool encode_govm_number(govm_info *, uint16_t); + +/* Enregistre un nouvel emplacement d'étiquette. */ +bool register_govm_label(govm_info *, const char *); + +/* Exécute un détournement de flot via une étiquette. */ +bool encode_reference_to_govm_label(govm_info *, GoVMOpcodes, const char *); + +/* Procède à l'enregistrement d'un shellcode pour GoVM. */ +bool write_govm_info(govm_info *, int); + + + +#endif /* _PLUGINS_GOVM_BUILD_H */ diff --git a/plugins/govm/goas.c b/plugins/govm/goas.c new file mode 100644 index 0000000..443d0d5 --- /dev/null +++ b/plugins/govm/goas.c @@ -0,0 +1,266 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * main.c - fichier d'entrée du programme + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <fcntl.h> +#include <getopt.h> +#include <libgen.h> +#include <malloc.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +#include "build.h" + + +/* gram.y : Procède à l'assemblage d'une ligne de code. */ +bool process_govm_code(govm_info *, const char *); + + +/* Affiche une description des appels au programme possibles. */ +static void show_usage(char *); + +/* Lit le fichier d'entrée ligne par ligne et l'assemble. */ +static bool feed_govm_parser(const char *, govm_info *); + + + +/****************************************************************************** +* * +* Paramètres : name = nom du programme lancé. * +* * +* Description : Affiche une description des appels au programme possibles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void show_usage(char *name) +{ + fprintf(stderr, "Usage: %s [--help] [--warn] [--output filename] [--big] [--data number] input\n", basename(name)); + + fprintf(stderr, "\n"); + + fprintf(stderr, "\t--help\t\t\tDisplay this help message.\n"); + + fprintf(stderr, "\n"); + + fprintf(stderr, "\t--warn\t\t\tDisplay warnings during the compilation.\n"); + fprintf(stderr, "\t--output filename\tDefine the output filename (a.out by default).\n"); + fprintf(stderr, "\t--big\t\t\tProduce big endian bytecode.\n"); + fprintf(stderr, "\t--data number\t\tSet the minimal data section size.\n"); + + fprintf(stderr, "\n"); + + fprintf(stderr, "\tinput\t\t\tFile containing the assembly code to compile.\n"); + + fprintf(stderr, "\n"); + +} + + +/****************************************************************************** +* * +* Paramètres : filename = chemin contenant le code à assembler. * +* info = informations tirées du contenu. * +* * +* Description : Lit le fichier d'entrée ligne par ligne et l'assemble. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool feed_govm_parser(const char *filename, govm_info *info) +{ + bool result; /* Résultat à retourner */ + int ret; /* Bilan d'un appel */ + struct stat finfo; /* Recueil des infos. fichier */ + char *buffer; /* Destination de lecture */ + FILE *stream; /* Flux d'entrée */ + size_t pos; /* Position du retour chariot */ + + result = true; + + ret = stat(filename, &finfo); + if (ret == -1) + { + perror("stat"); + return false; + } + + buffer = (char *)calloc(finfo.st_size + 1, sizeof(char)); + if (buffer == NULL) + { + perror("calloc"); + return false; + } + + stream = fopen(filename, "r"); + if (stream == NULL) + { + perror("fopen"); + result = false; + goto fgp_exit; + } + + while (result && fgets(buffer, finfo.st_size + 1, stream) != NULL) + { + pos = strlen(buffer); + + if (pos > 0 && buffer[pos - 1] == '\n') + buffer[pos - 1] = '\0'; + + result = process_govm_code(info, buffer); + + } + + fclose(stream); + + fgp_exit: + + free(buffer); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : argc = nombre d'arguments dans la ligne de commande. * +* argv = arguments de la ligne de commande. * +* * +* Description : Point d'entrée du programme. * +* * +* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int main(int argc, char **argv) +{ + int result; /* Statut en sortie */ + bool help; /* Affichage de l'aide */ + bool warn; /* Affichage d'avertissements */ + char *output; /* Fichier de sortie */ + bool big; /* Mode gros boutiste */ + uint16_t data; /* Taille min. des données */ + int option_index; /* Indice de l'argument */ + int ret; /* Bilan d'un appel */ + govm_info *info; /* Informations de construct° */ + int fd; /* Flux ouvert en écriture */ + + static struct option long_options[] = { + { "help", no_argument, NULL, 'h' }, + { "warn", no_argument, NULL, 'w' }, + { "output", required_argument, NULL, 'o' }, + { "big", no_argument, NULL, 'b' }, + { "data", required_argument, NULL, 'd' }, + { NULL, 0, NULL, 0 } + }; + + result = EXIT_SUCCESS; + + help = false; + warn = false; + output = "a.out"; + big = false; + data = 0; + + while (1) + { + ret = getopt_long(argc, argv, "hwo:bd:", long_options, &option_index); + if (ret == -1) break; + + switch (ret) + { + case 'h': + help = true; + break; + + case 'w': + warn = true; + break; + + case 'o': + output = optarg; + break; + + case 'b': + big = true; + break; + + case 'd': + data = atoi(optarg); + break; + + } + + } + + if (help || optind == argc) + { + show_usage(argv[0]); + return help ? EXIT_SUCCESS : EXIT_FAILURE; + } + + info = create_govm_info(!big, warn); + + if (!feed_govm_parser(argv[optind], info)) + { + result = EXIT_FAILURE; + goto error_parsing; + } + + fd = open(output, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (fd == -1) + { + perror("open"); + result = EXIT_FAILURE; + goto error_parsing; + } + + if (!write_govm_info(info, fd)) + { + result = EXIT_FAILURE; + goto error_writing; + } + + error_writing: + + close(fd); + + error_parsing: + + delete_govm_info(info); + + return result; + +} diff --git a/plugins/govm/gram.y b/plugins/govm/gram.y new file mode 100644 index 0000000..fe1ccc1 --- /dev/null +++ b/plugins/govm/gram.y @@ -0,0 +1,174 @@ +%{ + +#include <stdio.h> +#include <stdlib.h> + + +#include "build.h" + + +/* De tok.c... */ +extern int yylex(void); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE yy_scan_string(const char *); +extern void yy_delete_buffer(YY_BUFFER_STATE); + + +/* Affiche un message d'erreur concernant l'analyse. */ +int yyerror(govm_info *, char *); + +/* Procède à l'assemblage d'une ligne de code. */ +bool process_govm_code(govm_info *, const char *); + +%} + +%union { + + char *text; + short/*uint16_t*/ number; + +} + + +%parse-param { govm_info *info } + +%token COMMENT + +%token ADD AND CALL DIV DUP EQU GOE GT JMP JZ LB LI LOE LT LW LWS MUL NOP NOR NOT OR POP PUSH ROT ROT3 SALLOC SB SHL SHR SUB SW SWS SYSCALL XOR + +%token NUMBER LABEL TEXT +%token REG_A REG_B REG_C REG_D REG_E REG_F + +%type <text> LABEL TEXT +%type <number> NUMBER + + +%% + +input: + /* Vide */ + | input line + ; + +line: + COMMENT + | LABEL { register_govm_label(info, $1); } + | expression + ; + +expression: + ADD { encode_govm_instruction(info, GOP_ADD); } + | AND { encode_govm_instruction(info, GOP_AND); } + | data + | DIV { encode_govm_instruction(info, GOP_DIV); } + | DUP { encode_govm_instruction(info, GOP_DUP); } + | EQU { encode_govm_instruction(info, GOP_EQU); } + | flow_mod + | GOE { encode_govm_instruction(info, GOP_GOE); } + | GT { encode_govm_instruction(info, GOP_GT); } + | LI NUMBER { encode_govm_instruction(info, GOP_LI); encode_govm_number(info, $2); } + | LOE { encode_govm_instruction(info, GOP_LOE); } + | LT { encode_govm_instruction(info, GOP_LT); } + | LWS { encode_govm_instruction(info, GOP_LWS); } + | MUL { encode_govm_instruction(info, GOP_MUL); } + | NOP { encode_govm_instruction(info, GOP_NOP); } + | NOR { encode_govm_instruction(info, GOP_NOR); } + | NOT { encode_govm_instruction(info, GOP_NOT); } + | OR { encode_govm_instruction(info, GOP_OR); } + | POP { encode_govm_instruction(info, GOP_POP); } + | pop_reg + | push_reg + | ROT { encode_govm_instruction(info, GOP_ROT); } + | ROT3 { encode_govm_instruction(info, GOP_ROT3); } + | SALLOC { encode_govm_instruction(info, GOP_SALLOC); } + | SHL { encode_govm_instruction(info, GOP_SHL); } + | SHR { encode_govm_instruction(info, GOP_SHR); } + | SUB { encode_govm_instruction(info, GOP_SUB); } + | SWS { encode_govm_instruction(info, GOP_SWS); } + | SYSCALL { encode_govm_instruction(info, GOP_SYSCALL); } + | XOR { encode_govm_instruction(info, GOP_XOR); } + ; + +data: + LB { encode_govm_instruction(info, GOP_LB); } + | LW { encode_govm_instruction(info, GOP_LW); } + | SB { encode_govm_instruction(info, GOP_SB); } + | SW { encode_govm_instruction(info, GOP_SW); } + ; + +flow_mod: + CALL { encode_govm_instruction(info, GOP_CALL); } + | JMP { encode_govm_instruction(info, GOP_JMP); } + | JZ { encode_govm_instruction(info, GOP_JZ); } + | CALL TEXT { encode_reference_to_govm_label(info, GOP_CALL, $2); } + | JMP TEXT { encode_reference_to_govm_label(info, GOP_JMP, $2); } + | JZ TEXT { encode_reference_to_govm_label(info, GOP_JZ, $2); } + ; + +pop_reg: + POP REG_A { encode_govm_instruction(info, GOP_MOV_A); } + | POP REG_B { encode_govm_instruction(info, GOP_MOV_B); } + | POP REG_C { encode_govm_instruction(info, GOP_MOV_C); } + | POP REG_D { encode_govm_instruction(info, GOP_MOV_D); } + | POP REG_E { encode_govm_instruction(info, GOP_MOV_E); } + | POP REG_F { encode_govm_instruction(info, GOP_MOV_F); } + +push_reg: + PUSH REG_A { encode_govm_instruction(info, GOP_A_MOV); } + | PUSH REG_B { encode_govm_instruction(info, GOP_B_MOV); } + | PUSH REG_C { encode_govm_instruction(info, GOP_C_MOV); } + | PUSH REG_D { encode_govm_instruction(info, GOP_D_MOV); } + | PUSH REG_E { encode_govm_instruction(info, GOP_E_MOV); } + | PUSH REG_F { encode_govm_instruction(info, GOP_F_MOV); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : info = ensemble d'informations en place. * +* msg = texte à afficher. * +* * +* Description : Affiche un message d'erreur concernant l'analyse. * +* * +* Retour : Statut de sortie à fournir. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int yyerror(govm_info *info, char *msg) +{ + printf("PARSING ERROR :: %s\n", msg); + + return -1; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble d'informations à venir compléter. * +* code = ligne de code à traiter. * +* * +* Description : Procède à l'assemblage d'une ligne de code. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool process_govm_code(govm_info *info, const char *code) +{ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + buffer = yy_scan_string(code); + ret = yyparse(info); + yy_delete_buffer(buffer); + + return (ret == 0); + +} diff --git a/plugins/govm/instruction.c b/plugins/govm/instruction.c new file mode 100644 index 0000000..98ef526 --- /dev/null +++ b/plugins/govm/instruction.c @@ -0,0 +1,109 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - gestion des instructions de la machine virtuelle GoVM + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "instruction.h" + + + + + +/* Répertoire de toutes les instructions GoVM */ +typedef struct _govm_instruction +{ + bin_t opcode; /* Opcode de l'instruction */ + + const char *keyword; /* Mot clef de la commande */ + +} govm_instruction; + + +static govm_instruction _instructions[GOP_COUNT] = { + + [GOP_SYSCALL] = { 0x00, "syscall" }, + [GOP_LI] = { 0x01, "li" }, + [GOP_JMP] = { 0x02, "jmp" }, + [GOP_JZ] = { 0x03, "jz" }, + [GOP_LB] = { 0x04, "lb" }, + [GOP_LW] = { 0x05, "lw" }, + [GOP_SB] = { 0x06, "sb" }, + [GOP_SW] = { 0x07, "sw" }, + [GOP_ADD] = { 0x08, "add" }, + [GOP_SALLOC] = { 0x09, "salloc" }, + [GOP_DIV] = { 0x0a, "div" }, + [GOP_NOR] = { 0x0b, "nor" }, + [GOP_POP] = { 0x0c, "pop" }, + [GOP_DUP] = { 0x0d, "dup" }, + [GOP_ROT] = { 0x0e, "rot" }, + [GOP_ROT3] = { 0x0f, "rot3" }, + [GOP_MOV_A] = { 0x10, "pop" }, + [GOP_MOV_B] = { 0x11, "pop" }, + [GOP_MOV_C] = { 0x12, "pop" }, + [GOP_MOV_D] = { 0x13, "pop" }, + [GOP_MOV_E] = { 0x14, "pop" }, + [GOP_MOV_F] = { 0x15, "pop" }, + [GOP_A_MOV] = { 0x16, "push" }, + [GOP_B_MOV] = { 0x17, "push" }, + [GOP_C_MOV] = { 0x18, "push" }, + [GOP_D_MOV] = { 0x19, "push" }, + [GOP_E_MOV] = { 0x1a, "push" }, + [GOP_F_MOV] = { 0x1b, "push" }, + [GOP_CALL] = { 0x1c, "call" }, + [GOP_LWS] = { 0x1d, "lws" }, + [GOP_SWS] = { 0x1e, "sws" }, + [GOP_SUB] = { 0x1f, "sub" }, + [GOP_NOT] = { 0x20, "not" }, + [GOP_EQU] = { 0x21, "equ" }, + [GOP_LOE] = { 0x22, "loe" }, + [GOP_GOE] = { 0x23, "goe" }, + [GOP_LT] = { 0x24, "lt" }, + [GOP_GT] = { 0x25, "gt" }, + [GOP_AND] = { 0x26, "and" }, + [GOP_OR] = { 0x27, "or" }, + [GOP_SHL] = { 0x28, "shl" }, + [GOP_SHR] = { 0x29, "shr" }, + [GOP_MUL] = { 0x2a, "mul" }, + [GOP_NOP] = { 0x2b, "nop" }, + [GOP_XOR] = { 0x2c, "xor" } + +}; + + + + +/****************************************************************************** +* * +* Paramètres : id = identifiant de l'instruction à exporter. * +* * +* Description : Fournit de quoi encodée une instruction donnée. * +* * +* Retour : Valeur de codage de l'instruction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_t get_govm_instruction_opcode(GoVMOpcodes id) +{ + return _instructions[id].opcode; + +} diff --git a/plugins/govm/instruction.h b/plugins/govm/instruction.h new file mode 100644 index 0000000..c1ef444 --- /dev/null +++ b/plugins/govm/instruction.h @@ -0,0 +1,97 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions de la machine virtuelle GoVM + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_GOVM_INSTRUCTION_H +#define _PLUGINS_GOVM_INSTRUCTION_H + + +#include "../../src/arch/archbase.h" + + + +/* Enumération de tous les opcodes */ +typedef enum _GoVMOpcodes +{ + GOP_SYSCALL, /* syscall (0x00) */ + GOP_LI, /* li (0x01) */ + GOP_JMP, /* jmp (0x02) */ + GOP_JZ, /* jz (0x03) */ + GOP_LB, /* lb (0x04) */ + GOP_LW, /* lw (0x05) */ + GOP_SB, /* sb (0x06) */ + GOP_SW, /* sw (0x07) */ + GOP_ADD, /* add (0x08) */ + GOP_SALLOC, /* salloc (0x09) */ + GOP_DIV, /* div (0x0a) */ + GOP_NOR, /* nor (0x0b) */ + GOP_POP, /* pop (0x0c) */ + GOP_DUP, /* dup (0x0d) */ + GOP_ROT, /* rot (0x0e) */ + GOP_ROT3, /* rot3 (0x0f) */ + GOP_MOV_A, /* pop (0x10) */ + GOP_MOV_B, /* pop (0x11) */ + GOP_MOV_C, /* pop (0x12) */ + GOP_MOV_D, /* pop (0x13) */ + GOP_MOV_E, /* pop (0x14) */ + GOP_MOV_F, /* pop (0x15) */ + GOP_A_MOV, /* push (0x16) */ + GOP_B_MOV, /* push (0x17) */ + GOP_C_MOV, /* push (0x18) */ + GOP_D_MOV, /* push (0x19) */ + GOP_E_MOV, /* push (0x1a) */ + GOP_F_MOV, /* push (0x1b) */ + GOP_CALL, /* call (0x1c) */ + GOP_LWS, /* lws (0x1d) */ + GOP_SWS, /* sws (0x1e) */ + GOP_SUB, /* sub (0x1f) */ + GOP_NOT, /* not (0x20) */ + GOP_EQU, /* equ (0x21) */ + GOP_LOE, /* loe (0x22) */ + GOP_GOE, /* goe (0x23) */ + GOP_LT, /* lt (0x24) */ + GOP_GT, /* gt (0x25) */ + GOP_AND, /* and (0x26) */ + GOP_OR, /* or (0x27) */ + GOP_SHL, /* shl (0x28) */ + GOP_SHR, /* shr (0x29) */ + GOP_MUL, /* mul (0x2a) */ + GOP_NOP, /* nop (0x2b) */ + GOP_XOR, /* xor (0x2c) */ + + GOP_COUNT + +} GoVMOpcodes; + + + + + +/* Fournit de quoi encodée une instruction donnée. */ +bin_t get_govm_instruction_opcode(GoVMOpcodes); + + + + + + +#endif /* _PLUGINS_GOVM_INSTRUCTION_H */ diff --git a/plugins/govm/samples/test.asm b/plugins/govm/samples/test.asm new file mode 100644 index 0000000..b62e9f8 --- /dev/null +++ b/plugins/govm/samples/test.asm @@ -0,0 +1,26 @@ + + ; Should be skipped + jmp end + +start: + ; Let's start ! + + nop + nop + nop ; Zzz + + li 0x1234 + + li 0x01 + li 0x002 + add + + pop b + +end: + + li 0x0 + syscall ; halt + + nop + diff --git a/plugins/govm/tok.l b/plugins/govm/tok.l new file mode 100644 index 0000000..adec51d --- /dev/null +++ b/plugins/govm/tok.l @@ -0,0 +1,63 @@ +%{ + +#include "gram.h" + +%} + +%option noinput +%option nounput +%option noyywrap +%option yylineno + +%% + +;[^$]* return COMMENT; + +add return ADD; +and return AND; +call return CALL; +div return DIV; +dup return DUP; +equ return EQU; +goe return GOE; +gt return GT; +jmp return JMP; +jz return JZ; +lb return LB; +li return LI; +loe return LOE; +lt return LT; +lws return LWS; +lw return LW; +mul return MUL; +nop return NOP; +nor return NOR; +not return NOT; +or return OR; +pop return POP; +push return PUSH; +rot3 return ROT3; +rot return ROT; +salloc return SALLOC; +sb return SB; +shl return SHL; +shr return SHR; +sub return SUB; +sws return SWS; +sw return SW; +syscall return SYSCALL; +xor return XOR; + +0x[0-9a-f]{1,4} { yylval.number = strtol(yytext + 2, NULL, 16); return NUMBER; } +[A-Za-z0-9]+: { yylval.text = yytext; return LABEL; } + +a return REG_A; +b return REG_B; +c return REG_C; +d return REG_D; +e return REG_E; +f return REG_F; + +[A-Za-z0-9]+ { yylval.text = yytext; return TEXT; } + +[ \t]+ |