From 2b3d86868d130ac82b403575d0b5521176e77827 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 12 Oct 2021 08:51:18 +0200 Subject: Update code for restricted contents. --- src/analysis/contents/restricted.c | 256 ++++++++++++++++++++++++++-------- tests/analysis/contents/restricted.py | 83 ++++++----- 2 files changed, 247 insertions(+), 92 deletions(-) diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c index 3e9cbbb..55bc83f 100644 --- a/src/analysis/contents/restricted.c +++ b/src/analysis/contents/restricted.c @@ -31,9 +31,14 @@ #include "../content-int.h" #include "../db/misc/rlestr.h" #include "../storage/serialize-int.h" +#include "../../common/extstr.h" +#include "../../core/logs.h" +/* -------------------------- ENSEMBLE DE DONNEES BINAIRES -------------------------- */ + + /* Contenu de données binaires issues d'un contenu restreint (instance) */ struct _GRestrictedContent { @@ -59,27 +64,35 @@ static void g_restricted_content_class_init(GRestrictedContentClass *); /* Initialise une instance de contenu de données binaires. */ static void g_restricted_content_init(GRestrictedContent *); -/* Procède à l'initialisation de l'interface de sérialisation. */ -static void g_restricted_content_serializable_init(GSerializableObjectInterface *); - /* Procède à l'initialisation de l'interface de lecture. */ static void g_restricted_content_interface_init(GBinContentInterface *); +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_restricted_content_serializable_init(GSerializableObjectInterface *); + /* Supprime toutes les références externes. */ static void g_restricted_content_dispose(GRestrictedContent *); /* Procède à la libération totale de la mémoire. */ static void g_restricted_content_finalize(GRestrictedContent *); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_restricted_content_load(GRestrictedContent *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_restricted_content_store(const GRestrictedContent *, GObjectStorage *, packed_buffer_t *); + +/* ---------------------- INTERACTIONS AVEC UN CONTENU BINAIRE ---------------------- */ + + +/* Associe un ensemble d'attributs au contenu binaire. */ +static void g_restricted_content_set_attributes(GRestrictedContent *, GContentAttributes *); + +/* Fournit l'ensemble des attributs associés à un contenu. */ +static GContentAttributes *g_restricted_content_get_attributes(const GRestrictedContent *); /* Donne l'origine d'un contenu binaire. */ static GBinContent *g_restricted_content_get_root(GRestrictedContent *); +/* Fournit le nom associé au contenu binaire. */ +static char *g_restricted_content_describe(const GRestrictedContent *, bool); + /* Calcule une empreinte unique (SHA256) pour les données. */ static void g_restricted_content_compute_checksum(GRestrictedContent *, GChecksum *); @@ -124,10 +137,26 @@ static bool g_restricted_content_read_leb128(const GRestrictedContent *, vmpa2t +/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ + + +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_restricted_content_load(GRestrictedContent *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool g_restricted_content_store(const GRestrictedContent *, GObjectStorage *, packed_buffer_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* ENSEMBLE DE DONNEES BINAIRES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini par la GLib pour les contenus de données. */ G_DEFINE_TYPE_WITH_CODE(GRestrictedContent, g_restricted_content, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_restricted_content_serializable_init) - G_IMPLEMENT_INTERFACE(G_TYPE_BIN_CONTENT, g_restricted_content_interface_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_BIN_CONTENT, g_restricted_content_interface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_restricted_content_serializable_init)); /****************************************************************************** @@ -182,26 +211,6 @@ static void g_restricted_content_init(GRestrictedContent *content) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de sérialisation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_restricted_content_serializable_init(GSerializableObjectInterface *iface) -{ - iface->load = (load_serializable_object_cb)g_restricted_content_load; - iface->store = (store_serializable_object_cb)g_restricted_content_store; - -} - - -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * * Description : Procède à l'initialisation de l'interface de lecture. * * * * Retour : - * @@ -212,8 +221,13 @@ static void g_restricted_content_serializable_init(GSerializableObjectInterface static void g_restricted_content_interface_init(GBinContentInterface *iface) { + iface->set_attribs = (set_content_attributes)g_restricted_content_set_attributes; + iface->get_attribs = (get_content_attributes)g_restricted_content_get_attributes; + iface->get_root = (get_content_root_fc)g_restricted_content_get_root; + iface->describe = (describe_content_fc)g_restricted_content_describe; + iface->compute_checksum = (compute_checksum_fc)g_restricted_content_compute_checksum; iface->compute_size = (compute_size_fc)g_restricted_content_compute_size; @@ -239,6 +253,26 @@ static void g_restricted_content_interface_init(GBinContentInterface *iface) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_restricted_content_serializable_init(GSerializableObjectInterface *iface) +{ + iface->load = (load_serializable_object_cb)g_restricted_content_load; + iface->store = (store_serializable_object_cb)g_restricted_content_store; + +} + + +/****************************************************************************** +* * * Paramètres : content = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -337,55 +371,67 @@ GBinContent *g_restricted_content_new_ro(const GBinContent *content, const mrang /****************************************************************************** * * -* Paramètres : content = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : content = contenu binaire à venir lire. * +* range = espace de restrictions pour les accès. [OUT] * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Indique l'espace de restriction appliqué à un contenu. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_restricted_content_load(GRestrictedContent *content, GObjectStorage *storage, packed_buffer_t *pbuf) +void g_restricted_content_get_range(const GRestrictedContent *content, mrange_t *range) { - bool result; /* Bilan à retourner */ + copy_mrange(range, &content->range); - content->internal = G_BIN_CONTENT(g_object_storage_unpack_object(storage, "contents", pbuf)); - result = (content->internal != NULL); +} - if (result) - result = unpack_mrange(&content->range, pbuf); - return result; -} +/* ---------------------------------------------------------------------------------- */ +/* INTERACTIONS AVEC UN CONTENU BINAIRE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : content = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : content = contenu binaire à actualiser. * +* attribs = jeu d'attributs à lier au contenu courant. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Associe un ensemble d'attributs au contenu binaire. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_restricted_content_store(const GRestrictedContent *content, GObjectStorage *storage, packed_buffer_t *pbuf) +static void g_restricted_content_set_attributes(GRestrictedContent *content, GContentAttributes *attribs) { - bool result; /* Bilan à retourner */ + g_binary_content_set_attributes(content->internal, attribs); - result = g_object_storage_pack_object(storage, "contents", G_SERIALIZABLE_OBJECT(content->internal), pbuf); +} - if (result) - result = pack_mrange(&content->range, pbuf); + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à consulter. * +* * +* Description : Fournit l'ensemble des attributs associés à un contenu. * +* * +* Retour : Jeu d'attributs liés au contenu courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GContentAttributes *g_restricted_content_get_attributes(const GRestrictedContent *content) +{ + GContentAttributes *result; /* Instance à retourner */ + + result = g_binary_content_get_attributes(content->internal); return result; @@ -417,6 +463,57 @@ static GBinContent *g_restricted_content_get_root(GRestrictedContent *content) /****************************************************************************** * * +* Paramètres : content = contenu binaire à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le nom associé au contenu binaire. * +* * +* Retour : Nom de fichier avec chemin absolu au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_restricted_content_describe(const GRestrictedContent *content, bool full) +{ + char *result; /* Description à retourner */ + VMPA_BUFFER(start_str); /* Zone de départ en texte */ + vmpa2t end; /* Position de fin */ + VMPA_BUFFER(end_str); /* Zone de départ en texte */ + char *suffix; /* Construction d'un appendice */ + int ret; /* Bilan de construction */ + + result = g_binary_content_describe(content->internal, full); + + vmpa2_to_string(get_mrange_addr(&content->range), MDS_UNDEFINED, start_str, NULL); + + compute_mrange_end_addr(&content->range, &end); + + vmpa2_to_string(&end, MDS_UNDEFINED, end_str, NULL); + + ret = asprintf(&suffix, "[%s:%s]", start_str, end_str); + + if (ret == -1) + LOG_ERROR_N("asprintf"); + + else + { + if (result != NULL) + result = stradd(result, " "); + + result = stradd(result, suffix); + + free(suffix); + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : content = contenu binaire à venir lire. * * checksum = empreinte de zone mémoire à compléter. * * * @@ -930,21 +1027,64 @@ static bool g_restricted_content_read_leb128(const GRestrictedContent *content, } + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : content = contenu binaire à venir lire. * -* range = espace de restrictions pour les accès. [OUT] * +* Paramètres : content = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * * * -* Description : Indique l'espace de restriction appliqué à un contenu. * +* Description : Charge un contenu depuis une mémoire tampon. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_restricted_content_get_range(const GRestrictedContent *content, mrange_t *range) +static bool g_restricted_content_load(GRestrictedContent *content, GObjectStorage *storage, packed_buffer_t *pbuf) { - copy_mrange(range, &content->range); + bool result; /* Bilan à retourner */ + + content->internal = G_BIN_CONTENT(g_object_storage_unpack_object(storage, "contents", pbuf)); + result = (content->internal != NULL); + + if (result) + result = unpack_mrange(&content->range, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un contenu dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_restricted_content_store(const GRestrictedContent *content, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = g_object_storage_pack_object(storage, "contents", G_SERIALIZABLE_OBJECT(content->internal), pbuf); + + if (result) + result = pack_mrange(&content->range, pbuf); + + return result; } diff --git a/tests/analysis/contents/restricted.py b/tests/analysis/contents/restricted.py index 08aa968..ae11619 100644 --- a/tests/analysis/contents/restricted.py +++ b/tests/analysis/contents/restricted.py @@ -8,6 +8,7 @@ from chrysacase import ChrysalideTestCase from pychrysalide import arch +from pychrysalide.analysis import BinContent from pychrysalide.analysis.contents import FileContent, RestrictedContent from pychrysalide.arch import vmpa, mrange import tempfile @@ -52,7 +53,7 @@ class TestRestrictedContent(ChrysalideTestCase): fcnt = FileContent(self._out.name) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) covered = mrange(start, 12) # 0x15 ... 0x28 rcnt = RestrictedContent(fcnt, covered) @@ -64,10 +65,10 @@ class TestRestrictedContent(ChrysalideTestCase): val = rcnt.read_u8(start) self.assertEqual(val, 0x16) - val = rcnt.read_u16(start, arch.SRE_LITTLE) + val = rcnt.read_u16(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x1817) - val = rcnt.read_u32(start, arch.SRE_LITTLE) + val = rcnt.read_u32(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x24232221) @@ -76,7 +77,7 @@ class TestRestrictedContent(ChrysalideTestCase): fcnt = FileContent(self._out.name) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) covered = mrange(start, 12) # 0x15 ... 0x28 rcnt = RestrictedContent(fcnt, covered) @@ -100,42 +101,42 @@ class TestRestrictedContent(ChrysalideTestCase): fcnt = FileContent(self._out.name) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) covered = mrange(start, 12) # 0x15 ... 0x28 rcnt = RestrictedContent(fcnt, covered) self.assertIsNotNone(rcnt) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_u8(start) self.assertEqual(val, 0x15) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u16(start, arch.SRE_LITTLE) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u16(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x1615) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u32(start, arch.SRE_LITTLE) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u32(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x18171615) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u64(start, arch.SRE_LITTLE) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u64(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x2423222118171615) - start = vmpa(23, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(23, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_u8(start) self.assertEqual(val, 0x28) - start = vmpa(22, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u16(start, arch.SRE_LITTLE) + start = vmpa(22, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u16(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x2827) - start = vmpa(20, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u32(start, arch.SRE_LITTLE) + start = vmpa(20, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u32(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x28272625) - start = vmpa(16, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u64(start, arch.SRE_LITTLE) + start = vmpa(16, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u64(start, BinContent.SourceEndian.LITTLE) self.assertEqual(val, 0x2827262524232221) @@ -144,41 +145,41 @@ class TestRestrictedContent(ChrysalideTestCase): fcnt = FileContent(self._out.name) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) covered = mrange(start, 12) # 0x15 ... 0x28 rcnt = RestrictedContent(fcnt, covered) self.assertIsNotNone(rcnt) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 1) self.assertEqual(val, b'\x15') - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 2) self.assertEqual(val, b'\x15\x16') - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 4) self.assertEqual(val, b'\x15\x16\x17\x18') - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 8) self.assertEqual(val, b'\x15\x16\x17\x18\x21\x22\x23\x24') - start = vmpa(23, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(23, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 1) self.assertEqual(val, b'\x28') - start = vmpa(22, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(22, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 2) self.assertEqual(val, b'\x27\x28') - start = vmpa(20, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(20, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 4) self.assertEqual(val, b'\x25\x26\x27\x28') - start = vmpa(16, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(16, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_raw(start, 8) self.assertEqual(val, b'\x21\x22\x23\x24\x25\x26\x27\x28') @@ -188,7 +189,7 @@ class TestRestrictedContent(ChrysalideTestCase): fcnt = FileContent(self._out.name) - start = vmpa(12, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) covered = mrange(start, 12) # 0x15 ... 0x28 rcnt = RestrictedContent(fcnt, covered) @@ -196,15 +197,29 @@ class TestRestrictedContent(ChrysalideTestCase): with self.assertRaisesRegex(Exception, 'Invalid read access.'): - start = vmpa(1, vmpa.VMPA_NO_VIRTUAL) + start = vmpa(1, vmpa.VmpaSpecialValue.NO_VIRTUAL) val = rcnt.read_u8(start) with self.assertRaisesRegex(Exception, 'Invalid read access.'): - start = vmpa(11, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u16(start, arch.SRE_LITTLE) + start = vmpa(11, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u16(start, BinContent.SourceEndian.LITTLE) with self.assertRaisesRegex(Exception, 'Invalid read access.'): - start = vmpa(23, vmpa.VMPA_NO_VIRTUAL) - val = rcnt.read_u16(start, arch.SRE_LITTLE) + start = vmpa(23, vmpa.VmpaSpecialValue.NO_VIRTUAL) + val = rcnt.read_u16(start, BinContent.SourceEndian.LITTLE) + + + def testDescription(self): + """Ensure restriction range is described.""" + + fcnt = FileContent(self._out.name) + + start = vmpa(12, vmpa.VmpaSpecialValue.NO_VIRTUAL) + covered = mrange(start, 1) + + rcnt = RestrictedContent(fcnt, covered) + self.assertIsNotNone(rcnt) + + self.assertTrue(rcnt.describe().endswith(' [0xc:0xd]')) -- cgit v0.11.2-87-g4458