From 0c92911504f7d267c913fc8d2069cb87139b390b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 28 Jul 2016 23:55:02 +0200 Subject: Centralized the checksum computing of binary contents. --- ChangeLog | 26 ++++++++++++++ plugins/pychrysa/analysis/content.c | 7 ++-- src/analysis/binary.c | 8 ++--- src/analysis/content-int.h | 6 ++-- src/analysis/content.c | 29 ++++++++++++++-- src/analysis/content.h | 2 +- src/analysis/contents/file.c | 35 +++++-------------- src/analysis/contents/restricted.c | 42 +++++++++++++++++++++++ src/analysis/disass/disassembler.c | 2 +- src/analysis/project.c | 2 +- tests/analysis/contents/checksum.py | 67 +++++++++++++++++++++++++++++++++++++ 11 files changed, 181 insertions(+), 45 deletions(-) create mode 100644 tests/analysis/contents/checksum.py diff --git a/ChangeLog b/ChangeLog index 25f0b0e..0ccf59b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +16-07-28 Cyrille Bagard + + * plugins/pychrysa/analysis/content.c: + Update code. + + * src/analysis/binary.c: + Typo. + + * src/analysis/content-int.h: + * src/analysis/content.c: + Centralize the checksum computing of binary contents. + + * src/analysis/content.h: + Typo. + + * src/analysis/contents/file.c: + * src/analysis/contents/restricted.c: + Centralize the checksum computing of binary contents. + + * src/analysis/disass/disassembler.c: + * src/analysis/project.c: + Typo. + + * tests/analysis/contents/checksum.py: + New entry: verify checksums in the test suite. + 16-07-23 Cyrille Bagard * plugins/pychrysa/analysis/routine.c: diff --git a/plugins/pychrysa/analysis/content.c b/plugins/pychrysa/analysis/content.c index 00265e3..d3da2b1 100644 --- a/plugins/pychrysa/analysis/content.c +++ b/plugins/pychrysa/analysis/content.c @@ -82,12 +82,9 @@ static PyObject *py_binary_content_get_checksum(PyObject *self, PyObject *args) content = G_BIN_CONTENT(pygobject_get(self)); - //checksum = g_binary_content_get_cheksum(content); + checksum = g_binary_content_get_checksum(content); - printf("YEAH\n"); - fflush(NULL); - - result = PyUnicode_FromString("checksum"); + result = PyUnicode_FromString(checksum); return result; diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 20410f2..75c6e14 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -525,7 +525,7 @@ bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathC access = stradd(access, "/Main"); content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); - hash = g_binary_content_get_cheksum(content); + hash = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); result = add_content_to_node(xdoc, context, access, hash); @@ -541,7 +541,7 @@ bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathC debug = g_exe_format_get_debug_info(binary->format, i); content = g_binary_format_get_content(G_BIN_FORMAT(debug)); - hash = g_binary_content_get_cheksum(content); + hash = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); g_object_unref(G_OBJECT(debug)); @@ -1038,7 +1038,7 @@ static bool g_loaded_binary_connect_internal(GLoadedBinary *binary) /* Détermination de l'identifiant */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); - checksum = g_binary_content_get_cheksum(content); + checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); /* Tentative de connexion */ @@ -1114,7 +1114,7 @@ static bool g_loaded_binary_connect_remote(GLoadedBinary *binary) /* Détermination de l'identifiant */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); - checksum = g_binary_content_get_cheksum(content); + checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); /* Tentative de connexion */ diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h index d9f9ef9..24cea81 100644 --- a/src/analysis/content-int.h +++ b/src/analysis/content-int.h @@ -35,8 +35,8 @@ typedef const char * (* describe_content_fc) (const GBinContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); -/* Fournit une empreinte unique (SHA256) pour les données. */ -typedef const gchar * (* get_checksum_fc) (GBinContent *); +/* Calcule une empreinte unique (SHA256) pour les données. */ +typedef void (* compute_checksum_fc) (GBinContent *, GChecksum *); /* Détermine le nombre d'octets lisibles. */ typedef phys_t (* compute_size_fc) (const GBinContent *); @@ -78,7 +78,7 @@ struct _GBinContentIface save_content_fc save; /* Sauvegarde du contenu */ - get_checksum_fc get_checksum; /* Calcul de l'empreinte */ + compute_checksum_fc compute_checksum; /* Calcul de l'empreinte */ compute_size_fc compute_size; /* Calcul de la taille totale */ diff --git a/src/analysis/content.c b/src/analysis/content.c index 01c9c99..4b4645f 100644 --- a/src/analysis/content.c +++ b/src/analysis/content.c @@ -24,9 +24,13 @@ #include "content.h" +#include #include +#include + + #include "content-int.h" #include "contents/file.h" @@ -155,13 +159,32 @@ bool g_binary_content_save(const GBinContent *content, xmlDocPtr xdoc, xmlXPathC * * ******************************************************************************/ -const gchar *g_binary_content_get_cheksum(GBinContent *content) +const gchar *g_binary_content_get_checksum(GBinContent *content) { + const gchar *result; /* Empreinte à retourner */ + GChecksum *checksum; /* Calcul de l'empreinte */ GBinContentIface *iface; /* Interface utilisée */ - iface = G_BIN_CONTENT_GET_IFACE(content); + checksum = g_object_get_data(G_OBJECT(content), "checksum"); + + if (checksum == NULL) + { + checksum = g_checksum_new(G_CHECKSUM_SHA256); + assert(checksum != NULL); + + g_checksum_reset(checksum); + + iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->get_checksum(content); + iface->compute_checksum(content, checksum); + + g_object_set_data_full(G_OBJECT(content), "checksum", checksum, (GDestroyNotify)g_checksum_free); + + } + + result = g_checksum_get_string(checksum); + + return result; } diff --git a/src/analysis/content.h b/src/analysis/content.h index 1a61cb7..f1e5bbf 100644 --- a/src/analysis/content.h +++ b/src/analysis/content.h @@ -64,7 +64,7 @@ const char *g_binary_content_describe(const GBinContent *, bool); bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); /* Fournit une empreinte unique (SHA256) pour les données. */ -const gchar *g_binary_content_get_cheksum(GBinContent *); +const gchar *g_binary_content_get_checksum(GBinContent *); /* Détermine le nombre d'octets lisibles. */ phys_t g_binary_content_compute_size(const GBinContent *); diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c index 8416348..95cfd5d 100644 --- a/src/analysis/contents/file.c +++ b/src/analysis/contents/file.c @@ -24,7 +24,6 @@ #include "file.h" -#include #include #include #include @@ -49,9 +48,6 @@ struct _GFileContent bin_t *data; /* Contenu binaire représenté */ mrange_t range; /* Couverture du binaire */ - GChecksum *checksum; /* Calcul de l'empreinte */ - bool cs_computed; /* Calcul effectué ? */ - }; /* Contenu de données binaires issues d'un fichier (classe) */ @@ -84,7 +80,7 @@ static const char *g_file_content_describe(const GFileContent *, bool); static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); /* Fournit une empreinte unique (SHA256) pour les données. */ -static const gchar *g_file_content_get_checksum(GFileContent *); +static void g_file_content_compute_checksum(GFileContent *, GChecksum *); /* Détermine le nombre d'octets lisibles. */ static phys_t g_file_content_compute_size(const GFileContent *); @@ -161,10 +157,6 @@ static void g_file_content_class_init(GFileContentClass *klass) static void g_file_content_init(GFileContent *content) { - content->checksum = g_checksum_new(G_CHECKSUM_SHA256); - assert(content->checksum != NULL); - - content->cs_computed = false; } @@ -187,7 +179,7 @@ static void g_file_content_interface_init(GBinContentInterface *iface) iface->save = (save_content_fc)g_file_content_save; - iface->get_checksum = (get_checksum_fc)g_file_content_get_checksum; + iface->compute_checksum = (compute_checksum_fc)g_file_content_compute_checksum; iface->compute_size = (compute_size_fc)g_file_content_compute_size; @@ -220,8 +212,6 @@ static void g_file_content_interface_init(GBinContentInterface *iface) static void g_file_content_dispose(GFileContent *content) { - g_checksum_free(content->checksum); - G_OBJECT_CLASS(g_file_content_parent_class)->dispose(G_OBJECT(content)); } @@ -444,29 +434,20 @@ static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xml /****************************************************************************** * * -* Paramètres : content = contenu binaire à venir lire. * +* Paramètres : content = contenu binaire à venir lire. * +* checksum = empreinte de zone mémoire à compléter. * * * -* Description : Fournit une empreinte unique (SHA256) pour les données. * +* Description : Calcule une empreinte unique (SHA256) pour les données. * * * -* Retour : Chaîne représentant l'empreinte du contenu binaire. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static const gchar *g_file_content_get_checksum(GFileContent *content) +static void g_file_content_compute_checksum(GFileContent *content, GChecksum *checksum) { - if (!content->cs_computed) - { - g_checksum_reset(content->checksum); - - g_checksum_update(content->checksum, content->data, get_mrange_length(&content->range)); - - content->cs_computed = true; - - } - - return g_checksum_get_string(content->checksum); + g_checksum_update(checksum, content->data, get_mrange_length(&content->range)); } diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c index a8f1763..e342242 100644 --- a/src/analysis/contents/restricted.c +++ b/src/analysis/contents/restricted.c @@ -66,6 +66,9 @@ static void g_restricted_content_dispose(GRestrictedContent *); /* Procède à la libération totale de la mémoire. */ static void g_restricted_content_finalize(GRestrictedContent *); +/* Calcule une empreinte unique (SHA256) pour les données. */ +static void g_restricted_content_compute_checksum(GRestrictedContent *, GChecksum *); + /* Donne accès à une portion des données représentées. */ static const bin_t *g_restricted_content_get_raw_access(const GRestrictedContent *, vmpa2t *, phys_t); @@ -156,6 +159,8 @@ static void g_restricted_content_init(GRestrictedContent *content) static void g_restricted_content_interface_init(GBinContentInterface *iface) { + iface->compute_checksum = (compute_checksum_fc)g_restricted_content_compute_checksum; + iface->get_raw_access = (get_raw_access_fc)g_restricted_content_get_raw_access; iface->read_raw = (read_raw_fc)g_restricted_content_read_raw; @@ -242,6 +247,43 @@ GBinContent *g_restricted_content_new(GBinContent *content, const mrange_t *rang /****************************************************************************** * * +* Paramètres : content = contenu binaire à venir lire. * +* checksum = empreinte de zone mémoire à compléter. * +* * +* Description : Calcule une empreinte unique (SHA256) pour les données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_restricted_content_compute_checksum(GRestrictedContent *content, GChecksum *checksum) +{ + vmpa2t start; /* Point de départ */ + phys_t i; /* Boucle de parcours */ + vmpa2t iter; /* Tête de lecture */ + const bin_t *byte; /* Octet de données à intégrer */ + + copy_vmpa(&start, get_mrange_addr(&content->range)); + + for (i = 0; i < get_mrange_length(&content->range); i++) + { + copy_vmpa(&iter, &start); + advance_vmpa(&iter, i); + + byte = g_binary_content_get_raw_access(G_BIN_CONTENT(content->internal), &iter, 1); + + if (byte != NULL) + g_checksum_update(checksum, byte, 1); + + } + +} + + +/****************************************************************************** +* * * Paramètres : content = contenu binaire à venir lire. * * addr = position de la tête de lecture. * * length = quantité d'octets à lire. * diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 1499064..7c16dd1 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -691,7 +691,7 @@ void disassemble_binary(GLoadedBinary *binary, GArchInstruction **instrs, GCodeB format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); content = g_binary_format_get_content(format); - checksum = g_binary_content_get_cheksum(content); + checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); build_disass_prologue(*buffer, g_binary_content_describe(content, true), checksum); diff --git a/src/analysis/project.c b/src/analysis/project.c index 1a73e74..bf78a49 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -528,7 +528,7 @@ GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, for (i = 0; i < project->contents_count && result == NULL; i++) { iter = project->contents[i].content; - other = g_binary_content_get_cheksum(iter); + other = g_binary_content_get_checksum(iter); if (strcmp(hash, other) == 0) { diff --git a/tests/analysis/contents/checksum.py b/tests/analysis/contents/checksum.py new file mode 100644 index 0000000..ba09a3f --- /dev/null +++ b/tests/analysis/contents/checksum.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + + +# Tests validant le bon calcul d'empreintes. + + +from chrysacase import ChrysalideTestCase +from pychrysalide.analysis.contents import FileContent, RestrictedContent +from pychrysalide.arch import vmpa, mrange +import hashlib +import tempfile + + +class TestRestrictedContent(ChrysalideTestCase): + """TestCase for analysis.contents.RestrictedContent.""" + + @classmethod + def setUpClass(cls): + + super(TestRestrictedContent, cls).setUpClass() + + cls._out = tempfile.NamedTemporaryFile() + + cls._out.write(b'AAAABBBBCCCCDDDD') + + cls._out.flush() + + cls.log('Using temporary file "%s"' % cls._out.name) + + + @classmethod + def tearDownClass(cls): + + super(TestRestrictedContent, cls).tearDownClass() + + cls.log('Delete file "%s"' % cls._out.name) + + cls._out.close() + + + def testFullChecksum(self): + """Check checksum of full content.""" + + fcnt = FileContent(self._out.name) + self.assertIsNotNone(fcnt) + + expected = hashlib.sha256(b'AAAABBBBCCCCDDDD').hexdigest() + + self.assertEqual(fcnt.get_checksum(), expected) + + + def testPartialChecksum(self): + """Check checksum of restricted content.""" + + fcnt = FileContent(self._out.name) + self.assertIsNotNone(fcnt) + + start = vmpa(4, vmpa.VMPA_NO_VIRTUAL) + covered = mrange(start, 4) # 'BBBB' + + rcnt = RestrictedContent(fcnt, covered) + self.assertIsNotNone(rcnt) + + expected = hashlib.sha256(b'BBBB').hexdigest() + + self.assertEqual(rcnt.get_checksum(), expected) -- cgit v0.11.2-87-g4458