summaryrefslogtreecommitdiff
path: root/plugins/govm/build.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/govm/build.c')
-rw-r--r--plugins/govm/build.c633
1 files changed, 633 insertions, 0 deletions
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;
+
+}