Karel Berka

25 papers Journal 24
YearRankTypeTitle / Venue / Authors
2025 J jnl
J. Cheminformatics
Adrián Rosinec, Terézia Slanináková, Tomás Pavlík, Róbert Randiak, Tomás Svoboda, Tomás Racek, Gabriela Buceková, Ondrej Schindler, Matej Antol, Ales Krenek, Karel Berka, Radka Svobodová Vareková
2025 J jnl
Bioinform.
Tomás Racek, Dusan Vel'ký, Gabriela Buceková, Ondrej Schindler, Ivana Hutarová Vareková, Anna Spacková, Václav Bazgier, Karel Berka, Radka Svobodová Vareková
2023 J jnl
Nucleic Acids Res.
Aliaksei Chareshneu, Adam Midlik, Crina-Maria Ionescu, Alexander S. Rose, Vladimír Horský, Alessio Cantara, Radka Svobodová Vareková, Karel Berka, David Sehnal
2023 J jnl
Nucleic Acids Res.
Ondrej Schindler, Karel Berka, Alessio Cantara, Ales Krenek, Dominik Tichý, Tomás Racek, Radka Svobodová Vareková
2022 J jnl
Bioinform.
Adam Midlik, Ivana Hutarová Vareková, Jan Hutar, Aliaksei Chareshneu, Karel Berka, Radka Svobodová Vareková
2022 J jnl
Nucleic Acids Res.
Mihaly Varadi, Stephen Anyango, David R. Armstrong, John M. Berrisford, Preeti Choudhary, Mandar S. Deshpande, Nurul Nadzirin, Sreenath Nair, Lukás Pravda, Ahsan Tanweer, Bissan Al-Lazikani, Claudia Andreini, Geoffrey J. Barton, David Bednar, Karel Berka, Tom L. Blundell, Kelly Brock, José María Carazo, Jirí Damborský, Alessia David, Sucharita Dey, Roland L. Dunbrack Jr., Juan Fernández-Recio, Franca Fraternali, Toby J. Gibson, Manuela Helmer-Citterich, David Hoksza, Thomas A. Hopf, David Jakubec, Natarajan Kannan, Radoslav Krivák, Manjeet Kumar, Emmanuel D. Levy, Nir London, José Ramón Macías, Mallur Srivatsan Madhusudhan, Debora S. Marks, Lennart Martens, Stuart A McGowan, Jake E. McGreig, Vivek Modi, R. Gonzalo Parra, Gerardo Pepe, Damiano Piovesan, Jaime Prilusky, Valeria Putignano, Leandro G. Radusky, Pathmanaban Ramasamy, Atilio O. Rausch, Nathalie Reuter, Luis A. Rodriguez, Nathan J. Rollins, Antonio Rosato, Pawel Rubach, Luis Serrano, Gulzar Singh, Petr Skoda, Carlos Oscar Sánchez Sorzano, Jan Stourac, Joanna I. Sulkowska, Radka Svobodová Vareková, Natalia Tichshenko, Silvio C. E. Tosatto, Wim F. Vranken, Mark N. Wass, Dandan Xue, Daniel Zaidman, Janet M. Thornton, Michael J. E. Sternberg, Christine A. Orengo, Sameer Velankar
2021 J jnl
Bioinform.
Ivana Hutarová Vareková, Jan Hutar, Adam Midlik, Vladimír Horský, Eva Hladká, Radka Svobodová Vareková, Karel Berka
2021 J jnl
Nucleic Acids Res.
Ian Sillitoe, Nicola Bordin, Natalie L. Dawson, Vaishali P. Waman, Paul Ashford, Harry M. Scholes, Camilla S. M. Pang, Laurel Woodridge, Clemens Rauer, Neeladri Sen, Mahnaz Abbasian, Sean Le Cornu, Su Datt Lam, Karel Berka, Ivana Hutarová Vareková, Radka Svobodová Vareková, Jonathan G. Lees, Christine A. Orengo
2021 J jnl
J. Cheminformatics
Ondrej Schindler, Tomás Racek, Aleksandra Marsavelski, Jaroslav Koca, Karel Berka, Radka Svobodová Vareková
2021 J jnl
Nucleic Acids Res.
David Sehnal, Sebastian Bittrich, Mandar S. Deshpande, Radka Svobodová Vareková, Karel Berka, Václav Bazgier, Sameer Velankar, Stephen K. Burley, Jaroslav Koca, Alexander S. Rose
2021 J jnl
J. Cheminformatics
Ondrej Schindler, Tomás Racek, Aleksandra Marsavelski, Jaroslav Koca, Karel Berka, Radka Svobodová Vareková
2020 J jnl
Nucleic Acids Res.
Tomás Racek, Ondrej Schindler, Dominik Tousek, Vladimír Horský, Karel Berka, Jaroslav Koca, Radka Svobodová Vareková
2020 J jnl
Nucleic Acids Res.
Mihaly Varadi, John M. Berrisford, Mandar S. Deshpande, Sreenath Nair, Aleksandras Gutmanas, David R. Armstrong, Lukás Pravda, Bissan Al-Lazikani, Stephen Anyango, Geoffrey J. Barton, Karel Berka, Tom L. Blundell, Neera Borkakoti, Jose M. Dana, Sayoni Das, Sucharita Dey, Patrizio Di Micco, Franca Fraternali, Toby J. Gibson, Manuela Helmer-Citterich, David Hoksza, Liang-Chin Huang, Rishabh Jain, Harry Jubb, Christos C. Kannas, Natarajan Kannan, Jaroslav Koca, Radoslav Krivák, Manjeet Kumar, Emmanuel D. Levy, Fábio Madeira, M. S. Madhusudhan, Henry J. Martell, Stuart A. MacGowan, Jake E. McGreig, Saqib Mir, Abhik Mukhopadhyay, Luca Parca, Typhaine Paysan-Lafosse, Leandro G. Radusky, António J. M. Ribeiro, Luis Serrano, Ian Sillitoe, Gulzar Singh, Petr Skoda, Radka Svobodová Vareková, Jonathan D. Tyzack, Alfonso Valencia, Eloy D. Villasclaras-Fernández, Wim F. Vranken, Mark N. Wass, Janet M. Thornton, Michael J. E. Sternberg, Christine A. Orengo, Sameer Velankar
2019 J jnl
Database J. Biol. Databases Curation
Jakub Juracka, Martin Srejber, Michaela Melikova, Václav Bazgier, Karel Berka
2018 J jnl
Nucleic Acids Res.
Lukás Pravda, David Sehnal, Radka Svobodová Vareková, Veronika Navrátilová, Dominik Tousek, Karel Berka, Michal Otyepka, Jaroslav Koca
2018 J jnl
Nucleic Acids Res.
Lukás Pravda, David Sehnal, Dominik Tousek, Veronika Navrátilová, Václav Bazgier, Karel Berka, Radka Svobodová Vareková, Jaroslav Koca, Michal Otyepka
2016 J jnl
J. Comput. Chem.
Václav Bazgier, Karel Berka, Michal Otyepka, Pavel Banás
2016 J jnl
J. Chem. Inf. Model.
Petra Cechová, Karel Berka, Martin Kubala
2016 J jnl
Nucleic Acids Res.
Jon C. Ison, Kristoffer Rapacki, Hervé Ménager, Matús Kalas, Emil Rydza, Piotr Chmura, Christian Anthon, Niall Beard, Karel Berka, Dan M. Bolser, Tim Booth, Anthony Bretaudeau, Jan Brezovsky, Rita Casadio, Gianni Cesareni, Frederik Coppens, Michael Cornell, Gianmauro Cuccuru, Kristian Davidsen, Gianluca Della Vedova, Tunca Dogan, Olivia Doppelt-Azeroual, Laura Emery, Elisabeth Gasteiger, Thomas Gatter, Tatyana Goldberg, Marie Grosjean, Björn A. Grüning, Manuela Helmer-Citterich, Hans Ienasescu, Vassilios Ioannidis, Martin Closter Jespersen, Rafael C. Jiménez, Nick S. Juty, Peter Juvan, Maximilian Koch, Camille Laibe, Jing-Woei Li, Luana Licata, Fabien Mareuil, Ivan Micetic, Rune Møllegaard Friborg, Sébastien Moretti, Chris Morris, Steffen Möller, Aleksandra Nenadic, Hedi Peterson, Giuseppe Profiti, Peter M. Rice, Paolo Romano, Paola Roncaglia, Rabie Saidi, Andrea Schafferhans, Veit Schwämmle, Callum Smith, Maria Maddalena Sperotto, Heinz Stockinger, Radka Svobodová Vareková, Silvio C. E. Tosatto, Victor de la Torre, Paolo Uva, Allegra Via, Guy Yachdav, Federico Zambelli, Gert Vriend, Burkhard Rost, Helen E. Parkinson, Peter Løngreen, Søren Brunak
2015 J jnl
J. Chem. Inf. Model.
Veronika Navrátilová, Markéta Paloncýová, Michaela Kajsová, Karel Berka, Michal Otyepka
2014 J jnl
BMC Bioinform.
Lukás Pravda, Karel Berka, Radka Svobodová Vareková, David Sehnal, Pavel Banás, Roman A. Laskowski, Jaroslav Koca, Michal Otyepka
2014 J jnl
Nucleic Acids Res.
Tjaart A. P. de Beer, Karel Berka, Janet M. Thornton, Roman A. Laskowski
2013 J jnl
J. Cheminformatics
David Sehnal, Radka Svobodová Vareková, Karel Berka, Lukás Pravda, Veronika Navrátilová, Pavel Banás, Crina-Maria Ionescu, Michal Otyepka, Jaroslav Koca
2012 J jnl
Nucleic Acids Res.
Karel Berka, Ondrej Hanák, David Sehnal, Pavel Banás, Veronika Navrátilová, Deepti Jaiswal Kundu, Crina-Maria Ionescu, Radka Svobodová Vareková, Jaroslav Koca, Michal Otyepka
1986 book
Logik-Texte - kommentierte Auswahl zur Geschichte der modernen Logik (4. Aufl.).
Karel Berka, Lothar Kreiser
redb/extractors/pe_extractors/pe_dotnet.py
← Index redb/extractors/pe_extractors/pe_dotnet.py python
import inspect
import pefile
from dotnetfile import DotNetPE

