Calisto Zuzarte

90 papers A* 10A 5B 11C 6Misc 1Journal 23Unranked 34
YearRankTypeTitle / Venue / Authors
2026 B conf
EDBT
Sudip Chatterjee, Xiaozheng Zhang, Suprio Ray, Ian Finlay, Calisto Zuzarte, Mark Stoodley
2026 B conf
EDBT
Shaikh Quader, Andres Jaramillo, Sumona Mukhopadhyay, Ghadeer Abuoda, Calisto Zuzarte, David Kalmuk, Marin Litoiu, Manos Papagelis
2025 A* conf
ICDE
Alexander Bianchi, Rafael Dolores, Andrew Chai, Vincent Corvinelli, Parke Godfrey, Jarek Szlichta, Calisto Zuzarte
2025 A* conf
ICDE
Andrew Chai, Alexander Bianchi, Vincent Corvinelli, Parke Godfrey, Jarek Szlichta, Calisto Zuzarte
2025 J jnl
Proc. VLDB Endow.
Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli
2024 J jnl
CoRR
Chang Liu, Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli
2024 B conf
IEEE Big Data
Chang Liu, Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli
2024 J jnl
Proc. VLDB Endow.
Alexander Bianchi, Andrew Chai, Vincent Corvinelli, Parke Godfrey, Jarek Szlichta, Calisto Zuzarte
2024 J jnl
CoRR
Shaikh Quader, Andres Jaramillo, Sumona Mukhopadhyay, Ghadeer Abuoda, Calisto Zuzarte, David Kalmuk, Marin Litoiu, Manos Papagelis
2024 conf
SIGMOD Conference Companion
Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli
2024 A* conf
ICDE
Amin Kamali, Verena Kantere, Calisto Zuzarte
2024 J jnl
CoRR
Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli
2023 conf
AIKE
Ning Wang, Amin Kamali, Verena Kantere, Calisto Zuzarte, Vincent Corvinelli, Brandon Frendo, Steve Donoghue
2023 A* conf
ICDE
Connor Henderson, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2023 conf
CASCON
Sudip Chatterjee, Shubh Sharma, Nithin Ivan, Saumya Verma, Suprio Ray, Mark Stoodley, Calisto Zuzarte, Ian Finlay
2023 conf
CASCON
Amin Kamali, Calisto Zuzarte, Verena Kantere, Jaroslaw Szlichta, Yueting Chen, Xiaohui Yu, Ning Wang
2022 A conf
CIKM
Connor Henderson, Spencer Bryson, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2022 conf
CASCON
Amin Kamali, Jarek Szlichta, Calisto Zuzarte, Yueting Chen, Verena Kantere, Shaikh Quader
2021 conf
CASCON
Amin Kamali, Calisto Zuzarte, Verena Kantere
2021 conf
CASCON
Waikeat Tan, Mohammed Alhamid, Mohamad Kalil, Ronghao Yang, Vincent Corvinelli, Calisto Zuzarte, Liam Finnie
2021 A conf
CIKM
Alexandar Mihaylov, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2020 conf
CASCON
Omar El Zarif, Safwat Hassan, Ying Zou, Calisto Zuzarte, Vincent Corvinelli, Mohammed Alhamid
2019 J jnl
Proc. VLDB Endow.
Guilherme Damasio, Spencer Bryson, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2019 J jnl
CoRR
Guilherme Damasio, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Alexandar Mihaylov, Jaroslaw Szlichta, Calisto Zuzarte
2019 J jnl
Proc. VLDB Endow.
Guilherme Damasio, Vincent Corvinelli, Parke Godfrey, Piotr Mierzejewski, Alexandar Mihaylov, Jaroslaw Szlichta, Calisto Zuzarte
2018 J jnl
SIGMOD Rec.
Jan-Eike Michels, Keith W. Hare, Krishna G. Kulkarni, Calisto Zuzarte, Zhen Hua Liu, Beda Christoph Hammerschmidt, Fred Zemke
2017 conf
CASCON
Yu Huang, Fei Chiang, Albert Maier, Martin Petitclerc, Yannick Saillet, Damir Spisic, Calisto Zuzarte
2016 A* conf
ICDE
Guilherme Damasio, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2016 J jnl
Inf. Syst. Frontiers
Chao Zhu, Qiang Zhu, Calisto Zuzarte, Wenbin Ma
2016 B conf
EDBT
Guilherme Damasio, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2015 conf
CASCON
Henry Liu, Mingbin Xu, Ziting Yu, Vincent Corvinelli, Calisto Zuzarte
2015 J jnl
CoRR
Guilherme Damasio, Piotr Mierzejewski, Jaroslaw Szlichta, Calisto Zuzarte
2015 J jnl
CoRR
Priyank Gupta, Nick Koudas, Europa Shang, Ryan Johnson, Calisto Zuzarte
2014 conf
CASCON
Petrus Chan, Aruna De Silva, Calisto Zuzarte
2014 B conf
EDBT
Jaroslaw Szlichta, Parke Godfrey, Jarek Gryz, Wenbin Ma, Weinan Qiu, Calisto Zuzarte
2014 J jnl
Comput. J.
Chao Zhu, Qiang Zhu, Calisto Zuzarte
2013 conf
AMW
Jaroslaw Szlichta, Parke Godfrey, Jarek Gryz, Calisto Zuzarte
2013 J jnl
J. Inf. Process. Syst.
Chao Zhu, Qiang Zhu, Calisto Zuzarte, Wenbin Ma
2013 J jnl
Proc. VLDB Endow.
Jaroslaw Szlichta, Parke Godfrey, Jarek Gryz, Calisto Zuzarte
2013 J jnl
VLDB J.
Iman Elghandour, Ashraf Aboulnaga, Daniel C. Zilio, Calisto Zuzarte
2012 conf
DEXA (2)
Zahid Abul-Basher, Yi Feng, Parke Godfrey, Xiaohui Yu, Mokhtar Kandil, Daniel C. Zilio, Calisto Zuzarte
2012 conf
CASCON
Chao Zhu, Qiang Zhu, Calisto Zuzarte, Wenbin Ma
2012 conf
DBTest
Dominic Letarte, François Gauthier, Ettore Merlo, Nattavut Sutyanyong, Calisto Zuzarte
2011 conf
CASCON
Chao Zhu, Qiang Zhu, Calisto Zuzarte, Wenbin Ma
2011 conf
CASCON
Angela Yang, Calisto Zuzarte
2011 B conf
EDBT
Jaroslaw Szlichta, Parke Godfrey, Jarek Gryz, Wenbin Ma, Przemyslaw Pawluk, Calisto Zuzarte
2010 J jnl
VLDB J.
Xiaoying Wu, Dimitri Theodoratos, Calisto Zuzarte
2010 conf
CASCON
Chao Zhu, Qiang Zhu, Calisto Zuzarte
2010 conf
DEXA (1)
Joan Guisado-Gámez, Antoni Wolski, Calisto Zuzarte, Josep Lluís Larriba-Pey, Victor Muntés-Mulero
2010 A conf
CIKM
Marina Barsky, Alex Thomo, Zoltan Toth, Calisto Zuzarte
2010 J jnl
J. Intell. Inf. Syst.
Jarek Gryz, Qiong Wang, Xiaoyan Qian, Calisto Zuzarte
2009 A* conf
ICDE
Parke Godfrey, Jarek Gryz, Andrzej Hoppe, Wenbin Ma, Calisto Zuzarte
2009 conf
XSym
Iman Elghandour, Ashraf Aboulnaga, Daniel C. Zilio, Calisto Zuzarte
2009 J jnl
Proc. VLDB Endow.
Amr El-Helw, Ihab F. Ilyas, Calisto Zuzarte
2008 conf
SIGMOD Conference
Iman Elghandour, Ashraf Aboulnaga, Daniel C. Zilio, Fei Chiang, Andrey Balmin, Kevin S. Beyer, Calisto Zuzarte
2008 conf
SIGMOD Conference
Chaitanya Mishra, Nick Koudas, Calisto Zuzarte
2008 C conf
ISMIS
Jarek Gryz, Qiong Wang, Xiaoyan Qian, Calisto Zuzarte
2008 A conf
CIKM
Guangjun Xie, Qi Cheng, Jarek Gryz, Calisto Zuzarte
2008 A* conf
ICDE
Iman Elghandour, Ashraf Aboulnaga, Daniel C. Zilio, Fei Chiang, Andrey Balmin, Kevin S. Beyer, Calisto Zuzarte
2007 B conf
DaWaK
Wugang Xu, Dimitri Theodoratos, Calisto Zuzarte, Xiaoying Wu, Vincent Oria
2007 A* conf
ICDE
Amr El-Helw, Ihab F. Ilyas, Wing Lau, Volker Markl, Calisto Zuzarte
2007 J jnl
Data Knowl. Eng.
Wen-Syan Li, Daniel C. Zilio, Vishal S. Batra, Calisto Zuzarte, Inderpal Narang
2007 conf
ICDE Workshops
Adrian M. Teisanu, Sam Lightstone, Mariano P. Consens, Daniel C. Zilio, Mokhtar Kandil, Calisto Zuzarte
2007 J jnl
Data Knowl. Eng.
Josep Aguilar-Saborit, Victor Muntés-Mulero, Calisto Zuzarte, Josep Lluís Larriba-Pey
2007 conf
CASCON
Kristine Towne, Qiang Zhu, Calisto Zuzarte, Wen-Chi Hou
2006 C conf
IDEAS
Victor Muntés-Mulero, Josep Lluís Larriba-Pey, Josep Aguilar-Saborit, Calisto Zuzarte, Volker Markl
2006 conf
BNCOD
Victor Muntés-Mulero, Josep Aguilar-Saborit, Calisto Zuzarte, Volker Markl, Josep Lluís Larriba-Pey
2006 Misc conf
International Conference on Computational Science (1)
Victor Muntés-Mulero, Josep Aguilar-Saborit, Calisto Zuzarte, Josep Lluís Larriba-Pey
2006 C conf
DOLAP
Wugang Xu, Dimitri Theodoratos, Calisto Zuzarte
2006 C conf
PDP
Josep Aguilar-Saborit, Victor Muntés-Mulero, Calisto Zuzarte, Adriana Zubiri, Josep Lluís Larriba-Pey
2006 conf
SIGMOD Conference
Calisto Zuzarte, Xiaohui Yu
2006 B conf
EDBT
Xiaohui Yu, Nick Koudas, Calisto Zuzarte
2006 conf
JISBD
Victor Muntés-Mulero, Josep Aguilar-Saborit, Calisto Zuzarte, Josep Lluís Larriba-Pey
2006 A* conf
ICDE
Wen-Syan Li, Daniel C. Zilio, Vishal S. Batra, Mahadevan Subramanian, Calisto Zuzarte, Inderpal Narang
2006 C conf
DEXA
Victor Muntés-Mulero, Marta Pérez-Casany, Josep Aguilar-Saborit, Calisto Zuzarte, Josep Lluís Larriba-Pey
2006 B conf
DaWaK
Wugang Xu, Calisto Zuzarte, Dimitri Theodoratos, Wenbin Ma
2005 B conf
DaWaK
Josep Aguilar-Saborit, Victor Muntés-Mulero, Calisto Zuzarte, Josep Lluís Larriba-Pey
2005 J jnl
SIGMOD Rec.
Leopoldo E. Bertossi, Jan Chomicki, Parke Godfrey, Phokion G. Kolaitis, Alex Thomo, Calisto Zuzarte
2005 J jnl
Knowl. Inf. Syst.
Qiang Zhu, Yingying Tao, Calisto Zuzarte
2005 A conf
CIKM
Xiaohui Yu, Calisto Zuzarte, Kenneth C. Sevcik
2004 conf
SIGMOD Conference
Jun Rao, Hamid Pirahesh, Calisto Zuzarte
2004 B conf
ISPASS
R. Bonilla-Lucas, Peter Plachta, Aamer Sachedina, Daniel Jiménez-González, Calisto Zuzarte, Josep Lluís Larriba-Pey
2004 conf
SIGMOD Conference
Jarek Gryz, Junjie Guo, Linqi Liu, Calisto Zuzarte
2004 conf
ICAC
Daniel C. Zilio, Calisto Zuzarte, Sam Lightstone, Wenbin Ma, Guy M. Lohman, Roberta Cochrane, Hamid Pirahesh, Latha S. Colby, Jarek Gryz, Eric Alton, Dongming Liang, Gary Valentin
2003 C conf
DEXA
Yingying Tao, Qiang Zhu, Calisto Zuzarte
2003 conf
CASCON
Yingying Tao, Qiang Zhu, Calisto Zuzarte, Wing Lau
2003 conf
SIGMOD Conference
Calisto Zuzarte, Hamid Pirahesh, Wenbin Ma, Qi Cheng, Linqi Liu, Kwai Wong
2002 conf
CASCON
Yingying Tao, Qiang Zhu, Calisto Zuzarte
2001 A* conf
ICDE
Jarek Gryz, K. Bernhard Schiefer, Jian Zheng, Calisto Zuzarte
2001 conf
SIGMOD Conference
Parke Godfrey, Jarek Gryz, Calisto Zuzarte
redb/extractors/pe_extractors/pe_features.py
← Index redb/extractors/pe_extractors/pe_features.py python
import base64
import inspect
import json
from pprint import pprint
import re

