/* Chrysalide - Outil d'analyse de fichiers binaires * pychrysa.c - plugin permettant des extensions en Python * * Copyright (C) 2009-2014 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "pychrysa.h" #if 0 #include #include #include //#include #include #include "quirks.h" #include "analysis/module.h" #include "arch/module.h" #include "debug/module.h" #include "format/module.h" #include "glibext/module.h" #include "gtkext/module.h" #include "gui/module.h" /* #include "analysis/py_binary.h" #include "analysis/py_line.h" #include "analysis/py_line_code.h" #include "analysis/roptions.h" */ #include "../../src/common/environment.h" #include "../../src/common/extstr.h" #include "../../src/plugins/plugin-int.h" static PyMethodDef SpamMethods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; /****************************************************************************** * * * Paramètres : - * * * * Description : Précise le nom associé au greffon. * * * * Retour : Nom à libérer de la mémoire. * * * * Remarques : - * * * ******************************************************************************/ char *get_plugin_name(void) { return strdup("PyChrysalide"); } /****************************************************************************** * * * Paramètres : plugin = instance représentant le greffon en chargement. * * ref = espace de référencement global. * * * * Description : Initialise le greffon permettant l'usage de Python. * * * * Retour : true. * * * * Remarques : - * * * ******************************************************************************/ bool init_plugin(GPluginModule *plugin, GObject *ref) { char *paths; /* Emplacements de greffons */ char *path; /* Chemin à fouiller */ char *save; /* Sauvegarde pour ré-entrance */ DIR *dir; /* Répertoire à parcourir */ struct dirent entry; /* Elément trouvé */ struct dirent *next; /* Prochain élément fourni */ int ret; /* Bilan d'un appel système */ char *filename; /* Chemin d'accès reconstruit */ GPluginModule *pyplugin; /* Définition des zones d'influence */ add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";"); paths = get_env_var("PYTHONPATH"); /* Intialisations Python */ //return false; define_internal_ref(ref); Py_Initialize(); //pychrysalide_set_gc_threshold(INT_MAX, INT_MAX, INT_MAX); //pychrysalide_set_gc_threshold(1, 1, 1); initpychrysa(); /* Chargement des greffons */ save = NULL; /* gcc... */ for (path = strtok_r(paths, ";", &save); path != NULL; path = strtok_r(NULL, ";", &save)) { dir = opendir(path); if (dir == NULL) { perror("opendir"); continue; } for (ret = readdir_r(dir, &entry, &next); ret == 0 && next != NULL; ret = readdir_r(dir, &entry, &next)) { if (entry.d_name[0] == '.') continue; //if (strcmp(entry.d_name, "test") != 0) continue; printf("NAME :: '%s'\n", entry.d_name); if (strcmp(entry.d_name, "apkfiles") != 0) continue; filename = strdup(entry.d_name); filename = stradd(filename, "."); filename = stradd(filename, "__init__"); pyplugin = g_python_plugin_new(entry.d_name, filename); if (pyplugin == NULL) g_plugin_module_log_variadic_message(plugin, LMT_ERROR, _("No suitable Python plugin found in '%s'"), filename); else { g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, _("Loaded Python plugin '%s' from the '%s' directory"), g_plugin_module_get_name(G_PLUGIN_MODULE(pyplugin)), path); add_plugin_to_main_list(pyplugin); } free(filename); } closedir(dir); } return true; } /****************************************************************************** * * * Paramètres : plugin = instance représentant le greffon en déchargement. * * * * Description : Libère le greffon permettant l'usage de Python. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void exit_plugin(GPluginModule *plugin) { /* FIXME */ //Py_Finalize(); } /****************************************************************************** * * * Paramètres : plugin = greffon à consulter. * * * * Description : Indique les opérations offertes par un greffon donné. * * * * Retour : Action(s) offerte(s) par le greffon. * * * * Remarques : - * * * ******************************************************************************/ PluginAction get_plugin_action(const GPluginModule *plugin) { PluginAction result; /* Combinaison à retourner */ result = PGA_NONE; return result; } #if PY_VERSION_HEX >= 0x03000000 /****************************************************************************** * * * Paramètres : - * * * * Description : Point d'entrée pour l'initialisation de Python. * * * * Retour : ? * * * * Remarques : - * * * ******************************************************************************/ PyMODINIT_FUNC initpychrysa/*PyInit_pychrysa*/(void) { PyObject *module; //init_pygobject(); //init_pygtk(); pychrysalide_init_quirks(); module = Py_InitModule("pychrysalide", SpamMethods); //add_analysis_roptions_to_python_module(module); add_analysis_module_to_python_module(module); add_arch_module_to_python_module(module); add_debug_module_to_python_module(module); add_format_module_to_python_module(module); add_glibext_module_to_python_module(module); add_gtkext_module_to_python_module(module); add_gui_module_to_python_module(module); add_plugin_to_python_module(module); /* static struct PyModuleDef spammodule = { PyModuleDef_HEAD_INIT, "pychrysalide", "pychrysalide_doc", -1, SpamMethods }; PyModule_Create(&spammodule); */ } #else /****************************************************************************** * * * Paramètres : - * * * * Description : Point d'entrée pour l'initialisation de Python. * * * * Retour : ? * * * * Remarques : - * * * ******************************************************************************/ PyMODINIT_FUNC initpychrysa(void) { PyObject *module; init_pygobject(); //init_pygtk(); pychrysalide_init_quirks(); module = Py_InitModule("pychrysalide", SpamMethods); //add_analysis_roptions_to_python_module(module); add_analysis_module_to_python_module(module); add_arch_module_to_python_module(module); add_debug_module_to_python_module(module); add_format_module_to_python_module(module); add_glibext_module_to_python_module(module); add_gtkext_module_to_python_module(module); add_gui_module_to_python_module(module); add_plugin_to_python_module(module); } #endif #endif #include #include #include "analysis/module.h" #include "arch/module.h" #include "core/module.h" #include "glibext/module.h" // TODO : à bouger ? #include "../../src/arch/processor.h" #include "../../src/format/format.h" /////////////////////////// #include #include #include #include #include #include #include #include "../../revision.h" DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0", PGA_ALL); /* Fournit la version du programme global. */ static PyObject *py_chrysalide_version(PyObject *, PyObject *); /* Fournit la version du greffon pour Python. */ static PyObject *py_chrysalide_mod_version(PyObject *, PyObject *); /* Détermine si l'interpréteur lancé est celui pris en compte. */ static bool is_current_abi_suitable(void); /****************************************************************************** * * * Paramètres : self = NULL car méthode statique. * * args = non utilisé ici. * * * * Description : Fournit la version du programme global. * * * * Retour : Numéro de révision. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_chrysalide_version(PyObject *self, PyObject *args) { char version[16]; int major; int minor; int revision; major = REVISION / 1000; minor = (REVISION - (major * 1000)) / 100; revision = REVISION % 100; snprintf(version, sizeof(version), "%d.%d.%d", major, minor, revision); return PyUnicode_FromString(version); } /****************************************************************************** * * * Paramètres : self = NULL car méthode statique. * * args = non utilisé ici. * * * * Description : Fournit la version du greffon pour Python. * * * * Retour : Numéro de révision. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_chrysalide_mod_version(PyObject *self, PyObject *args) { char version[16]; snprintf(version, sizeof(version), "%s", _chrysalide_plugin.version); return PyUnicode_FromString(version); } /****************************************************************************** * * * Paramètres : - * * * * Description : Détermine si l'interpréteur lancé est celui pris en compte. * * * * Retour : true si l'exécution peut se poursuivre, false sinon. * * * * Remarques : - * * * ******************************************************************************/ static bool is_current_abi_suitable(void) { bool result; int fds[2]; int ret; char cmds[128]; char content[64]; ssize_t got; #define GRAB_ABI_FLAGS_IN_PYTHON \ "import sys" "\n" \ "import os" "\n" \ "os.write(%d, bytes(sys.abiflags, 'UTF-8'))" "\n" result = false; ret = pipe(fds); if (ret == -1) { perror("pipe()"); return false; } snprintf(cmds, sizeof(cmds), GRAB_ABI_FLAGS_IN_PYTHON, fds[1]); ret = PyRun_SimpleString(cmds); if (ret != 0) goto icas_exit; got = read(fds[0], content, sizeof(content)); if (got < 0) { perror("read()"); goto icas_exit; } content[got] = '\0'; result = (strcmp(content, LIBPYTHON_ABI_FLAGS) == 0); icas_exit: if (!result) PyErr_SetString(PyExc_SystemError, "the ABI flags of the current interpreter do not match " \ "the ones of the Python library used during the module compilation."); return result; } /****************************************************************************** * * * Paramètres : - * * * * Description : Point d'entrée pour l'initialisation de Python. * * * * Retour : ? * * * * Remarques : - * * * ******************************************************************************/ PyMODINIT_FUNC PyInit_pychrysalide(void) { PyObject *result; /* Module Python à retourner */ PyObject *pygobj_mod; /* Module Python-GObject */ bool status; /* Bilan des inclusions */ static PyMethodDef py_chrysalide_methods[] = { { "version", py_chrysalide_version, METH_NOARGS, "Provide the revision number of Chrysalide." }, { "mod_version", py_chrysalide_mod_version, METH_NOARGS, "Provide the revision number of Chrysalide module for Python." }, { NULL } }; static PyModuleDef py_chrysalide_module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "pychrysalide", .m_doc = "Python module for Chrysalide", .m_size = -1, .m_methods = py_chrysalide_methods }; // TODO : à bouger ! //init_all_processors(); //init_all_formats(); if (!is_current_abi_suitable()) return NULL; if (pygobject_init(-1, -1, -1) == NULL) { PyErr_SetString(PyExc_SystemError, "unable to init GObject in Python."); return NULL; } if (!load_all_basic_components()) { PyErr_SetString(PyExc_SystemError, "unable to load all basic components."); return NULL; } /** * Pour une raison non identifiée, si le module n'est pas préchargé, * le flot d'exécution plante dans la fonction insertdict() de Objects/dictobject.c:818. */ pygobj_mod = PyImport_ImportModule("gi.repository.GObject"); if (pygobj_mod == NULL) return NULL; result = PyModule_Create(&py_chrysalide_module); status = true; status &= add_analysis_module_to_python_module(result); status &= add_arch_module_to_python_module(result); status &= add_core_module_to_python_module(result); status &= add_glibext_module_to_python_module(result); if (!status) { PyErr_SetString(PyExc_SystemError, "fail to load all PyChrysalide components."); return NULL; } return result; }