import base64
from hashlib import md5
from pprint import pprint

import magic
import pefile

from redb.extractors.enum import Tag
from redb.extractors.pe_extractor import PEExtractor
from redb.models.dataclasses import PEDotNet
from datetime import datetime, timezone
import json
from typing import Any


class PEDotNetExtractor(PEExtractor):

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
        pe=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious,
            pe,
        )
        # self.pe_features = None
        self.elastic_index = self.index_prefix + "-pe_dotnet"
        self.dotnet, self.error = self._generate_dotnetfile_object()
        self.log.debug(inspect.currentframe().f_code.co_name)

    def _decode_assembly_flags(self, flag_value):
        self.log.debug(inspect.currentframe().f_code.co_name)
        ASSEMBLY_FLAGS = {
            0x00000001: "COMIMAGE_FLAGS_ILONLY",
            0x00000002: "COMIMAGE_FLAGS_32BITREQUIRED",
            0x00000004: "COMIMAGE_FLAGS_IL_LIBRARY",
            0x00000008: "COMIMAGE_FLAGS_STRONGNAMESIGNED",
            0x00000010: "COMIMAGE_FLAGS_NATIVE_ENTRYPOINT",
            0x00010000: "COMIMAGE_FLAGS_TRACKDEBUGDATA",
            0x00020000: "COMIMAGE_FLAGS_32BITPREFERRED",
        }
        flags = []
        for bit, name in ASSEMBLY_FLAGS.items():
            if flag_value & bit:
                flags.append(name)
        return flags

    def _normalize_data(self, data):
        self.log.debug(inspect.currentframe().f_code.co_name)
        if isinstance(data, str):
            return {"value": data}
        return data

    def _compute_md5(self, data):
        self.log.debug(inspect.currentframe().f_code.co_name)
        if isinstance(data, str):
            # If it's a string, encode it to first
            return md5(data.encode("raw_unicode_escape")).hexdigest()
        elif not isinstance(data, bytes):
            # If it's neither string nor bytes, convert it to string and then to bytes
            return md5(str(data).encode("raw_unicode_escape")).hexdigest()
        else:
            return md5(data).hexdigest()

    def tag(self):
        return Tag.PE_DOTNET.value

    def extract(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        metadata = {}

        if self.error:
            metadata["Corrupted"] = self.error.args[0]
            dotnet = PEDotNet(metadata)
            self.dotnet = dotnet  # Store for later use in prepare_export_data
            return dotnet  # Return the extracted data instead of exporting directly

        metadata["info"] = {}
        try:
            available_tables = self.dotnet.existent_metadata_tables()
        except Exception as e:
            self.log.error(f"Error getting metadata tables for {self.hash.sha256}: {e}")
            available_tables = []
            metadata["info"]["PotentiallyCorrupted"] = True

        # GUID extraction
        try:
            input_string = self.dotnet.guid_stream_guids[0].string_representation
            
            formatted_uuid = (
                f"{input_string[6:8]}{input_string[4:6]}{input_string[2:4]}{input_string[0:2]}"
                f"-{input_string[10:12]}{input_string[8:10]}"
                f"-{input_string[14:16]}{input_string[12:14]}"
                f"-{input_string[16:20]}"
                f"-{input_string[20:]}"
            )
            metadata["info"]["ModuleVersionID"] = formatted_uuid
        except Exception as e:
            self.log.error(f"Error extracting GUID for {self.hash.sha256}: {e}")

        # CLR Version
        try:
            metadata["info"]["CLRversion"] = self.dotnet.get_runtime_target_version()
        except Exception as e:
            self.log.error(f"Error getting CLR version for {self.hash.sha256}: {e}")

        # Module information
        try:
            if self.dotnet.metadata_table_exists("Module"):
                metadata["info"]["AssemblyModuleName"] = self.dotnet.Module.get_module_name()
        except Exception as e:
            self.log.error(f"Error getting module info for {self.hash.sha256}: {e}")

        # Basic properties
        try:
            metadata["info"].update({
                "IsNativeNgenImage": self.dotnet.is_native_image(),
                "IsMixedAssembly": self.dotnet.is_mixed_assembly(),
                "IsWindowsFormsApp": self.dotnet.is_windows_forms_app(),
                "EntryPointToken": self.dotnet.clr_header.EntryPointToken.value,
                "HasNativeEntryPoint": self.dotnet.has_native_entry_point(),
            })
        except Exception as e:
            self.log.error(f"Error getting basic properties for {self.hash.sha256}: {e}")

        # Assembly flags
        try:
            metadata["info"]["AssemblyFlags"] = self._decode_assembly_flags(
                self.dotnet.clr_header.Flags.value
            )
        except Exception as e:
            self.log.error(f"Error getting assembly flags for {self.hash.sha256}: {e}")

        # More Metadata/Info CLR Header
        try:
            metadata["info"]["NumOfStreams"] = self.dotnet.get_number_of_streams()
            # [TODO] The following two on VT are "RVA entry point"
            #  and "Resources va" respectively. To verify.
            metadata["info"][
                "ResourcesDirectoryAddress"
            ] = self.dotnet.clr_header.ResourcesDirectoryAddress.value
            metadata["info"][
                "ResourcesDirectorySize"
            ] = self.dotnet.clr_header.ResourcesDirectorySize.value
            metadata["info"][
                "StrongNameSignatureAddress"
            ] = self.dotnet.clr_header.StrongNameSignatureAddress.value
            metadata["info"][
                "StrongNameSignatureSize"
            ] = self.dotnet.clr_header.StrongNameSignatureSize.value
            metadata["info"][
                "CodeManagerTableAddress"
            ] = self.dotnet.clr_header.CodeManagerTableAddress.value
            metadata["info"][
                "CodeManagerTableSize"
            ] = self.dotnet.clr_header.CodeManagerTableSize.value
            metadata["info"][
                "VTableFixupsAddress"
            ] = self.dotnet.clr_header.VTableFixupsAddress.value
            metadata["info"][
                "VTableFixupsSize"
            ] = self.dotnet.clr_header.VTableFixupsSize.value
            metadata["info"][
                "ExportAddressTableJumpsAddress"
            ] = self.dotnet.clr_header.ExportAddressTableJumpsAddress.value
            metadata["info"][
                "ExportAddressTableJumpsSize"
            ] = self.dotnet.clr_header.ExportAddressTableJumpsSize.value
            metadata["info"][
                "ManagedNativeHeaderAddress"
            ] = self.dotnet.clr_header.ManagedNativeHeaderAddress.value
            metadata["info"][
                "ManagedNativeHeaderSize"
            ] = self.dotnet.clr_header.ManagedNativeHeaderSize.value
        except Exception as e:
            self.log.error(f"Error getting more metadata/info clr header for {self.hash.sha256}: {e}")

        # Streams section
        try:
            metadata["Streams"] = {}
            stream_names = self.dotnet.get_stream_names()
            for name in stream_names:
                indx = stream_names.index(name)
                stream_header = self.dotnet.dotnet_stream_headers[indx]
                stream_address = self.dotnet.dotnet_streams[indx].address
                metadata["Streams"][name] = {}
                metadata["Streams"][name]["raw_name"] = base64.b64encode(
                    stream_header.Name.value
                ).decode()
                # metadata["Streams"][name]["raw_name"] = name
                metadata["Streams"][name]["size"] = stream_header.Size.value
                # Retrieve the stream data directly using the given address and size
                stream_data = self.pe.get_data(stream_address, stream_header.Size.value)
                metadata["Streams"][name]["entropy"] = (
                    "%.2f" % pefile.SectionStructure.entropy_H(self.pe, stream_data)
                )
                metadata["Streams"][name]["md5"] = md5(stream_data).hexdigest()
        except Exception as e:
            self.log.error(f"Error getting streams for {self.hash.sha256}: {e}")

        # ManifestResource
        try:
            metadata["ManifestResource"] = ()
            if "ManifestResource" in available_tables:
                metadata["info"]["HasManifestResource"] = True
                metadata["ManifestResource"] = (
                    self.dotnet.ManifestResource.get_resource_names()
                )
        except Exception as e:
            self.log.error(f"Error getting manifest resource for {self.hash.sha256}: {e}")

        # ExternalAssemblyRef
        try:
            metadata["ExternalAssemblyRef"] = {}
            if "AssemblyRef" in available_tables:
                metadata["ExternalAssemblyRef"][
                    "names"
                ] = self.dotnet.AssemblyRef.get_assemblyref_names()
                metadata["ExternalAssemblyRef"][
                    "cultures"
                ] = self.dotnet.AssemblyRef.get_assemblyref_cultures()
        except Exception as e:
            self.log.error(f"Error getting external assembly ref for {self.hash.sha256}: {e}")

        # AssemblyData
        try:
            metadata["AssemblyData"] = {}
            if "Assembly" in available_tables:
                metadata["AssemblyData"][
                    "name"
                ] = self.dotnet.Assembly.get_assembly_name()
                # It's officially a one-row table, but there are ITW files with more than one row.
                # It stores information about the current assembly. It is documented in ECMA-335.
                assembly_table = self.dotnet.metadata_tables_lookup[
                    "Assembly"
                ].table_rows[0]
                metadata["AssemblyData"][
                    "MajorVersion"
                ] = assembly_table.MajorVersion.value
                metadata["AssemblyData"][
                    "MinorVersion"
                ] = assembly_table.MinorVersion.value
                metadata["AssemblyData"]["hashalgid"] = assembly_table.HashAlgId.value
                metadata["AssemblyData"][
                    "BuildNumber"
                ] = assembly_table.BuildNumber.value
                metadata["AssemblyData"][
                    "RevisionNumber"
                ] = assembly_table.RevisionNumber.value
                metadata["AssemblyData"][
                    "culture"
                ] = self.dotnet.Assembly.get_assembly_culture()
        except Exception as e:
            self.log.error(f"Error getting assembly data for {self.hash.sha256}: {e}")

        # TypeDef handling
        try:
            metadata["TypeDef"] = {}
            if "TypeDef" in available_tables:
                metadata["info"]["HasTypeDef"] = True
                # Get basic type definitions
                try:
                    # Get all types (ANY visibility)
                    type_defs = self.dotnet.TypeDef.get_type_names()
                    metadata["TypeDef"]["names"] = type_defs if type_defs else []
                    
                    # Get detailed type information with methods
                    types_with_methods = self.dotnet.TypeDef.get_type_names_with_methods()
                    if types_with_methods:
                        metadata["TypeDef"]["detailed"] = []
                        for type_info in types_with_methods:
                            type_data = {
                                "type": type_info.Type,
                                "namespace": type_info.Namespace,
                                "flags": type_info.Flags,
                                "methods": []
                            }
                            for method in type_info.Methods:
                                method_data = {
                                    "name": method.Name,
                                    "flags": method.Flags
                                }
                                if method.Signature:
                                    method_data["signature"] = {
                                        "parameters": method.Signature.get("parameter", []),
                                        "return_type": method.Signature.get("return", ""),
                                        "has_this": method.Signature.get("hasthis", False)
                                    }
                                type_data["methods"].append(method_data)
                            metadata["TypeDef"]["detailed"].append(type_data)
                except AttributeError as e:
                    self.log.warning(f"TypeDef table exists but attributes missing for {self.hash.sha256}: {e}")
                    # metadata["info"]["TypeDefParsingError"] = f"Missing attributes: {str(e)}"
                except Exception as e:
                    self.log.error(f"Error parsing TypeDef table for {self.hash.sha256}: {e}")
                    # metadata["info"]["TypeDefParsingError"] = str(e)
        except Exception as e:
            self.log.error(f"Error handling TypeDef section for {self.hash.sha256}: {e}")
            metadata["TypeDef"] = {"names": [], "detailed": []}
            # metadata["info"]["TypeDefParsingError"] = str(e)

        # ExternalUnmanagedModules
        try:
            metadata["ExternalUnmanagedModules"] = ()
            if "ModuleRef" in available_tables:
                metadata["info"]["HasModuleRef"] = True
                metadata["ExternalUnmanagedModules"] = (
                    self.dotnet.ModuleRef.get_unmanaged_module_names(
                        self.dotnet.Type.UnmanagedModules.RAW
                    )
                )
        except Exception as e:
            self.log.error(f"Error getting external unmanaged modules for {self.hash.sha256}: {e}")

        # ExternalUnmanagedMethods
        try:
            metadata["ExternalUnmanagedMethods"] = ()
            if "ImplMap" in available_tables:
                metadata["info"]["HasImplMap"] = True
                metadata["ExternalUnmanagedMethods"] = (
                    self.dotnet.ImplMap.get_unmanaged_functions()
                )
        except Exception as e:
            self.log.error(f"Error getting external unmanaged methods for {self.hash.sha256}: {e}")

        # Event
        try:
            metadata["Event"] = ()
            if "Event" in available_tables:
                metadata["info"]["HasEvent"] = True
                metadata["Event"] = self.dotnet.Event.get_event_names()
        except Exception as e:
            self.log.error(f"Error getting event for {self.hash.sha256}: {e}")

        # Resources
        try:
            metadata["Resources"] = []
            if self.dotnet.has_resources():
                tmp_resources_list = []
                resource_data = self.dotnet.get_resources()
                for data in resource_data:
                    tmp_dict = {}
                    for resource_item in data.items():
                        if resource_item[0] == "SubResources":
                            if resource_item[1]:
                                tmp_dict["SubResources"] = {}
                                for sub_resource in resource_item[1]:
                                    for sub_resource_item in sub_resource.items():
                                        if sub_resource_item[0] == "Data":
                                            # Check if data is a sequence type that supports len()
                                            if hasattr(sub_resource_item[1], '__len__') and len(sub_resource_item[1]) > 100:
                                                tmp_dict["SubResources"]["Data"] = {}
                                                try:
                                                    # tmp_dict["SubResources"]["Data"][
                                                    #     "md5"
                                                    # ] = md5(
                                                    #     sub_resource_item[1].encode()
                                                    # ).hexdigest()
                                                    tmp_dict["SubResources"]["Data"][
                                                        "md5"
                                                    ] = self._compute_md5(
                                                        sub_resource_item[1]
                                                    )
                                                except Exception as e:
                                                    self.log.error(
                                                        f"Error in dotnet resources"
                                                        f" extraction {self.hash.sha256}: {e}"
                                                    )
                                                guess = magic.from_buffer(
                                                    sub_resource_item[1], mime=True
                                                )
                                                tmp_dict["SubResources"]["Data"][
                                                    "MimeType"
                                                ] = (guess if guess else None)
                                            else:
                                                normalized_data = self._normalize_data(
                                                    sub_resource_item[1].decode()
                                                    if isinstance(
                                                        sub_resource_item[1], bytes
                                                    )
                                                    else sub_resource_item[1]
                                                )
                                                tmp_dict["SubResources"][
                                                    sub_resource_item[0]
                                                ] = normalized_data
                                        else:
                                            tmp_dict["SubResources"][
                                                sub_resource_item[0]
                                            ] = (
                                                sub_resource_item[1].decode()
                                                if isinstance(
                                                    sub_resource_item[1], bytes
                                                )
                                                else sub_resource_item[1]
                                            )
                        elif resource_item[0] == "Data":
                            # Check if data is a sequence type that supports len()
                            if hasattr(resource_item[1], '__len__') and len(resource_item[1]) > 100:
                                tmp_dict["Data"] = {}
                                tmp_dict["Data"]["md5"] = self._compute_md5(
                                    resource_item[1]
                                )
                                guess = magic.from_buffer(resource_item[1], mime=True)
                                tmp_dict["Data"]["MimeType"] = guess if guess else None
                            else:
                                normalized_data = self._normalize_data(
                                    resource_item[1].decode()
                                    if isinstance(resource_item[1], bytes)
                                    else resource_item[1]
                                )
                                tmp_dict["Data"] = normalized_data
                        else:
                            tmp_dict[resource_item[0]] = (
                                resource_item[1].decode()
                                if isinstance(resource_item[1], bytes)
                                else resource_item[1]
                            )
                    tmp_resources_list.append(tmp_dict)
                metadata["Resources"] = tmp_resources_list
        except Exception as e:
            self.log.error(f"Error getting resources for {self.hash.sha256}: {e}")
            metadata["Resources"] = []  # Ensure we always have a valid list even on error

        dotnet = PEDotNet(metadata)
        self.dotnet = dotnet  # Store for later use in prepare_export_data
        return dotnet  # Return the extracted data instead of exporting directly


    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ElasticsearchExporter":
            return self.dotnet
        elif exporter_type == "ClickHouseExporter":
            # Convert metadata to JSON string
            metadata_json = json.dumps(self.dotnet.dotnet)
            
            data = [[
                self.sha256,
                self.md5,
                self.sha1,
                metadata_json,
                datetime.now(timezone.utc)
            ]]
            
            column_names = [
                'sha256', 'md5', 'sha1', 'dotnet', 'analysis_date'
            ]
            
            if not data:
                return None

            column_type_names = [
                'String', 'String', 'String', 'JSON', 'DateTime64(3, \'UTC\')'
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "redb_pe_dotnet"