/* Chrysalide - Outil d'analyse de fichiers binaires
* yara2rost.c - traduction de règles YARA en règles ROST
*
* Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Chrysalide is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chrysalide. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "decl.h"
/* Affiche des indications sur l'utilisation du programme. */
static void show_usage(const char *);
/* Récupère un contenu à traiter depuis l'entrée standard. */
static void *get_input_data_from_stdin(size_t *);
/* Récupère un contenu à traiter depuis un fichier externe. */
static void *get_input_data_from_file(const char *, size_t *);
/******************************************************************************
* *
* Paramètres : argv0 = nombre du programme exécuté. *
* *
* Description : Affiche des indications sur l'utilisation du programme. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void show_usage(const char *argv0)
{
printf("\n");
printf("Usage: %s [options] []\n", argv0);
printf("\n");
printf("General options:\n");
printf("\n");
printf("\t-h | --help\t\tDisplay this messsage.\n");
printf("\n");
printf("If no YARA file is provided as argument, a rule definition is expected from the standard input.\n");
printf("\n");
}
/******************************************************************************
* *
* Paramètres : length = taille de l'espace mémoire mis en place. [OUT] *
* *
* Description : Récupère un contenu à traiter depuis l'entrée standard. *
* *
* Retour : Adresse valide ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static void *get_input_data_from_stdin(size_t *length)
{
char *result; /* Espace mémoire à retourner */
ssize_t got; /* Quantité d'octets lus */
result = NULL;
*length = 0;
#define ALLOC_SIZE 2048
while (true)
{
result = realloc(result, (*length + ALLOC_SIZE) * sizeof(char));
got = read(STDIN_FILENO, result + *length, ALLOC_SIZE);
if (got == -1)
{
perror("read");
goto exit_with_error;
}
*length += got;
if (got < ALLOC_SIZE)
break;
}
return result;
exit_with_error:
free(result);
*length = 0;
return NULL;
}
/******************************************************************************
* *
* Paramètres : filename = chemin du fichier à charger en mémoire. *
* length = taille de l'espace mémoire mis en place. [OUT] *
* *
* Description : Récupère un contenu à traiter depuis un fichier externe. *
* *
* Retour : Adresse valide ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static void *get_input_data_from_file(const char *filename, size_t *length)
{
char *result; /* Espace mémoire à retourner */
int fd; /* Descripteur du fichier */
struct stat info; /* Informations sur le fichier */
int ret; /* Bilan d'un appel */
ssize_t got; /* Quantité d'octets lus */
result = NULL;
fd = open(filename, O_RDONLY);
if (fd == -1)
{
perror("open");
goto exit;
}
ret = fstat(fd, &info);
if (ret == -1)
{
perror("fstat");
goto exit_with_fd;
}
*length = info.st_size;
result = malloc(*length * sizeof(char));
got = read(fd, result, *length);
if (got == -1 || got != *length)
{
perror("read");
free(result);
result = NULL;
*length = 0;
}
exit_with_fd:
close(fd);
exit:
return result;
}
/******************************************************************************
* *
* Paramètres : argc = nombre d'arguments dans la ligne de commande. *
* argv = arguments de la ligne de commande. *
* *
* Description : Point d'entrée du programme. *
* *
* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. *
* *
* Remarques : - *
* *
******************************************************************************/
int main(int argc, char **argv)
{
int result; /* Bilan à retourner */
bool need_help; /* Affichage de l'aide ? */
int index; /* Indice d'argument à traiter */
int ret; /* Bilan d'une lecture d'arg. */
const char *source; /* Source de définitions */
void *content; /* Contenu à traduire */
size_t length; /* Taille de ce contenu */
static struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
/* Récupération des commandes */
need_help = false;
while (true)
{
ret = getopt_long(argc, argv, "h", long_options, &index);
if (ret == -1) break;
switch (ret)
{
case 'h':
need_help = true;
break;
}
}
/* Vérifications supplémentaires */
if (need_help || (optind != argc && (optind + 1) != argc))
{
show_usage(argv[0]);
result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE);
goto exit;
}
/* Execution attendue */
result = EXIT_FAILURE;
if (optind == argc)
content = get_input_data_from_stdin(&length);
else
{
source = argv[optind];
if (strcmp(source, "-") == 0 || strcmp(source, "/dev/stdin") == 0)
content = get_input_data_from_stdin(&length);
else
content = get_input_data_from_file(source, &length);
}
if (content != NULL)
{
if (process_rules_definitions(content, length))
result = EXIT_SUCCESS;
free(content);
}
exit:
return result;
}