/* Chrysalide - Outil d'analyse de fichiers binaires * fast-rost.c - fichier d'entrée du centre de collecte, adapté pour un fuzzing optimal * * 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __AFL_FUZZ_TESTCASE_LEN ssize_t fuzz_len; unsigned char fuzz_buf[1024000]; # define __AFL_FUZZ_TESTCASE_LEN fuzz_len # define __AFL_FUZZ_TESTCASE_BUF fuzz_buf # define __AFL_FUZZ_INIT() void sync(void); # define __AFL_LOOP(x) \ ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0) # define __AFL_INIT() sync() #endif __AFL_FUZZ_INIT(); /****************************************************************************** * * * 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 de l'exécution */ bool check_only; /* Validation uniquement */ LogMessageType verbosity; /* Niveau de filtre de message */ GScanOptions *options; /* Options d'analyses */ int index; /* Indice d'argument */ int ret; /* Bilan d'un appel */ char *edir; /* Répertoire de base effectif */ char *target; /* Cible communiquée */ unsigned char *afl_buf; /* Tampon de travail d'AFL */ int afl_len; /* Taille de ce tampon */ GContentScanner *scanner; /* Encadrement d'une recherche */ GBinContent *content; /* Contenu à analyser */ GScanContext *context; /* Contexte des trouvailles */ sized_string_t padding; /* Bourrage pour le JSON */ bool full; /* Détailler l'affichage ? */ static struct option long_options[] = { { "algorithm", required_argument, NULL, 'A' }, { "check-only", no_argument, NULL, 'C' }, { "print-json", no_argument, NULL, 'j' }, { "print-strings", no_argument, NULL, 's' }, { "print-stats", no_argument, NULL, 'S' }, { "print-tags", no_argument, NULL, 'g' }, { "tag", required_argument, NULL, 't' }, { "verbosity", required_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; result = EXIT_FAILURE; /* Décodage des options */ check_only = false; verbosity = LMT_COUNT; options = g_scan_options_new(); g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND); while (true) { ret = getopt_long(argc, argv, "A:CjsSgt:V:", long_options, &index); if (ret == -1) break; switch (ret) { case 'A': if (strcmp(optarg, "bitmap") == 0) g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND); else if (strcmp(optarg, "acism") == 0) g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND); else g_scan_options_set_backend_for_data(options, G_TYPE_INVALID); break; case 'C': check_only = true; g_scan_options_set_check_only(options, true); break; case 'j': g_scan_options_set_print_json(options, true); break; case 's': g_scan_options_set_print_strings(options, true); break; case 'S': g_scan_options_set_print_stats(options, true); break; case 'g': g_scan_options_set_print_tags(options, true); break; case 't': g_scan_options_select_tag(options, optarg); break; case 'V': verbosity = strtoul(optarg, NULL, 10); break; } } if ((check_only && (optind + 0) != argc && (optind + 1) != argc) || (!check_only && (optind + 1) != argc && (optind + 2) != argc)) { goto done; } /* Actions de base */ if (g_scan_options_get_backend_for_data(options) == G_TYPE_INVALID) { goto done; } /* Lancement des choses sérieuses */ setlocale(LC_ALL, ""); edir = get_effective_directory(LOCALE_DIR); bindtextdomain(PACKAGE, edir); free(edir); textdomain(PACKAGE); /* Initialisation de GTK */ g_set_prgname("ROST"); //gtk_init(&argc, &argv); /* Initialisation du programme */ set_batch_mode(); set_log_verbosity(verbosity); if (!load_all_core_components(true)) goto done; init_all_plugins(true); /* Traitement des recherches */ if ((optind + 1) == argc) target = argv[optind]; else goto done; __AFL_INIT(); afl_buf = __AFL_FUZZ_TESTCASE_BUF; while (__AFL_LOOP(10000)) { afl_len = __AFL_FUZZ_TESTCASE_LEN; scanner = g_content_scanner_new_from_text((char *)afl_buf, afl_len); #if 0 do { FILE *stream; stream = fopen("/dev/shm/ctrl.log", "a"); fprintf(stream, "running %d bytes => %p\n", afl_len, scanner); fclose(stream); } while (0); #endif if (scanner != NULL) result = EXIT_SUCCESS; if (scanner != NULL && !check_only) { content = g_file_content_new(target); if (content == NULL) goto bad_file_content; context = g_content_scanner_analyze(scanner, options, content); if (g_scan_options_get_print_json(options)) { padding.data = " "; padding.len = 3; g_content_scanner_output_to_json(scanner, context, &padding, 0, STDOUT_FILENO); } else { full = g_scan_options_get_print_strings(options); g_content_scanner_output_to_text(scanner, context, full, STDOUT_FILENO); } g_object_unref(G_OBJECT(context)); g_object_unref(G_OBJECT(content)); bad_file_content: g_object_unref(G_OBJECT(scanner)); } } g_object_unref(G_OBJECT(options)); /* Sortie */ unload_all_core_components(false); done: return result; }