diff options
Diffstat (limited to 'src/analysis/scan/exprs')
-rw-r--r-- | src/analysis/scan/exprs/Makefile.am | 24 | ||||
-rw-r--r-- | src/analysis/scan/exprs/arithmop-int.h | 60 | ||||
-rw-r--r-- | src/analysis/scan/exprs/arithmop.c | 414 | ||||
-rw-r--r-- | src/analysis/scan/exprs/arithmop.h | 67 | ||||
-rw-r--r-- | src/analysis/scan/exprs/boolop-int.h | 60 | ||||
-rw-r--r-- | src/analysis/scan/exprs/boolop.c | 450 | ||||
-rw-r--r-- | src/analysis/scan/exprs/boolop.h | 65 | ||||
-rw-r--r-- | src/analysis/scan/exprs/call-int.h | 63 | ||||
-rw-r--r-- | src/analysis/scan/exprs/call.c | 426 | ||||
-rw-r--r-- | src/analysis/scan/exprs/call.h | 59 | ||||
-rw-r--r-- | src/analysis/scan/exprs/literal-int.h | 73 | ||||
-rw-r--r-- | src/analysis/scan/exprs/literal.c | 605 | ||||
-rw-r--r-- | src/analysis/scan/exprs/literal.h | 70 | ||||
-rw-r--r-- | src/analysis/scan/exprs/relop-int.h | 60 | ||||
-rw-r--r-- | src/analysis/scan/exprs/relop.c | 374 | ||||
-rw-r--r-- | src/analysis/scan/exprs/relop.h | 56 | ||||
-rw-r--r-- | src/analysis/scan/exprs/str-int.h | 61 | ||||
-rw-r--r-- | src/analysis/scan/exprs/str.c | 437 | ||||
-rw-r--r-- | src/analysis/scan/exprs/str.h | 67 |
19 files changed, 3491 insertions, 0 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am new file mode 100644 index 0000000..f164864 --- /dev/null +++ b/src/analysis/scan/exprs/Makefile.am @@ -0,0 +1,24 @@ + +noinst_LTLIBRARIES = libanalysisscanexprs.la + + +libanalysisscanexprs_la_SOURCES = \ + arithmop-int.h \ + arithmop.h arithmop.c \ + boolop-int.h \ + boolop.h boolop.c \ + call-int.h \ + call.h call.c \ + literal-int.h \ + literal.h literal.c \ + relop-int.h \ + relop.h relop.c \ + str-int.h \ + str.h str.c + +libanalysisscanexprs_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanexprs_la_SOURCES:%c=) diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmop-int.h new file mode 100644 index 0000000..75f1dbb --- /dev/null +++ b/src/analysis/scan/exprs/arithmop-int.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H +#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H + + +#include "arithmop.h" + + +#include "../expr-int.h" + + + +/* Opération arithmétique impliquant deux opérandes (instance) */ +struct _GArithmOperation +{ + GScanExpression parent; /* A laisser en premier */ + + ArithmeticExpressionOperator operator; /* Type d'opération menée */ + + GScanExpression *first; /* Expression impactée #1 */ + GScanExpression *second; /* Expression impactée #2 */ + +}; + +/* Opération arithmétique impliquant deux opérandes (classe) */ +struct _GArithmOperationClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une opération arithmétique entre expressions. */ +bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */ diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c new file mode 100644 index 0000000..f57e260 --- /dev/null +++ b/src/analysis/scan/exprs/arithmop.c @@ -0,0 +1,414 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * arithmop.c - gestion des opérations arithmétiques + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "arithmop.h" + + +#include "arithmop-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des opérations arithmétiques. */ +static void g_arithmetic_operation_class_init(GArithmOperationClass *); + +/* Initialise une instance d'opération arithmétique. */ +static void g_arithmetic_operation_init(GArithmOperation *); + +/* Supprime toutes les références externes. */ +static void g_arithmetic_operation_dispose(GArithmOperation *); + +/* Procède à la libération totale de la mémoire. */ +static void g_arithmetic_operation_finalize(GArithmOperation *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *); + +/* Initialise une instance d'opération de relation. */ +static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une opération de relation entre expressions. */ +G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérations arithmétiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_arithmetic_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich; + expr->dup = (dup_expr_fc)g_arithmetic_operation_duplicate; + expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'opération arithmétique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arithmetic_operation_init(GArithmOperation *op) +{ + op->first = NULL; + op->second = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arithmetic_operation_dispose(GArithmOperation *op) +{ + g_clear_object(&op->first); + g_clear_object(&op->second); + + G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arithmetic_operation_finalize(GArithmOperation *op) +{ + G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : operator = type d'opération arithmétique à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Organise une opération arithmétique entre expressions. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL); + + if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, first, second)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser pleinement. * +* operator = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Met en place une opération arithmétique entre expressions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +{ + bool result; /* Bilan à retourner */ + ExprValueType vtype; /* Type de valeur portée */ + + result = false; + + vtype = g_scan_expression_get_value_type(first); + + if (vtype != EVT_INTEGER && vtype != EVT_PENDING) + goto exit; + + vtype = g_scan_expression_get_value_type(second); + + if (vtype != EVT_INTEGER && vtype != EVT_PENDING) + goto exit; + + if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER)) + goto exit; + + op->operator = operator; + + op->first = first; + g_object_ref(G_OBJECT(op->first)); + + op->second = second; + g_object_ref(G_OBJECT(op->second)); + + result = true; + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * +* op = opération de comparaison à réaliser. * +* status = bilan des opérations de comparaison. [OUT] * +* * +* Description : Réalise une comparaison entre objets selon un critère précis.* +* * +* Retour : true si la comparaison a pu être effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status) +{ + bool result; /* Etat à retourner */ + bool equal; /* Bilan intermédiaire */ + + result = true; // TODO : cmp parent()->type + + if (item->operator != other->operator) + { + result = compare_rich_integer_values(item->operator, other->operator, op); + goto done; + } + + equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + + if (!equal) + { + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), + G_COMPARABLE_ITEM(other->first), + op, status); + goto done; + } + + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), + G_COMPARABLE_ITEM(other->second), + op, status); + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *expr) +{ + GScanExpression *result; /* Instance copiée à retourner */ + + result = g_arithmetic_operation_new(expr->operator, expr->first, expr->second); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* final = impose une conversion finale de dernier tour. * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, bool final) +{ + GScanExpression *result; /* Instance à renvoyer */ + GScanExpression *new; /* Nouvelle expression obtenue */ + unsigned long long val_1; /* Première valeur à traiter */ + unsigned long long val_2; /* Second valeur à traiter */ + bool valid; /* Validité de ce bilan obtenu */ + unsigned long long reduced; /* Valeur réduite finale */ + + result = NULL; + + /* Réduction des éléments considérés */ + + new = g_scan_expression_reduce(expr->first, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->first)); + expr->first = new; + } + + if (expr->second != NULL) + { + new = g_scan_expression_reduce(expr->second, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->second)); + expr->second = new; + } + + } + + /* Construction d'une réduction locale ? */ + + if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + { + valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->first), &val_1); + + if (valid) + valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->second), &val_2); + + if (valid) + switch (expr->operator) + { + case AEO_PLUS: + reduced = val_1 + val_2; + break; + + case AEO_MINUS: + reduced = val_1 - val_2; + break; + + case AEO_MUL: + reduced = val_1 * val_2; + break; + + case AEO_DIV: + valid = (val_2 != 0); + if (valid) + reduced = val_1 / val_2; + break; + + case AEO_MOD: + valid = (val_2 != 0); + if (valid) + reduced = val_1 % val_2; + break; + + } + + if (valid) + result = g_literal_expression_new(EVT_INTEGER, &reduced); + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmop.h new file mode 100644 index 0000000..dcc8bf8 --- /dev/null +++ b/src/analysis/scan/exprs/arithmop.h @@ -0,0 +1,67 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * arithmop.h - prototypes pour la gestion des opérations arithmétiques + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_H +#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H + + +#include "../expr.h" + + + +#define G_TYPE_ARITHMETIC_OPERATION g_arithmetic_operation_get_type() +#define G_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation)) +#define G_IS_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION)) +#define G_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass)) +#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION)) +#define G_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass)) + + +/* Opération arithmétique impliquant deux opérandes (instance) */ +typedef struct _GArithmOperation GArithmOperation; + +/* Opération arithmétique impliquant deux opérandes (classe) */ +typedef struct _GArithmOperationClass GArithmOperationClass; + + +/* Type d'opération arithmétique */ +typedef enum _ArithmeticExpressionOperator +{ + AEO_PLUS, /* Opération binaire "+" */ + AEO_MINUS, /* Opération binaire "-" */ + AEO_MUL, /* Opération binaire "*" */ + AEO_DIV, /* Opération binaire "\" */ + AEO_MOD, /* Opération binaire "%" */ + +} ArithmeticExpressionOperator; + + +/* Indique le type défini pour une opération arithmétique entre expressions. */ +GType g_arithmetic_operation_get_type(void); + +/* Organise une opération arithmétique entre expressions. */ +GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */ diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/boolop-int.h new file mode 100644 index 0000000..c381cfe --- /dev/null +++ b/src/analysis/scan/exprs/boolop-int.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * boolop-int.h - prototypes internes pour la gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H +#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H + + +#include "boolop.h" + + +#include "../expr-int.h" + + + +/* Opération booléenne avec un ou deux opérandes (instance) */ +struct _GBoolOperation +{ + GScanExpression parent; /* A laisser en premier */ + + BooleanOperationType type; /* Type d'opération menée */ + + GScanExpression *first; /* Expression impactée #1 */ + GScanExpression *second; /* Expression impactée #2 */ + +}; + +/* Opération booléenne avec un ou deux opérandes (classe) */ +struct _GBoolOperationClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'opération booléenne. */ +bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */ diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c new file mode 100644 index 0000000..2902fdd --- /dev/null +++ b/src/analysis/scan/exprs/boolop.c @@ -0,0 +1,450 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * boolop.c - gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "boolop.h" + + +#include <assert.h> + + +#include "boolop-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des opérations booléennes. */ +static void g_boolean_operation_class_init(GBoolOperationClass *); + +/* Initialise une instance d'opération booléenne. */ +static void g_boolean_operation_init(GBoolOperation *); + +/* Supprime toutes les références externes. */ +static void g_boolean_operation_dispose(GBoolOperation *); + +/* Procède à la libération totale de la mémoire. */ +static void g_boolean_operation_finalize(GBoolOperation *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *); + +/* Reproduit une expression en place dans une nouvelle instance. */ +static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_boolean_operation_reduce(GBoolOperation *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une opération booléenne sur expression(s). */ +G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérations booléennes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_boolean_operation_class_init(GBoolOperationClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_boolean_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich; + expr->dup = (dup_expr_fc)g_boolean_operation_duplicate; + expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'opération booléenne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_boolean_operation_init(GBoolOperation *op) +{ + op->first = NULL; + op->second = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_boolean_operation_dispose(GBoolOperation *op) +{ + g_clear_object(&op->first); + g_clear_object(&op->second); + + G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_boolean_operation_finalize(GBoolOperation *op) +{ + G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Organise un appel de fonction avec ses arguments. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL); + + if (!g_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser pleinement. * +* type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Met en place une expression d'opération booléenne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second) +{ + bool result; /* Bilan à retourner */ + + result = false; + + if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN) + goto exit; + + if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN) + goto exit; + + if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN)) + goto exit; + + op->type = type; + + switch (type) + { + case BOT_AND: + case BOT_OR: + op->first = first; + g_object_ref(G_OBJECT(op->first)); + + op->second = second; + g_object_ref(G_OBJECT(op->second)); + + result = true; + break; + + case BOT_NOT: + op->first = first; + g_object_ref(G_OBJECT(op->first)); + + result = (second == NULL); + assert(second != NULL); + break; + + } + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * +* op = opération de comparaison à réaliser. * +* status = bilan des opérations de comparaison. [OUT] * +* * +* Description : Réalise une comparaison entre objets selon un critère précis.* +* * +* Retour : true si la comparaison a pu être effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status) +{ + bool result; /* Etat à retourner */ + bool equal; /* Bilan intermédiaire */ + + result = true; + + if (item->type != other->type) + { + *status = compare_rich_integer_values(item->type, other->type, op); + goto done; + } + + equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + + if (!equal) + { + *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), + G_COMPARABLE_ITEM(other->first), + op, status); + goto done; + } + + if (item->second == NULL) + { + assert(other->second == NULL); + + switch (op) + { + case RCO_LT: + case RCO_NE: + case RCO_GT: + *status = false; + break; + + case RCO_LE: + case RCO_EQ: + case RCO_GE: + *status = true; + break; + + } + + } + + else + *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), + G_COMPARABLE_ITEM(other->second), + op, status); + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr) +{ + GScanExpression *result; /* Instance copiée à retourner */ + + result = g_boolean_operation_new(expr->type, expr->first, expr->second); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* final = impose une conversion finale de dernier tour. * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, bool final) +{ + GScanExpression *result; /* Instance à renvoyer */ + GScanExpression *new; /* Nouvelle expression obtenue */ + bool values[2]; /* Valeurs des éléments portés */ + bool valid[2]; /* Validité de ces valeurs */ + + result = NULL; + + /* Réduction des éléments considérés */ + + new = g_scan_expression_reduce(expr->first, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->first)); + expr->first = new; + } + + if (expr->second != NULL) + { + new = g_scan_expression_reduce(expr->second, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->second)); + expr->second = new; + } + + } + + /* Construction d'une réduction locale ? */ + + switch (expr->type) + { + case BOT_AND: + if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + { + valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); + valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + + if (valid[0] && valid[1]) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); + + else + /* Etre malin si 0 && x => bilan (si ctx->quick) */ + ; + + } + break; + + case BOT_OR: + if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + { + valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); + valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + + if (valid[0] && valid[1]) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); + + } + break; + + case BOT_NOT: + if (G_IS_LITERAL_EXPRESSION(expr->first)) + { + valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); + + if (valid[0]) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[1] }); + + } + break; + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/boolop.h new file mode 100644 index 0000000..4add5a1 --- /dev/null +++ b/src/analysis/scan/exprs/boolop.h @@ -0,0 +1,65 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * boolop.h - prototypes pour la gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_H +#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H + + +#include "../expr.h" + + + +#define G_TYPE_BOOLEAN_OPERATION g_boolean_operation_get_type() +#define G_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation)) +#define G_IS_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION)) +#define G_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass)) +#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION)) +#define G_BOOLEAN_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass)) + + +/* Opération booléenne avec un ou deux opérandes (instance) */ +typedef struct _GBoolOperation GBoolOperation; + +/* Opération booléenne avec un ou deux opérandes (classe) */ +typedef struct _GBoolOperationClass GBoolOperationClass; + + +/* Types d'opérations booléennes supportées */ +typedef enum _BooleanOperationType +{ + BOT_AND, /* Opérateur binaire "and" */ + BOT_OR, /* Opérateur binaire "or" */ + BOT_NOT, /* Opérateur unaire "not" */ + +} BooleanOperationType; + + +/* Indique le type défini pour une opération booléenne sur expression(s). */ +GType g_boolean_operation_get_type(void); + +/* Organise un appel de fonction avec ses arguments. */ +GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */ diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h new file mode 100644 index 0000000..d68977f --- /dev/null +++ b/src/analysis/scan/exprs/call-int.h @@ -0,0 +1,63 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_CALL_INT_H +#define _ANALYSIS_SCAN_EXPRS_CALL_INT_H + + +#include "call.h" + + +#include "../expr-int.h" + + + +/* Exécution d'une fonction auxiliaire d'analyse (instance) */ +struct _GPendingCall +{ + GScanExpression parent; /* A laisser en premier */ + + GRegisteredItem *base; /* Base de recherche */ + char *target; /* Cible dans l'espace */ + + GScanExpression **args; /* Arguments d'appel fournis */ + size_t count; /* Quantité de ces arguments */ + + struct _GPendingCall *next; /* Evnetuel prochain élément */ + +}; + +/* Exécution d'une fonction auxiliaire d'analyse (classe) */ +struct _GPendingCallClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'appel. */ +bool g_pending_call_create(GPendingCall *, const char *, size_t, GScanExpression **, size_t); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_CALL_INT_H */ diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c new file mode 100644 index 0000000..76f5fc3 --- /dev/null +++ b/src/analysis/scan/exprs/call.c @@ -0,0 +1,426 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * call.c - organisation d'un appel à un élément de scan enregistré + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "call.h" + + +#include <malloc.h> +#include <string.h> + + +#include "call-int.h" +#include "../../../core/global.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des appels de fonction avec arguments. */ +static void g_pending_call_class_init(GPendingCallClass *); + +/* Initialise une instance d'appel de fonction avec arguments. */ +static void g_pending_call_init(GPendingCall *); + +/* Supprime toutes les références externes. */ +static void g_pending_call_dispose(GPendingCall *); + +/* Procède à la libération totale de la mémoire. */ +static void g_pending_call_finalize(GPendingCall *); + +/* Définit une base de recherche pour la cible d'appel. */ +static void g_pending_call_set_base(GPendingCall *, GRegisteredItem *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Reproduit une expression en place dans une nouvelle instance. */ +static GScanExpression *g_pending_call_duplicate(const GPendingCall *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des appels de fonction avec arguments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pending_call_class_init(GPendingCallClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_pending_call_dispose; + object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->dup = (dup_expr_fc)g_pending_call_duplicate; + expr->reduce = (reduce_expr_fc)g_pending_call_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : call = instance à initialiser. * +* * +* Description : Initialise une instance d'appel de fonction avec arguments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pending_call_init(GPendingCall *call) +{ + call->base = NULL; + call->target = NULL; + + call->args = NULL; + call->count = 0; + + call->next = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : call = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pending_call_dispose(GPendingCall *call) +{ + size_t i; /* Boucle de parcours */ + + g_clear_object(&call->base); + + for (i = 0; i < call->count; i++) + g_clear_object(&call->args[i]); + + g_clear_object(&call->next); + + G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call)); + +} + + +/****************************************************************************** +* * +* Paramètres : call = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pending_call_finalize(GPendingCall *call) +{ + if (call->target != NULL) + free(call->target); + + if (call->args != NULL) + free(call->args); + + G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de l'objet d'appel à identifier. * +* len = taille de cette désignation. * +* args = éventuelle liste d'arguments à actionner. * +* count = quantité de ces arguments. * +* * +* Description : Organise un appel de fonction avec ses arguments. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpression **args, size_t count) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_PENDING_CALL, NULL); + + if (!g_pending_call_create(G_PENDING_CALL(result), target, len, args, count)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : call = instance à initialiser pleinement. * +* target = désignation de l'objet d'appel à identifier. * +* len = taille de cette désignation. * +* args = éventuelle liste d'arguments à actionner. * +* count = quantité de ces arguments. * +* * +* Description : Met en place une expression d'appel. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, GScanExpression **args, size_t count) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = g_scan_expression_create(G_SCAN_EXPRESSION(call), EVT_PENDING); + if (!result) goto exit; + + call->target = strndup(target, len); + + call->args = malloc(count * sizeof(GScanExpression *)); + call->count = count; + + for (i = 0; i < count; i++) + { + call->args[i] = args[i]; + g_object_ref(G_OBJECT(args[i])); + } + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : call = expression d'appel à actualiser. * +* base = zone de recherche pour la résolution à venir. * +* * +* Description : Définit une base de recherche pour la cible d'appel. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pending_call_set_base(GPendingCall *call, GRegisteredItem *base) +{ + call->base = base; + g_object_ref(G_OBJECT(base)); + +} + + +/****************************************************************************** +* * +* Paramètres : call = expression d'appel à compléter. * +* next = expression d'appel suivante dans la chaîne. * +* * +* Description : Complète la chaine d'expressions d'appel. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next) +{ + call->next = next; + g_object_ref(G_OBJECT(next)); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : expr = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr) +{ + GScanExpression *result; /* Instance copiée à retourner */ + + result = g_pending_call_new(expr->target, strlen(expr->target), expr->args, expr->count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* final = indique une ultime conversion dans le cycle en cours.* +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, bool final) +{ + GScanExpression *result; /* Instance à renvoyer */ + size_t i; /* Boucle de parcours */ + GScanExpression *new; /* Nouvelle expression obtenue */ + bool last; /* Détection de fin de chaîne */ + GRegisteredItem *base; /* Base de recherche courante */ + GRegisteredItem *rebase; /* Nouvelle base résolue */ + GScanExpression *new_next; /* Nouvelle version du suivant */ + + for (i = 0; i < expr->count; i++) + { + new = g_scan_expression_reduce(expr->args[i], ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->args[i])); + expr->args[i] = new; + } + + } + + last = (expr->next == NULL); + + if (!last) + new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr->next)); + else + new_next = NULL; + + if (expr->target != NULL) + { + if (expr->base != NULL) + { + base = expr->base; + g_object_ref(G_OBJECT(base)); + } + else + base = G_REGISTERED_ITEM(get_rost_root_namespace()); + + rebase = g_registered_item_resolve(base, expr->target, ctx, + last ? NULL : expr->args, last ? 0 : expr->count, + last, final); + + g_object_unref(G_OBJECT(base)); + + if (rebase == NULL) + { + result = NULL; + goto done; + } + + if (last) + { + g_pending_call_set_base(expr, rebase); + + free(expr->target); + expr->target = NULL; + + } + else + g_pending_call_set_base(G_PENDING_CALL(new_next), rebase); + + } + + if (last) + result = g_registered_item_reduce(expr->base, ctx, expr->args, expr->count, final); + + else + { + result = g_scan_expression_reduce(new_next, ctx, final); + + if (result == NULL) + { + g_object_ref(G_OBJECT(new_next)); + result = new_next; + } + + } + + done: + + g_clear_object(&new_next); + + return result; + +} diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h new file mode 100644 index 0000000..b69ca85 --- /dev/null +++ b/src/analysis/scan/exprs/call.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_CALL_H +#define _ANALYSIS_SCAN_EXPRS_CALL_H + + +#include "../expr.h" +#include "../item.h" + + + +#define G_TYPE_PENDING_CALL g_pending_call_get_type() +#define G_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall)) +#define G_IS_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL)) +#define G_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass)) +#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL)) +#define G_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass)) + + +/* Exécution d'une fonction auxiliaire d'analyse (instance) */ +typedef struct _GPendingCall GPendingCall; + +/* Exécution d'une fonction auxiliaire d'analyse (classe) */ +typedef struct _GPendingCallClass GPendingCallClass; + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +GType g_pending_call_get_type(void); + +/* Organise un appel de fonction avec ses arguments. */ +GScanExpression *g_pending_call_new(const char *, size_t, GScanExpression **, size_t); + +/* Complète la chaine d'expressions d'appel. */ +void g_pending_call_attach_next(GPendingCall *, GPendingCall *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_CALL_H */ diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h new file mode 100644 index 0000000..d803d30 --- /dev/null +++ b/src/analysis/scan/exprs/literal-int.h @@ -0,0 +1,73 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal-int.h - prototypes internes pour la représentation d'une valeur concrète + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H +#define _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H + + +#include "literal.h" + + +#include <stdbool.h> + + +#include "../expr-int.h" + + + +/* Expression portant une valeur concrète (instance) */ +struct _GLiteralExpression +{ + GScanExpression parent; /* A laisser en premier */ + + ExprValueType value_type; /* Type de valeur portée */ + + union + { + bool boolean; /* Valeur booléenne */ + unsigned long long integer; /* Valeur entière 64 bits */ + char *string; /* Chaîne de caractères */ + struct + { + char *regex; /* Formulation d'origine */ + regex_t preg; /* Expression rationnelle */ + }; + + } value; + +}; + +/* Expression portant une valeur concrète (classe) */ +struct _GLiteralExpressionClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression de valeur concrête. */ +bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H */ diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c new file mode 100644 index 0000000..f40747d --- /dev/null +++ b/src/analysis/scan/exprs/literal.c @@ -0,0 +1,605 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.c - représentation d'une valeur concrète + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "literal.h" + + +#include <assert.h> +#include <stdarg.h> +#include <string.h> + + +#include "literal-int.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des expressions de valeur concrète. */ +static void g_literal_expression_class_init(GLiteralExpressionClass *); + +/* Initialise une instance d'expression de valeur concrète. */ +static void g_literal_expression_init(GLiteralExpression *); + +/* Supprime toutes les références externes. */ +static void g_literal_expression_dispose(GLiteralExpression *); + +/* Procède à la libération totale de la mémoire. */ +static void g_literal_expression_finalize(GLiteralExpression *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *); + +/* Reproduit une expression en place dans une nouvelle instance. */ +static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_literal_expression_reduce(GLiteralExpression *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des expressions de valeur concrète. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_literal_expression_class_init(GLiteralExpressionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose; + object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich; + expr->dup = (dup_expr_fc)g_literal_expression_duplicate; + expr->reduce = (reduce_expr_fc)g_literal_expression_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser. * +* * +* Description : Initialise une instance d'expression de valeur concrète. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_literal_expression_init(GLiteralExpression *expr) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_literal_expression_dispose(GLiteralExpression *expr) +{ + G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr)); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_literal_expression_finalize(GLiteralExpression *expr) +{ + G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr)); + +} + + +/****************************************************************************** +* * +* Paramètres : vtype = type de valeur associée par l'expression. * +* ... = valeur concrête à intégrer. * +* * +* Description : Organise un appel de fonction avec ses arguments. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_literal_expression_new(ExprValueType vtype, ...) +{ + GScanExpression *result; /* Structure à retourner */ + va_list ap; /* Liste d'arguements */ + void *ptr; /* Vision générique de valeur */ + + result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL); + + va_start(ap, vtype); + + ptr = va_arg(ap, void *); + + if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr)) + g_clear_object(&result); + + va_end(ap); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser pleinement. * +* vtype = type de valeur associée par l'expression. * +* ... = valeur concrête à intégrer. * +* * +* Description : Met en place une expression de valeur concrête. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...) +{ + bool result; /* Bilan à retourner */ + va_list ap; /* Liste d'arguements */ + const bool *boolean; /* Valeur booléenne */ + const unsigned long long *integer; /* Valeur entière 64 bits */ + const char *string; /* Chaîne de caractères */ + size_t len; /* Taille de la chaîne */ + int cflags; /* Détails de compilation */ + unsigned int i; /* Boucle de parcours */ + char *tmp; /* Zone de travail temporaire */ + int ret; /* Bilan d'une opération */ + + result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype); + + if (result) + { + va_start(ap, vtype); + + switch (vtype) + { + case EVT_BOOLEAN: + boolean = va_arg(ap, const bool *); + expr->value.boolean = *boolean; + break; + + case EVT_INTEGER: + integer = va_arg(ap, const unsigned long long *); + expr->value.integer = *integer; + break; + + case EVT_STRING: + string = va_arg(ap, const char *); + expr->value.string = strdup(string); + break; + + case EVT_REG_EXPR: + string = va_arg(ap, const char *); + len = strlen(string); + + result = (len > 2 && string[0] == '/'); + + cflags = REG_EXTENDED | REG_NOSUB; + + for (i = 0; i < 2 && result; i++) + { + result = (len > 2); + + if (string[len - 1] == 'i') + { + cflags |= REG_ICASE; + len -= 1; + } + + else if (string[len - 1] == 's') + { + cflags |= REG_NEWLINE; + len -= 1; + } + + else if (string[len - 1] == '/') + break; + + } + + if (result) + result = (string[len - 1] == '/'); + + if (result) + { + assert(len > 2); + + tmp = strndup(&string[1], len - 2); + ret = regcomp(&expr->value.preg, tmp, cflags); + free(tmp); + + result = (ret == 0); + + if (result) + expr->value.regex = strdup(string); + + } + + break; + + default: + result = false; + break; + + } + + va_end(ap); + + } + + expr->value_type = vtype; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression booléenne. * +* * +* Retour : true si l'expression est de type booléen, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value) +{ + bool result; /* Etat à retourner */ + + result = (item->value_type == EVT_BOOLEAN); + + if (result) + *value = item->value.boolean; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression d'entier. * +* * +* Retour : true si l'expression est de type entier, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value) +{ + bool result; /* Etat à retourner */ + + result = (item->value_type == EVT_INTEGER); + + if (result) + *value = item->value.integer; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression de chaîne. * +* * +* Retour : true si l'expression est de type entier, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_literal_expression_get_string_value(const GLiteralExpression *item, const char **value) +{ + bool result; /* Etat à retourner */ + + result = (item->value_type == EVT_STRING); + + if (result) + *value = item->value.string; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression rationnelle. * +* * +* Retour : true si l'expression est de type entier, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value) +{ + bool result; /* Etat à retourner */ + + result = (item->value_type == EVT_REG_EXPR); + + if (result) + *value = &item->value.preg; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * +* op = opération de comparaison à réaliser. * +* status = bilan des opérations de comparaison. [OUT] * +* * +* Description : Réalise une comparaison entre objets selon un critère précis.* +* * +* Retour : true si la comparaison a pu être effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status) +{ + bool result; /* Etat à retourner */ + int cmp; /* Bilan intermédiaire */ + + if (item->value_type != other->value_type) + { + *status = compare_rich_integer_values(item->value_type, other->value_type, op); + result = true; + goto done; + } + + switch (item->value_type) + { + case EVT_BOOLEAN: + switch (op) + { + case RCO_EQ: + *status = (item->value.boolean == other->value.boolean); + result = true; + break; + + case RCO_NE: + *status = (item->value.boolean != other->value.boolean); + result = true; + break; + + default: + result = false; + break; + + }; + break; + + case EVT_INTEGER: + *status = compare_rich_integer_values(item->value.integer, other->value.integer, op); + result = true; + break; + + case EVT_STRING: + cmp = strcmp(item->value.string, other->value.string); + *status = compare_rich_integer_values(cmp, 0, op); + result = true; + break; + + case EVT_REG_EXPR: + cmp = strcmp(item->value.regex, other->value.regex); + *status = compare_rich_integer_values(cmp, 0, op); + result = true; + break; + + default: + result = false; + break; + + } + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *expr) +{ + GScanExpression *result; /* Instance copiée à retourner */ + const void *ptr; /* Pointeur vers des données */ + + switch (expr->value_type) + { + case EVT_BOOLEAN: + ptr = &expr->value.boolean; + break; + + case EVT_INTEGER: + ptr = &expr->value.integer; + break; + + case EVT_STRING: + ptr = &expr->value.string; + break; + + case EVT_REG_EXPR: + ptr = &expr->value.regex; + break; + + default: + ptr = NULL; + break; + + } + + assert(ptr != NULL); + + result = g_literal_expression_new(expr->value_type, ptr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* force = impose une conversion en booléen si possible. * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, bool force) +{ + GScanExpression *result; /* Instance à renvoyer */ + + if (!force) + result = NULL; + + else + switch (expr->value_type) + { + case EVT_BOOLEAN: + result = NULL; + break; + + case EVT_INTEGER: + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { expr->value.integer > 0 }); + break; + + case EVT_STRING: + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.string) > 0 }); + break; + + case EVT_REG_EXPR: + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.regex) > 0 }); + break; + + default: + result = NULL; + break; + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h new file mode 100644 index 0000000..ac5724f --- /dev/null +++ b/src/analysis/scan/exprs/literal.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.h - prototypes pour la représentation d'une valeur concrète + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_LITERAL_H +#define _ANALYSIS_SCAN_EXPRS_LITERAL_H + + +#include <regex.h> + + +#include "../expr.h" + + + +#define G_TYPE_LITERAL_EXPRESSION g_literal_expression_get_type() +#define G_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression)) +#define G_IS_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION)) +#define G_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass)) +#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION)) +#define G_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass)) + + +/* Expression portant une valeur concrète (instance) */ +typedef struct _GLiteralExpression GLiteralExpression; + +/* Expression portant une valeur concrète (classe) */ +typedef struct _GLiteralExpressionClass GLiteralExpressionClass; + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +GType g_literal_expression_get_type(void); + +/* Organise un appel de fonction avec ses arguments. */ +GScanExpression *g_literal_expression_new(ExprValueType, ...); + +/* Indique la valeur portée par une expression booléenne. */ +bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *); + +/* Indique la valeur portée par une expression d'entier. */ +bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *); + +/* Indique la valeur portée par une expression de chaîne. */ +bool g_literal_expression_get_string_value(const GLiteralExpression *, const char **); + +/* Indique la valeur portée par une expression rationnelle. */ +bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_H */ diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relop-int.h new file mode 100644 index 0000000..273b543 --- /dev/null +++ b/src/analysis/scan/exprs/relop-int.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * relop-int.h - prototypes internes pour la gestion des opérations relationnelles + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_INT_H +#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H + + +#include "relop.h" + + +#include "../expr-int.h" + + + +/* Opération relationnelle impliquant deux opérandes (instance) */ +struct _GRelOperation +{ + GScanExpression parent; /* A laisser en premier */ + + RichCmpOperation rel_type; /* Type de relation étudiée */ + + GScanExpression *first; /* Expression impactée #1 */ + GScanExpression *second; /* Expression impactée #2 */ + +}; + +/* Opération relationnelle impliquant deux opérandes (classe) */ +struct _GRelOperationClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une opération relationnelle entre expressions. */ +bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */ diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c new file mode 100644 index 0000000..94ce77d --- /dev/null +++ b/src/analysis/scan/exprs/relop.c @@ -0,0 +1,374 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * relop.c - gestion des opérations relationnelles + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "relop.h" + + +#include "relop-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des opérations de relations. */ +static void g_relational_operation_class_init(GRelOperationClass *); + +/* Initialise une instance d'opération de relation. */ +static void g_relational_operation_init(GRelOperation *); + +/* Supprime toutes les références externes. */ +static void g_relational_operation_dispose(GRelOperation *); + +/* Procède à la libération totale de la mémoire. */ +static void g_relational_operation_finalize(GRelOperation *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *); + +/* Initialise une instance d'opération de relation. */ +static GScanExpression *g_relational_operation_duplicate(const GRelOperation *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_relational_operation_reduce(GRelOperation *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une opération de relation entre expressions. */ +G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérations de relations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_relational_operation_class_init(GRelOperationClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_relational_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich; + expr->dup = (dup_expr_fc)g_relational_operation_duplicate; + expr->reduce = (reduce_expr_fc)g_relational_operation_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'opération de relation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_relational_operation_init(GRelOperation *op) +{ + op->first = NULL; + op->second = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_relational_operation_dispose(GRelOperation *op) +{ + g_clear_object(&op->first); + g_clear_object(&op->second); + + G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_relational_operation_finalize(GRelOperation *op) +{ + G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Organise une opération relationnelle entre expressions. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *first, GScanExpression *second) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL); + + if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, first, second)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser pleinement. * +* type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* * +* Description : Met en place une opération relationnelle entre expressions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *first, GScanExpression *second) +{ + bool result; /* Bilan à retourner */ + + result = false; + + if (g_scan_expression_get_value_type(first) != g_scan_expression_get_value_type(first)) + goto exit; + + if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN)) + goto exit; + + op->rel_type = type; + + op->first = first; + g_object_ref(G_OBJECT(op->first)); + + op->second = second; + g_object_ref(G_OBJECT(op->second)); + + result = true; + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * +* op = opération de comparaison à réaliser. * +* status = bilan des opérations de comparaison. [OUT] * +* * +* Description : Réalise une comparaison entre objets selon un critère précis.* +* * +* Retour : true si la comparaison a pu être effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status) +{ + bool result; /* Etat à retourner */ + bool equal; /* Bilan intermédiaire */ + + result = true; // TODO : cmp parent()->type + + if (item->rel_type != other->rel_type) + { + result = compare_rich_integer_values(item->rel_type, other->rel_type, op); + goto done; + } + + equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + + if (!equal) + { + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), + G_COMPARABLE_ITEM(other->first), + op, status); + goto done; + } + + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), + G_COMPARABLE_ITEM(other->second), + op, status); + + done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_relational_operation_duplicate(const GRelOperation *expr) +{ + GScanExpression *result; /* Instance copiée à retourner */ + + result = g_relational_operation_new(expr->rel_type, expr->first, expr->second); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* final = impose une conversion finale de dernier tour. * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, bool final) +{ + GScanExpression *result; /* Instance à renvoyer */ + GScanExpression *new; /* Nouvelle expression obtenue */ + bool status; /* Bilan d'une comparaison */ + bool valid; /* Validité de ce bilan obtenu */ + + result = NULL; + + /* Réduction des éléments considérés */ + + new = g_scan_expression_reduce(expr->first, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->first)); + expr->first = new; + } + + if (expr->second != NULL) + { + new = g_scan_expression_reduce(expr->second, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(expr->second)); + expr->second = new; + } + + } + + /* Construction d'une réduction locale ? */ + + if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + { + valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->first), + G_COMPARABLE_ITEM(expr->second), + expr->rel_type, &status); + + if (valid) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h new file mode 100644 index 0000000..ecbc8ef --- /dev/null +++ b/src/analysis/scan/exprs/relop.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * relop.h - prototypes pour la gestion des opérations relationnelles + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_H +#define _ANALYSIS_SCAN_EXPRS_RELOP_H + + +#include "../expr.h" +#include "../../../glibext/comparison.h" + + + +#define G_TYPE_RELATIONAL_OPERATION g_relational_operation_get_type() +#define G_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation)) +#define G_IS_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION)) +#define G_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass)) +#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION)) +#define G_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass)) + + +/* Opération relationnelle impliquant deux opérandes (instance) */ +typedef struct _GRelOperation GRelOperation; + +/* Opération relationnelle impliquant deux opérandes (classe) */ +typedef struct _GRelOperationClass GRelOperationClass; + + +/* Indique le type défini pour une opération de relation entre expressions. */ +GType g_relational_operation_get_type(void); + +/* Organise une opération relationnelle entre expressions. */ +GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_H */ diff --git a/src/analysis/scan/exprs/str-int.h b/src/analysis/scan/exprs/str-int.h new file mode 100644 index 0000000..9bed5cf --- /dev/null +++ b/src/analysis/scan/exprs/str-int.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * str-int.h - prototypes internes pour la gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_STR_INT_H +#define _ANALYSIS_SCAN_EXPRS_STR_INT_H + + +#include "str.h" + + +#include "../expr-int.h" + + + +/* Opération booléenne avec un ou deux opérandes (instance) */ +struct _GStringOperation +{ + GScanExpression parent; /* A laisser en premier */ + + StringOperationType type; /* Type d'opération menée */ + bool case_sensitive; /* Respect de la casse ? */ + + GScanExpression *first; /* Expression impactée #1 */ + GScanExpression *second; /* Expression impactée #2 */ + +}; + +/* Opération booléenne avec un ou deux opérandes (classe) */ +struct _GStringOperationClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'opération traite une chaîne. */ +bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_STR_INT_H */ diff --git a/src/analysis/scan/exprs/str.c b/src/analysis/scan/exprs/str.c new file mode 100644 index 0000000..675b2f6 --- /dev/null +++ b/src/analysis/scan/exprs/str.c @@ -0,0 +1,437 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * str.c - gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "str.h" + + +#include <assert.h> +#include <string.h> +#include <strings.h> + + +#include "str-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des opérations visant des chaînes. */ +static void g_string_operation_class_init(GStringOperationClass *); + +/* Initialise une instance d'opération visant une chaîne. */ +static void g_string_operation_init(GStringOperation *); + +/* Supprime toutes les références externes. */ +static void g_string_operation_dispose(GStringOperation *); + +/* Procède à la libération totale de la mémoire. */ +static void g_string_operation_finalize(GStringOperation *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Reproduit une expression en place dans une nouvelle instance. */ +static GScanExpression *g_string_operation_duplicate(const GStringOperation *); + +/* Réduit une expression à une forme plus simple. */ +GScanExpression *g_string_operation_reduce(GStringOperation *, GScanContext *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une opération traitant une chaîne de caractères. */ +G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérations visant des chaînes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_operation_class_init(GStringOperationClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->dup = (dup_expr_fc)g_string_operation_duplicate; + expr->reduce = (reduce_expr_fc)g_string_operation_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'opération visant une chaîne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_operation_init(GStringOperation *op) +{ + op->first = NULL; + op->second = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_operation_dispose(GStringOperation *op) +{ + g_clear_object(&op->first); + g_clear_object(&op->second); + + G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_operation_finalize(GStringOperation *op) +{ + G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* sensitive = détermine la prise en compte de la casse. * +* * +* Description : Organise un appel de fonction avec ses arguments. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_STRING_OPERATION, NULL); + + if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser pleinement. * +* type = type d'opération booléenne à représenter. * +* first = premier opérande concerné. * +* second = éventuel second opérande impliqué ou NULL. * +* sensitive = détermine la prise en compte de la casse. * +* * +* Description : Met en place une expression d'opération traite une chaîne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) +{ + bool result; /* Bilan à retourner */ + ExprValueType vtype; /* Type de valeur portée */ + + result = false; + + vtype = g_scan_expression_get_value_type(first); + + if (vtype != EVT_STRING && vtype != EVT_PENDING) + goto exit; + + vtype = g_scan_expression_get_value_type(second); + + if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING) + goto exit; + + op->type = type; + + switch (type) + { + case SOT_CONTAINS: + case SOT_STARTSWITH: + case SOT_ENDSWITH: + op->case_sensitive = sensitive; + break; + + case SOT_MATCHES: + break; + + case SOT_IEQUALS: + assert(!sensitive); + op->case_sensitive = false; + break; + + } + + op->first = first; + g_object_ref(G_OBJECT(op->first)); + + op->second = second; + g_object_ref(G_OBJECT(op->second)); + + result = true; + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : op = expression à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : Nouvelle instance d'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_string_operation_duplicate(const GStringOperation *op) +{ + GScanExpression *result; /* Instance copiée à retourner */ + + result = g_string_operation_new(op->type, op->first, op->second, op->case_sensitive); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : op = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* final = impose une conversion finale de dernier tour. * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_string_operation_reduce(GStringOperation *op, GScanContext *ctx, bool final) +{ + GScanExpression *result; /* Instance à renvoyer */ + GScanExpression *new; /* Nouvelle expression obtenue */ + const char *strings[2]; /* Chaînes en jeu */ + bool status; /* Bilan intermédiaire */ + char *found; /* Eventuelle portion trouvée */ + size_t len[2]; /* Tailles max. de comparaison */ + int ret; /* Bilan de comparaison */ + const regex_t *preg; /* Expression rationnelle */ + + result = NULL; + + /* Réduction des éléments considérés */ + + new = g_scan_expression_reduce(op->first, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(op->first)); + op->first = new; + } + + new = g_scan_expression_reduce(op->second, ctx, final); + + if (new != NULL) + { + g_object_unref(G_OBJECT(op->second)); + op->second = new; + } + + /* Construction d'une réduction locale ? */ + + if (!G_IS_LITERAL_EXPRESSION(op->first)) + goto exit; + + if (!G_IS_LITERAL_EXPRESSION(op->second)) + goto exit; + + status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->first), &strings[0]); + if (!status) goto exit; + + switch (op->type) + { + case SOT_CONTAINS: + + status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); + if (!status) goto exit; + + if (op->case_sensitive) + found = strstr(strings[0], strings[1]); + else + found = strcasestr(strings[0], strings[1]); + + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL }); + break; + + case SOT_STARTSWITH: + + status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); + if (!status) goto exit; + + len[1] = strlen(strings[1]); + + if (op->case_sensitive) + ret = strncmp(strings[0], strings[1], len[1]); + else + ret = strncasecmp(strings[0], strings[1], len[1]); + + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); + break; + + case SOT_ENDSWITH: + + len[0] = strlen(strings[0]); + + status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); + if (!status) goto exit; + + len[1] = strlen(strings[1]); + + if (len[0] < len[1]) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + + else + { + if (op->case_sensitive) + ret = strncmp(strings[0] + (len[0] - len[1]), strings[1], len[1]); + else + ret = strncasecmp(strings[0] + (len[0] - len[1]), strings[1], len[1]); + + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); + + } + break; + + case SOT_MATCHES: + + status = g_literal_expression_get_regex_value(G_LITERAL_EXPRESSION(op->second), &preg); + if (!status) goto exit; + + ret = regexec(preg, strings[0], 0, NULL, 0); + + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); + break; + + case SOT_IEQUALS: + + len[0] = strlen(strings[0]); + + status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); + if (!status) goto exit; + + len[1] = strlen(strings[1]); + + if (len[0] != len[1]) + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + + else + { + ret = strcasecmp(strings[0], strings[1]); + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); + } + break; + + } + + exit: + + return result; + +} diff --git a/src/analysis/scan/exprs/str.h b/src/analysis/scan/exprs/str.h new file mode 100644 index 0000000..195f941 --- /dev/null +++ b/src/analysis/scan/exprs/str.h @@ -0,0 +1,67 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * str.h - prototypes pour la gestion des opérations booléennes + * + * Copyright (C) 2022 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_STR_H +#define _ANALYSIS_SCAN_EXPRS_STR_H + + +#include "../expr.h" + + + +#define G_TYPE_STRING_OPERATION g_string_operation_get_type() +#define G_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation)) +#define G_IS_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION)) +#define G_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass)) +#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION)) +#define G_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass)) + + +/* Opération booléenne avec un ou deux opérandes (instance) */ +typedef struct _GStringOperation GStringOperation; + +/* Opération booléenne avec un ou deux opérandes (classe) */ +typedef struct _GStringOperationClass GStringOperationClass; + + +/* Types d'opérations booléennes supportées */ +typedef enum _StringOperationType +{ + SOT_CONTAINS, /* Opérateurs "[i]contains" */ + SOT_STARTSWITH, /* Opérateurs "[i]startswith" */ + SOT_ENDSWITH, /* Opérateurs "[i]endswith" */ + SOT_MATCHES, /* Opérateur "matches" */ + SOT_IEQUALS, /* Opérateur "iequals" */ + +} StringOperationType; + + +/* Indique le type défini pour une opération traitant une chaîne de caractères. */ +GType g_string_operation_get_type(void); + +/* Organise un appel de fonction avec ses arguments. */ +GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_STR_H */ |