import pefile

from redb.ext.rich_header import get_rich_idVersion
from redb.extractors.enum import Tag
from redb.extractors.pe_extractor import PEExtractor
from redb.extractors.pe_extractors.pe_dotnet import PEDotNetExtractor
from redb.models.dataclasses import PE
from datetime import datetime, timezone
from typing import Any


class PEFeaturesExtractor(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_features"
        self.log.debug(inspect.currentframe().f_code.co_name)

    def _extract_type(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        if self.pe.is_dll():
            return "DLL"
        elif self.pe.is_driver():
            return "DRIVER"
        elif self.pe.is_exe():
            return "EXE"

    def _extract_architecture(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        mt = {"0x14c": "x86", "0x0200": "Itanium", "0x8664": "x64"}
        machine_value = self.pe.FILE_HEADER.Machine
        if isinstance(machine_value, int):
            return mt.get(str(hex(machine_value)), "")
        return str(machine_value) + " => Not x86/64 or Itanium"

    def _extract_rich_header(self):
        """Extract the Rich header from the PE file

        to decode it back from base64, use:
        rh_tmp = json.loads(rh_b64_string)
        rh_decoded = {}
        for k in rh_tmp:
            if isinstance(rh_tmp[k], str):
                rh_decoded[k] = base64.b64decode(rh_tmp[k])
            else:
                rh_decoded[k] = rh_tmp[k]
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        rh = self.pe.parse_rich_header()
        rich_header_b64 = {}
        rich_header_infos = []
        if rh:
            for key in rh:
                if isinstance(rh[key], bytes):
                    rich_header_b64[key] = base64.b64encode(rh[key]).decode("utf-8")
                else:
                    rich_header_b64[key] = rh[key]
            rich_header_infos = self._get_rich_header_infos(rh)
        return json.dumps(rich_header_b64) if rich_header_b64 else None, "\n".join(
            item for item in rich_header_infos
        ) if rich_header_infos else None

    def _get_rich_header_infos(self, rh):
        """Parse Rich header information from the PE Rich Header dump"""
        self.log.debug(inspect.currentframe().f_code.co_name)

        rich_header_infos = []
        try:
            # Get list of @Comp.IDs and counts from Rich header
            # Elements in rich_fields at even indices are @Comp.IDs
            # Elements in rich_fields at odd indices are counts
            # example:                  'values': [8681481,
            #                             1,
            #                             9795593,
            #                             1]
            rich_fields = rh.get("values", [])
            if len(rich_fields) % 2 != 0:
                self.log.info(f"rich header extraction stopped for {self.hash.sha256}")
                return None

            comp_id = None
            for i in rich_fields:
                if rich_fields.index(i) % 2 == 0:
                    # even -> save value
                    comp_id = get_rich_idVersion(i)
                else:
                    # odd -> add to list
                    if comp_id:
                        rich_header_infos.append(f"{comp_id} count={i}")
                        comp_id = None
        except Exception as e:
            self.log.error(
                f"Extract rich header error {self.hash.sha256} Exception: {e}"
            )
        return rich_header_infos

    def _extract_version_info(self):
        """Extract the VS_VERSIONINFO field in a PE file

        Returns:
        vsinfo: a list of "key:value" strings from VS_INFORMATION content.
               None if no VS_INFORMATION content is present.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        version_info = []
        try:
            if hasattr(self.pe, "VS_VERSIONINFO") and hasattr(self.pe, "FileInfo"):
                for finfo in self.pe.FileInfo:
                    for entry in finfo:
                        if hasattr(entry, "StringTable"):
                            for st_entry in entry.StringTable:
                                for key, str_entry in list(st_entry.entries.items()):
                                    version_info.append(f"{key.decode()}:{str_entry.decode()}")
        except Exception as e:
            self.log.error(
                f"Extract VersionInfo error {self.hash.sha256}  Exception: {e}"
            )
        return version_info if version_info else None

    def _extract_exports(self):
        """
        Returns:
        export_library_name: a str representing the name of the export library.
                            An empty string if no export library is present.
        exp_symbols_list: a list of function names exported as per DIRECTORY_ENTRY_EXPORT.symbols
                            An empty list if no export library is present.
        export_timestamp: a timestamp representing the time of the export.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        export_symbols_list = []
        export_library_name = ""
        export_library_name_raw = ""
        export_timestamp = None
        try:
            if hasattr(self.pe, "DIRECTORY_ENTRY_EXPORT"):
                export_timestamp = self.pe.DIRECTORY_ENTRY_EXPORT.struct.TimeDateStamp
                export_directory = self.pe.DIRECTORY_ENTRY_EXPORT
                export_library_name_rva = export_directory.struct.Name
                try:
                    export_library_name = self.remove_non_utf8(
                        self.pe.get_string_at_rva(export_library_name_rva)
                    ).decode()
                    export_library_name_raw = self.pe.get_string_at_rva(
                        export_library_name_rva
                    ).__str__()
                except Exception as e:
                    self.log.error(
                        f"Error while getting export library name {self.pe.get_string_at_rva(export_library_name_rva)} for file: {self.hash.sha256} {e}"
                    )
                    export_library_name = "REDB_ERROR"
                if hasattr(self.pe.DIRECTORY_ENTRY_EXPORT, "symbols"):
                    for exp in self.pe.DIRECTORY_ENTRY_EXPORT.symbols:
                        export_symbols_list.append(
                            exp.name.decode() if exp.name else None
                        )
        except Exception as e:
            self.log.error(f"Extract exports error {self.hash.sha256} Exception: {e}")

        return (
            export_library_name if export_library_name else None,
            export_library_name_raw if export_library_name_raw else None,
            export_symbols_list if export_symbols_list else None,
            export_timestamp if export_timestamp else None,
        )

    def _extract_dbg_info(self):
        """Extract debug information from PE if present

        At the moment this function parses only the DEBUG_ENTRY Structure where Type
        field == 1, i.e. IMAGE_DEBUG_TYPE_CODEVIEW, where the pdb is eventually present.

        Returns:
        debug_entry: the dump of pe.DIRECTORY_ENTRY_DEBUG.struct only for the type 1
                    "IMAGE_DEBUG_TYPE_CODEVIEW". "None" if not present.
        debug_time: a int representing the epoch timestamp as present in the
                    DIRECTORY_ENTRY_DEBUG. "None" if not present.
        pdb_info: a str with the pdb path. "None" if not present.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        dbg_timestamp = None
        dbg_timestamp_utc = ""
        dbg_pdb_info = ""
        dbg_pdb_info_raw = ""
        dbg_struct = ""
        try:
            if hasattr(self.pe, "DIRECTORY_ENTRY_DEBUG"):
                for debug_entry in self.pe.DIRECTORY_ENTRY_DEBUG:
                    if (
                        debug_entry.struct.Type
                        == pefile.DEBUG_TYPE["IMAGE_DEBUG_TYPE_CODEVIEW"]
                    ):
                        dbg_timestamp = debug_entry.struct.TimeDateStamp
                        dbg_timestamp_utc = datetime.fromtimestamp(
                            dbg_timestamp, timezone.utc
                        ).strftime("%Y-%m-%d %H:%M:%S")
                        # dbg_struct = base64.b64encode(debug_entry.entry).decode()
                        dbg_struct = debug_entry.entry.__str__()
                        if hasattr(debug_entry.entry, "PdbFileName"):
                            dbg_pdb_info = self.remove_non_utf8(
                                debug_entry.entry.PdbFileName.rstrip(b"\x00")
                            ).decode()
                            dbg_pdb_info_raw = debug_entry.entry.PdbFileName.rstrip(
                                b"\x00"
                            ).__str__()
                            # if dbg_pdb_info:
                            #     dbg_pdb_info = dbg_pdb_info.rstrip(b"\x00")
                            #     dbg_pdb_info = dbg_pdb_info.decode()

        except Exception as e:
            self.log.error(f"Extract DBG info error {self.hash.sha256} Exception: {e}")
        return (
            dbg_timestamp if dbg_timestamp else None,
            dbg_timestamp_utc if dbg_timestamp_utc else None,
            dbg_pdb_info if dbg_pdb_info else None,
            dbg_pdb_info_raw if dbg_pdb_info_raw else None,
            dbg_struct if dbg_struct else None,
        )

    def _extract_tls_info(self):
        """Check for the presence of Thread Local Storage and related extract
        callback addresses.

        Taken from the original version of PEScanner, as the python3 porting
        "ext_pescanner" does not have it.

        Returns:
        pe.DIRECTORY_ENTRY_TLS.struct: a pefile.Structure type containing the dump
                    of the TLS structure and content. "None" is no TLS is present.
        callbacks: a list containing the TLS callbacks addresse. Empty list if no
                    address is found, "None" is no TLS is present.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        callbacks = []
        tls_dir_struct = ""
        try:
            if (
                hasattr(self.pe, "DIRECTORY_ENTRY_TLS")
                and self.pe.DIRECTORY_ENTRY_TLS
                and self.pe.DIRECTORY_ENTRY_TLS.struct
                and self.pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks
            ):
                # tls_dir_struct = base64.b64encode(self.pe.DIRECTORY_ENTRY_TLS.struct).decode()
                tls_dir_struct = self.pe.DIRECTORY_ENTRY_TLS.struct.__str__()
                callback_array_rva = (
                    self.pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks
                    - self.pe.OPTIONAL_HEADER.ImageBase
                )
                # Originally it was while True
                # todo while can't be used cause risky
                # what maximum range makes sense to add here?
                for idx in range(10000):
                    func = self.pe.get_dword_from_data(
                        self.pe.get_data(callback_array_rva + 4 * idx, 4), 0
                    )
                    if func == 0:
                        break
                    callbacks.append(func)
        except Exception as e:
            self.log.error(f"Extract TLS error {self.hash.sha256} Exception: {e}")
        return callbacks if callbacks else None, tls_dir_struct if tls_dir_struct else None

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

    def extract(self):
        try:
            self.log.debug(inspect.currentframe().f_code.co_name)
            (
                export_library_name,
                export_library_name_raw,
                export_symbols_list,
                export_timestamp,
            ) = self._extract_exports()
            (
                dbg_timestamp,
                dbg_timestamp_utc,
                dbg_pdb_info,
                dbg_pdb_info_raw,
                dbg_struct,
            ) = self._extract_dbg_info()
            tls_callbacks, tls_struct = self._extract_tls_info()
            rich_header_dump, rich_header_parsed = self._extract_rich_header()

            is_dotnet = self._check_dotnet()

            number_of_resources = 0
            number_of_imports = 0
            if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"):
                number_of_resources = len(self.pe.DIRECTORY_ENTRY_RESOURCE.entries)
            if hasattr(self.pe, "DIRECTORY_ENTRY_IMPORT"):
                number_of_imports = len(self.pe.DIRECTORY_ENTRY_IMPORT)

            self.pe_features = PE(
                type=self._extract_type(),
                magic=hex(self.pe.OPTIONAL_HEADER.Magic),
                entry_point=hex(self.pe.OPTIONAL_HEADER.AddressOfEntryPoint),
                major_linker_version=self.pe.OPTIONAL_HEADER.MajorLinkerVersion,
                minor_linker_version=self.pe.OPTIONAL_HEADER.MinorLinkerVersion,
                target_machine=self.pe.FILE_HEADER.Machine,
                architecture=self._extract_architecture(),
                compilation_time=self.pe.FILE_HEADER.TimeDateStamp,
                compilation_time_utc=datetime.fromtimestamp(
                    self.pe.FILE_HEADER.TimeDateStamp, timezone.utc
                ).strftime("%Y-%m-%d %H:%M:%S"),
                rich_header_dump=rich_header_dump,
                rich_header_parsed=rich_header_parsed,
                dos_header=self.pe.DOS_HEADER.__str__(),
                nt_header=self.pe.NT_HEADERS.__str__(),
                optional_header=self.pe.OPTIONAL_HEADER.__str__(),
                file_header=self.pe.FILE_HEADER.__str__(),
                version_info=self._extract_version_info(),
                export_library_name=export_library_name,
                export_library_name_raw=export_library_name_raw,
                export_symbols_list=export_symbols_list,
                export_timestamp=export_timestamp,
                is_dotnet=is_dotnet,
                dbg_timestamp=dbg_timestamp,
                dbg_timestamp_utc=dbg_timestamp_utc,
                dbg_pdb_info=dbg_pdb_info,
                dbg_pdb_info_raw=dbg_pdb_info_raw,
                dbg_struct=dbg_struct,
                tls_callbacks=tls_callbacks,
                tls_struct=tls_struct,
                is_signed=self._is_signed(),
                has_overlay=self._has_overlay(),
                number_of_sections=len(self.pe.sections),
                number_of_imports=number_of_imports,
                number_of_exports=(
                    len(export_symbols_list) if export_symbols_list else 0
                ),
                number_of_resources=number_of_resources,
            )
            return self.pe_features
        except Exception as e:
            self.log.error(f"Error extracting PE features {self.hash.sha256}: {e}")
            return None

    def prepare_export_data(self, exporter_type: str) -> Any:
        self.log.debug(inspect.currentframe().f_code.co_name)
        if exporter_type == "ElasticsearchExporter":
            return self.pe_features
        elif exporter_type == "ClickHouseExporter":
            try:
                pe_dump = self.pe.dump_dict()   
                # Convert PE headers directly to JSON
                dos_header_raw = json.dumps(pe_dump['DOS_HEADER'])
                nt_header_raw = json.dumps(pe_dump['NT_HEADERS'])
                optional_header_raw = json.dumps(pe_dump['OPTIONAL_HEADER'])
                file_header_raw = json.dumps(pe_dump['FILE_HEADER'])

                # Convert magic and entry_point from hex strings to integers
                magic_raw = int(self.pe_features.magic, 16) if isinstance(self.pe_features.magic, str) else self.pe_features.magic
                entry_point = int(self.pe_features.entry_point, 16) if isinstance(self.pe_features.entry_point, str) else self.pe_features.entry_point

                # Convert target_machine to string if it's an integer
                target_machine = str(self.pe_features.target_machine) if isinstance(self.pe_features.target_machine, int) else self.pe_features.target_machine

                # debug struct
                dbg_struct_raw = {}
                if self.pe_features.dbg_struct:
                    if hasattr(self.pe, "DIRECTORY_ENTRY_DEBUG"):
                        for debug_entry in self.pe.DIRECTORY_ENTRY_DEBUG:
                            if (
                                debug_entry.struct.Type
                                == pefile.DEBUG_TYPE["IMAGE_DEBUG_TYPE_CODEVIEW"]
                            ):
                                dbg_struct_raw = json.dumps(debug_entry.struct.__dict__)

                # tls struct
                tls_struct_raw = {}
                if self.pe_features.tls_struct:
                    if (
                        hasattr(self.pe, "DIRECTORY_ENTRY_TLS")
                        and self.pe.DIRECTORY_ENTRY_TLS
                        and self.pe.DIRECTORY_ENTRY_TLS.struct
                        and self.pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks
                    ):
                        tls_struct_raw = json.dumps(self.pe.DIRECTORY_ENTRY_TLS.struct.__dict__)

                # Ensure arrays are properly initialized
                rich_header_parsed = []
                if self.pe_features.rich_header_parsed:
                    if isinstance(self.pe_features.rich_header_parsed, str):
                        rich_header_parsed = [x for x in self.pe_features.rich_header_parsed.split("\n") if x]
                    elif isinstance(self.pe_features.rich_header_parsed, list):
                        rich_header_parsed = self.pe_features.rich_header_parsed

                version_info = self.pe_features.version_info if self.pe_features.version_info else []
                version_info_raw = {}
                if version_info:
                    for finfo in self.pe.FileInfo:
                        for entry in finfo:
                            if hasattr(entry, "StringTable"):
                                for st_entry in entry.StringTable:
                                    for key, str_entry in list(st_entry.entries.items()):
                                        version_info_raw[key.decode()] = str_entry.decode()
                version_info_raw = json.dumps(version_info_raw) if version_info_raw else "{}"

                export_symbols_list = self.pe_features.export_symbols_list if self.pe_features.export_symbols_list else []
                tls_callbacks = self.pe_features.tls_callbacks if self.pe_features.tls_callbacks else []

                # Prepare data array
                data = [[
                    self.sha256,
                    self.md5,
                    self.sha1,
                    self.pe_features.dos_header,
                    dos_header_raw,
                    self.pe_features.nt_header,
                    nt_header_raw,
                    self.pe_features.optional_header,
                    optional_header_raw,
                    self.pe_features.file_header,
                    file_header_raw,
                    magic_raw,
                    entry_point,
                    self.pe_features.major_linker_version,
                    self.pe_features.minor_linker_version,
                    target_machine,
                    self.pe_features.architecture,
                    self.pe_features.compilation_time,
                    1 if self.pe_features.is_dotnet else 0,
                    1 if self.pe_features.is_signed else 0,
                    1 if self.pe_features.has_overlay else 0,
                    self.pe_features.number_of_sections,
                    self.pe_features.number_of_imports,
                    self.pe_features.number_of_exports,
                    self.pe_features.number_of_resources,
                    self.pe_features.type,
                    self.pe_features.dbg_struct,
                    dbg_struct_raw,
                    self.pe_features.dbg_timestamp,
                    self.pe_features.dbg_pdb_info,
                    self.pe_features.dbg_pdb_info_raw,
                    self.pe_features.tls_struct,
                    tls_struct_raw,
                    self.pe_features.export_timestamp,
                    self.pe_features.export_library_name,
                    self.pe_features.export_library_name_raw,
                    self.pe_features.rich_header_dump if self.pe_features.rich_header_dump else "{}",
                    rich_header_parsed,
                    version_info,
                    version_info_raw,
                    export_symbols_list,
                    tls_callbacks,
                    datetime.now(timezone.utc)
                ]]

                column_names = [
                    'sha256', 'md5', 'sha1',
                    'dos_header', 'dos_header_raw', 'nt_header', 'nt_header_raw', 'optional_header', 'optional_header_raw', 'file_header', 'file_header_raw',
                    'magic_raw', 'entry_point',
                    'major_linker_version', 'minor_linker_version',
                    'target_machine', 'architecture',
                    'compilation_time',
                    'is_dotnet', 'is_signed', 'has_overlay',
                    'number_of_sections', 'number_of_imports', 'number_of_exports', 'number_of_resources',
                    'type',
                    'dbg_struct', 'dbg_struct_raw', 'dbg_timestamp', 'dbg_pdb_info', 'dbg_pdb_info_raw',
                    'tls_struct', 'tls_struct_raw', 'export_timestamp', 'export_library_name', 'export_library_name_raw',
                    'rich_header_dump', 'rich_header_parsed', 'version_info', 'version_info_raw',
                    'export_symbols_list', 'tls_callbacks',
                    'analysis_date'
                ]

                column_type_names = [
                    'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                    'String', 'JSON', 'String', 'JSON', 'String', 'JSON', 'String', 'JSON',
                    'UInt16', 'UInt32',
                    'UInt8', 'UInt8',
                    'LowCardinality(String)', 'Enum8(\'x86\' = 1, \'Itanium\' = 2, \'x64\' = 3)',
                    'UInt64',
                    'UInt8', 'UInt8', 'UInt8',
                    'UInt16', 'UInt16', 'UInt16', 'UInt16',
                    'Enum8(\'DLL\' = 1, \'EXE\' = 2, \'DRIVER\' = 3)',
                    'Nullable(String)', 'JSON', 'Nullable(UInt64)', 'Nullable(String)', 'Nullable(String)',
                    'Nullable(String)', 'JSON', 'Nullable(UInt64)', 'Nullable(String)', 'Nullable(String)',
                    'JSON', 'Array(Nullable(String))', 'Array(Nullable(String))', 'JSON',
                    'Array(Nullable(String))', 'Array(Nullable(UInt64))',
                    'DateTime64(3, \'UTC\')'
                ]

                if not data:
                    return None

                return (data, column_names, column_type_names)
            except Exception as e:
                self.log.error(f"Error preparing export data: {e}")
                raise

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