/* Chrysalide - Outil d'analyse de fichiers binaires * main.c - fichier d'entrée du programme * * Copyright (C) 2009-2017 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 "analysis/binary.h" #include "analysis/loading.h" #include "analysis/contents/file.h" #include "analysis/db/server.h" #include "common/xdg.h" #include "core/core.h" #include "core/global.h" #include "core/logs.h" #include "core/params.h" #include "core/queue.h" #include "glibext/delayed.h" #include "gui/editor.h" #include "gui/core/core.h" #include "gui/core/global.h" #include "plugins/pglist.h" /* Affiche des indications quant à l'utilisation du programme. */ static void show_chrysalide_help(const char *); /* Affiche des indications sur la version courante du programme. */ static void show_chrysalide_version(void); /* Recharge le dernier projet ouvert s'il existe. */ static gboolean load_last_project(GGenConfig *); /* Ouvre les éventuels fichiers fournis au démarrage. */ static int open_binaries(char **, int); /* Sauvegarde le cache des binaires analysés. */ static int save_binary_caches(void); /****************************************************************************** * * * Paramètres : name = nom du programme en question. * * * * Description : Affiche des indications quant à l'utilisation du programme. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void show_chrysalide_help(const char *name) { char *base; /* Version courte du nom */ base = basename(name); printf("\n"); printf("Usage: %s [--help] [--version]\n", base); printf(" %s [args] \n", base); printf("\n"); printf("\t-h --help\t\tShow this help message.\n"); printf("\t-v --version\t\tDisplay the program version.\n"); printf("\n"); printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT); printf("\t-b --batch\t\tExit after processing files.\n"); printf("\t-s --save\t\tSave disassembly cache after analysis in batch mode (ignored in normal mode).\n"); printf("\t-p --project=filename\tOpen an existing project or create a new one.\n"); printf("\n"); } /****************************************************************************** * * * Paramètres : - * * * * Description : Affiche des indications sur la version courante du programme.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void show_chrysalide_version(void) { printf("\n"); printf("-o- Chrysalide r%u -o-\n", REVISION); printf(_("Last compiled on %s at %s\n"), __DATE__, __TIME__); printf("\n"); printf(_("Pictures directory: %s\n"), PIXMAPS_DIR); printf(_("Themes directory: %s\n"), THEMES_DIR); printf(_("Plugins library directory: %s\n"), PLUGINS_LIB_DIR); printf(_("Plugins data directory: %s\n"), PLUGINS_DATA_DIR); printf(_("Locale directory: %s\n"), LOCALE_DIR); printf("\n"); } /****************************************************************************** * * * 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 show_help; /* Affichage de l'aide ? */ bool show_version; /* Affichage de la version ? */ LogMessageType verbosity; /* Niveau de filtre de message */ bool batch_mode; /* Exécution sans GUI ? */ bool save; /* Sauvegarde du cache ? */ char *prj_filename; /* Chemin vers un projet */ int index; /* Indice d'argument */ int ret; /* Bilan d'un appel */ bool status; /* Bilan d'opérations */ GtkWidget *editor; /* Fenêtre graphique */ GDbServer *server; /* Enregistrements locaux */ GGenConfig *config; /* Configuration globale */ char *author; /* Identification à diffuser */ char *pub; /* Chemin de la clef publique */ bool welcome; /* Affichage de la bienvenue ? */ GStudyProject *project; /* Nouveau projet courant */ static struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "verbosity", required_argument, NULL, 'V' }, { "batch", no_argument, NULL, 'b' }, { "save", no_argument, NULL, 's' }, { "project", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; result = EXIT_FAILURE; /** * Initialisation de la bibliothèque et validation des correspondances * d'ABI entre la version du moment de la compilation et celle présente * sur le système courant. */ LIBXML_TEST_VERSION; /* Décodage des options */ show_help = false; show_version = false; verbosity = LMT_INFO; batch_mode = false; save = false; prj_filename = NULL; while (true) { ret = getopt_long(argc, argv, "hvV:bsp:", long_options, &index); if (ret == -1) break; switch (ret) { case 'h': show_help = true; break; case 'v': show_version = true; break; case 'V': verbosity = strtoul(optarg, NULL, 10); break; case 'b': batch_mode = true; break; case 's': save = true; break; case 'p': prj_filename = optarg; break; } } /* Actions de base */ if (show_help) { show_chrysalide_help(argv[0]); result = EXIT_SUCCESS; goto done; } if (show_version) { show_chrysalide_version(); result = EXIT_SUCCESS; goto done; } /* Lancement des choses sérieuses */ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALE_DIR); textdomain(PACKAGE); /* Initialisation de GTK */ g_set_prgname("Chrysalide"); setlocale (LC_ALL, ""); gtk_init(&argc, &argv); /* Initialisation du programme */ if (batch_mode) set_batch_mode(); set_log_verbosity(verbosity); if (!load_all_basic_components()) return EXIT_FAILURE; /* Création de l'interface */ if (!batch_mode) { editor = create_editor(); if (editor == NULL) goto failed_to_load_editor; status = load_all_gui_components(); if (!status) goto failed_to_load_editor; gtk_widget_show_now(editor); } init_all_plugins(true); config = get_main_configuration(); if (!batch_mode) { status = complete_loading_of_all_gui_components(config); if (!status) goto exit_complete_gui; } /* Utilisateur représenté */ if (!g_generic_config_get_value(config, MPK_AUTHOR_NAME, &author)) /*goto glbcl_exit*/; /* Chemin vers la clef privée */ pub = get_xdg_config_dir("chrysalide" G_DIR_SEPARATOR_S "id_rsa.pub"); server = g_db_server_new_internal(author, pub); if (server == NULL) goto no_internal_server; g_db_server_start(server); /* Charge le dernier projet ? */ if (batch_mode) welcome = true; else g_generic_config_get_value(config, MPK_WELCOME_STARTUP, &welcome); if (!welcome && prj_filename == NULL) g_idle_add((GSourceFunc)load_last_project, config); else { if (prj_filename == NULL) project = g_study_project_new(); else { ret = access(prj_filename, R_OK); if (ret == 0) { project = g_study_project_open(prj_filename); if (project == NULL) goto bad_project; } else { project = g_study_project_new(); status = g_study_project_save(project, prj_filename); if (!status) { g_object_unref(G_OBJECT(project)); goto bad_project; } } } set_current_project(project); } /* Exécution du programme */ result = open_binaries(argv + optind, argc - optind); if (batch_mode) { wait_for_all_global_works(); if (save && result == EXIT_SUCCESS) { result = save_binary_caches(); wait_for_all_global_works(); } } else gtk_main(); bad_project: g_db_server_stop(server); g_object_unref(G_OBJECT(server)); no_internal_server: exit_complete_gui: exit_all_plugins(); if (!batch_mode) gtk_widget_destroy(editor); failed_to_load_editor: if (!batch_mode) unload_all_gui_components(); unload_all_basic_components(); done: return result; } /****************************************************************************** * * * Paramètres : cfg = configuration globale sur laquelle s'appuyer. * * * * Description : Recharge le dernier projet ouvert s'il existe. * * * * Retour : G_SOURCE_REMOVE pour ne pas répéter l'action. * * * * Remarques : - * * * ******************************************************************************/ static gboolean load_last_project(GGenConfig *cfg) { const char *filename; /* Chemin du dernier projet */ GStudyProject *project; /* Nouveau projet courant */ if (!g_generic_config_get_value(cfg, MPK_LAST_PROJECT, &filename)) filename = NULL; if (filename == NULL) project = g_study_project_new(); else project = g_study_project_open(filename); set_current_project(project); return G_SOURCE_REMOVE; } /****************************************************************************** * * * Paramètres : files = noms de fichier fournis en ligne de commande. * * count = nombre d'arguments restant à traiter. * * * * Description : Ouvre les éventuels fichiers fournis au démarrage. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static int open_binaries(char **files, int count) { int result; /* Bilan à retourner */ GStudyProject *project; /* Projet courant à compléter */ int i; /* Boucle de parcours */ GBinContent *content; /* Contenu binaire à charger */ result = EXIT_SUCCESS; project = get_current_project(); for (i = 0; i < count && result == EXIT_SUCCESS; i++) { content = g_file_content_new(files[i]); if (content != NULL) { g_study_project_discover_binary_content(project, content); g_object_unref(G_OBJECT(content)); } else result = EXIT_FAILURE; } g_object_unref(G_OBJECT(project)); return result; } /****************************************************************************** * * * Paramètres : - * * * * Description : Sauvegarde le cache des binaires analysés. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static int save_binary_caches(void) { int result; /* Bilan à retourner */ GStudyProject *project; /* Projet courant à compléter */ GLoadedContent **loaded; /* Contenus chargés et analysés*/ size_t count; /* Quantité de ces contenus */ size_t i; /* Boucle de parcours */ bool status; /* Bilan de lancement */ result = EXIT_SUCCESS; project = get_current_project(); loaded = g_study_project_get_contents(project, &count); for (i = 0; i < count; i++) { if (G_IS_LOADED_BINARY(loaded[i])) { status = g_loaded_binary_save_cache(G_LOADED_BINARY(loaded[i])); if (!status) result = EXIT_FAILURE; } g_object_unref(G_OBJECT(loaded[i])); } if (loaded != NULL) free(loaded); g_object_unref(G_OBJECT(project)); return result; }