Magdalena Ortiz

138 papers A* 34A 5B 4C 4Journal 29Unranked 58
YearRankTypeTitle / Venue / Authors
2026 J jnl
Artif. Intell.
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2025 A* conf
KR
Federica Di Stefano, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Reijo Jaakkola, Tomi Janhunen, Antti Kuusisto, Magdalena Ortiz, Matias Selin, Mantas Simkus
2025 A* conf
KR
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 conf
DL
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 A* ed.
KR
Magdalena Ortiz, Renata Wassermann, Torsten Schaub
2025 conf
DL
Bianca Löhnert, Nikolaus Augsten, Cem Okulmus, Magdalena Ortiz
2025 conf
ISWC (1)
Shqiponja Ahmetaj, George Konstantinidis, Magdalena Ortiz, Paolo Pareti, Mantas Simkus
2025 J jnl
CoRR
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Shqiponja Ahmetaj, George Konstantinidis, Magdalena Ortiz, Paolo Pareti, Mantas Simkus
2025 conf
ESWC (1)
Bianca Löhnert, Nikolaus Augsten, Cem Okulmus, Magdalena Ortiz
2025 conf
DL
Jonas Philipp Haldimann, Magdalena Ortiz, Mantas Simkus
2025 conf
JELIA (1)
Jonas Haldimann, Magdalena Ortiz, Mantas Simkus
2025 conf
DL
Federica Di Stefano, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2024 J jnl
Artif. Intell.
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2024 ed.
FoIKS
Arne Meier, Magdalena Ortiz
2024 A* ed.
KR
Pierre Marquis, Magdalena Ortiz, Maurice Pagnucco
2024 conf
Description Logics
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2024 conf
Description Logics
Bianca Löhnert, Nikolaus Augsten, Cem Okulmus, Magdalena Ortiz
2024 J jnl
CoRR
Bianca Löhnert, Nikolaus Augsten, Cem Okulmus, Magdalena Ortiz
2024 conf
AMW
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2023 C conf
WoLLIC
Magdalena Ortiz
2023 conf
Description Logics
Piero A. Bonatti, Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2023 A* conf
IJCAI
Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2023 B ed.
JELIA
Sarah Alice Gaggl, Maria Vanina Martinez, Magdalena Ortiz
2023 conf
Description Logics
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2023 conf
AMW
Diego Calvanese, Cem Okulmus, Magdalena Ortiz, Mantas Simkus
2023 conf
Description Logics
Shqiponja Ahmetaj, Magdalena Ortiz, Anouk Michelle Oudshoorn, Mantas Simkus
2023 A conf
ECAI
Shqiponja Ahmetaj, Magdalena Ortiz, Anouk Oudshoorn, Mantas Simkus
2023 conf
ISWC (Posters/Demos/Industry)
Anouk Oudshoorn, Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2023 conf
Description Logics
Nikola Dragovic, Cem Okulmus, Magdalena Ortiz
2022 A conf
IJCAR
Claudia Cauli, Magdalena Ortiz, Nir Piterman
2022 J jnl
CoRR
Claudia Cauli, Magdalena Ortiz, Nir Piterman
2022 J jnl
Proc. VLDB Endow.
Shqiponja Ahmetaj, Bianca Löhnert, Magdalena Ortiz, Mantas Simkus
2022 conf
Description Logics
Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2021 conf
Description Logics
Claudia Cauli, Magdalena Ortiz, Nir Piterman
2021 A* conf
KR
Claudia Cauli, Magdalena Ortiz, Nir Piterman
2021 conf
ISWC (Posters/Demos/Industry)
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2021 conf
ISWC (Posters/Demos/Industry)
Shqiponja Ahmetaj, Bianca Loehnert, Magdalena Ortiz, Mantas Simkus
2021 conf
Description Logics
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2021 A* conf
KR
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2020 conf
Description Logics
Medina Andresel, Yazmín Ibáñez-García, Magdalena Ortiz
2020 J jnl
CoRR
Nadia Labai, Magdalena Ortiz, Mantas Simkus
2020 A* conf
KR
Nadia Labai, Magdalena Ortiz, Mantas Simkus
2020 A* conf
KR
Tomasz Gogacz, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2020 A conf
ECAI
Tomasz Gogacz, Víctor Gutiérrez-Basulto, Yazmín Ibáñez-García, Filip Murlak, Magdalena Ortiz, Mantas Simkus
2020 C conf
LATA
Nadia Labai, Tomer Kotek, Magdalena Ortiz, Helmut Veith
2020 J jnl
Artif. Intell.
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2020 A* conf
AAAI
Medina Andresel, Magdalena Ortiz, Mantas Simkus
2020 A* conf
AAAI
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2020 conf
Description Logics
Magdalena Ortiz
2020 A* conf
WWW
Medina Andresel, Julien Corman, Magdalena Ortiz, Juan L. Reutter, Ognjen Savkovic, Mantas Simkus
2019 conf
Description Logics
Magdalena Ortiz, Sanja Pavlovic, Mantas Simkus
2019 conf
AMW
Magdalena Ortiz
2019 J jnl
CoRR
Tomasz Gogacz, Víctor Gutiérrez-Basulto, Yazmín Angélica Ibáñez-García, Filip Murlak, Magdalena Ortiz, Mantas Simkus
2019 conf
GCAI
Magdalena Ortiz
2019 conf
ISWC (1)
Labinot Bajraktari, Magdalena Ortiz, Guohui Xiao
2019 J jnl
CoRR
Nadia Labai, Tomer Kotek, Magdalena Ortiz, Helmut Veith
2019 J jnl
CoRR
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2019 A* conf
AAAI
Medina Andresel, Yazmín Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 conf
Description Logics
Katinka Böhm, Magdalena Ortiz
2018 A* conf
AAAI
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2018 A* conf
IJCAI
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2018 A* conf
IJCAI
Magdalena Ortiz
2018 ed.
Description Logics
Magdalena Ortiz, Thomas Schneider
2018 A* conf
KR
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 J jnl
CoRR
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 J jnl
Dagstuhl Manifestos
Serge Abiteboul, Marcelo Arenas, Pablo Barceló, Meghyn Bienvenu, Diego Calvanese, Claire David, Richard Hull, Eyke Hüllermeier, Benny Kimelfeld, Leonid Libkin, Wim Martens, Tova Milo, Filip Murlak, Frank Neven, Magdalena Ortiz, Thomas Schwentick, Julia Stoyanovich, Jianwen Su, Dan Suciu, Victor Vianu, Ke Yi
2018 A conf
ICDT
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2018 conf
Description Logics
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2017 conf
Description Logics
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2017 conf
Description Logics
Nadia Labai, Martin Homola, Magdalena Ortiz
2017 J jnl
ACM Trans. Comput. Log.
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2017 C conf
FQAS
Christian G. Fermüller, Matthias F. J. Hofer, Magdalena Ortiz
2017 J jnl
CoRR
Serge Abiteboul, Marcelo Arenas, Pablo Barceló, Meghyn Bienvenu, Diego Calvanese, Claire David, Richard Hull, Eyke Hüllermeier, Benny Kimelfeld, Leonid Libkin, Wim Martens, Tova Milo, Filip Murlak, Frank Neven, Magdalena Ortiz, Thomas Schwentick, Julia Stoyanovich, Jianwen Su, Dan Suciu, Victor Vianu, Ke Yi
2016 conf
Description Logics
Medina Andresel, Magdalena Ortiz, Mantas Simkus
2016 conf
AMW
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2016 A* conf
KR
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2016 A* conf
IJCAI
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 conf
AMW
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 conf
Description Logics
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 J jnl
SIGMOD Rec.
Serge Abiteboul, Marcelo Arenas, Pablo Barceló, Meghyn Bienvenu, Diego Calvanese, Claire David, Richard Hull, Eyke Hüllermeier, Benny Kimelfeld, Leonid Libkin, Wim Martens, Tova Milo, Filip Murlak, Frank Neven, Magdalena Ortiz, Thomas Schwentick, Julia Stoyanovich, Jianwen Su, Dan Suciu, Victor Vianu, Ke Yi
2016 A conf
ICDT
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2016 ed.
RR
Magdalena Ortiz, Stefan Schlobach
2015 conf
AMW
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2015 conf
Reasoning Web
Meghyn Bienvenu, Magdalena Ortiz
2015 J jnl
J. Artif. Intell. Res.
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2015 conf
Description Logics
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2014 J jnl
Inf. Comput.
Diego Calvanese, Thomas Eiter, Magdalena Ortiz
2014 ed.
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Riccardo Rosati, Mantas Simkus
2014 A* conf
AAAI
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
AMW
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 A* conf
KR
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
Description Logics
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
AMW
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2014 conf
RR
Magdalena Ortiz, Mantas Simkus
2013 A* conf
IJCAI
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2013 conf
Description Logics
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2013 conf
AMW
Magdalena Ortiz
2013 J jnl
J. Artif. Intell. Res.
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2013 conf
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus, Guohui Xiao
2013 A* conf
IJCAI
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus, Guohui Xiao
2012 conf
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2012 J jnl
J. Comput. Syst. Sci.
Thomas Eiter, Magdalena Ortiz, Mantas Simkus
2012 A* conf
AAAI
Thomas Eiter, Magdalena Ortiz, Mantas Simkus, Trung-Kien Tran, Guohui Xiao
2012 conf
Reasoning Web
Magdalena Ortiz, Mantas Simkus
2012 A* conf
KR
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2012 conf
Description Logics
Thomas Eiter, Magdalena Ortiz, Mantas Simkus, Trung-Kien Tran, Guohui Xiao
2011 A* conf
IJCAI
Diego Calvanese, Domenico Carbotta, Magdalena Ortiz
2011 A* conf
IJCAI
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2011 A* conf
IJCAI
Magdalena Ortiz, Sebastian Rudolph, Mantas Simkus
2011 conf
Description Logics
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2010 conf
Description Logics
Meghyn Bienvenu, Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2010 A* conf
KR
Magdalena Ortiz, Sebastian Rudolph, Mantas Simkus
2009 A* conf
IJCAI
Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2009 C conf
WoLLIC
Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2009 A* conf
IJCAI
Diego Calvanese, Thomas Eiter, Magdalena Ortiz
2008 conf
LA-NMR
Magdalena Ortiz
2008 conf
Description Logics
Magdalena Ortiz, Mantas Simkus, Thomas Eiter
2008 J jnl
J. Autom. Reason.
Magdalena Ortiz, Diego Calvanese, Thomas Eiter
2008 B conf
JELIA
Magdalena Ortiz
2008 B conf
JELIA
Thomas Eiter, Georg Gottlob, Magdalena Ortiz, Mantas Simkus
2008 B conf
LPAR
Thomas Eiter, Magdalena Ortiz, Mantas Simkus
2008 A* conf
AAAI
Magdalena Ortiz, Mantas Simkus, Thomas Eiter
2007 A* conf
AAAI
Diego Calvanese, Thomas Eiter, Magdalena Ortiz
2007 J jnl
J. Log. Comput.
Magdalena Ortiz, Mauricio Osorio
2006 A* conf
AAAI
Magdalena Ortiz, Diego Calvanese, Thomas Eiter
2006 conf
Description Logics
Magdalena Ortiz, Diego Calvanese, Thomas Eiter
2005 conf
ENC
Gerardo Ayala, Magdalena Ortiz, Mauricio Osorio
2005 conf
MICAI
Gerardo Ayala, Magdalena Ortiz, Mauricio Osorio
2005 J jnl
CoRR
Magdalena Ortiz, Diego Calvanese, Thomas Eiter, Enrico Franconi
2005 conf
Answer Set Programming
Magdalena Ortiz, Mauricio Osorio
2004 conf
LA-NMR
Magdalena Ortiz
2003 conf
ENC
Magdalena Ortiz, Gerardo Ayala, Mauricio Osorio
redb/extractors/ioc_extractor/ioc_extractor.py
← Index redb/extractors/ioc_extractor/ioc_extractor.py python
"""
IOC Extractor - Extractor class for extracting IOCs from decompilation results.

This extractor works with in-memory data from DecompileBinja, following the
standard Extractor pattern to support both ClickHouse and PrintExporter (dry-run).

Usage:
    # After DecompileBinja completes:
    ioc_extractor = IOCExtractorFromResults(
        analysis_results=decompiler.analysis_results,
        sha256=sha256,
        log=logger,
        exporters=exporters,
        index_prefix=index_prefix
    )
    ioc_extractor.export_data()
"""

import inspect
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, List, Dict, Optional

from redb.extractors.enum import Tag
from redb.extractors.database_exporters import DatabaseExporter

# Import the IOCScraper and related classes from standalone module
from redb.extractors.ioc_extractor.standalone_ioc_extractor import (
    IOCScraper,
    IOCType,
    SourceType,
    ExtractedIOC,
)
from typing import Set


class IOCExtractorFromResults:
    """
    Extracts IOCs from in-memory decompilation results.

    This follows a simplified Extractor pattern but doesn't inherit from Extractor
    since it doesn't read from a binary file - instead it takes already-processed
    analysis results from DecompileBinja.
    """

    def __init__(
        self,
        analysis_results: Dict[str, Any],
        sha256: str,
        log: Any,
        exporters: Optional[List[DatabaseExporter]] = None,
        index_prefix: Optional[str] = None,
        tld_file: Optional[Path] = None,
        suppress_types: Optional[Set[IOCType]] = None,
        js_context: bool = False,
    ):
        """
        Initialize IOC Extractor with analysis results.

        Args:
            analysis_results: Dict containing 'strings' and 'decompiled' lists from DecompileBinja
            sha256: Sample SHA256 hash
            log: Logger instance
            exporters: List of database exporters (ClickHouse, Print, etc.)
            index_prefix: Index prefix for database
            tld_file: Optional path to TLD list file
            js_context: When True, the underlying IOCScraper rejects FQDN
                candidates that match JS object-access syntax (see
                JS_FP_TLDS / JS_FP_SLDS). Set this for the JS pipeline only;
                APK suppresses FQDN entirely via suppress_types and binary
                callers leave it disabled.
        """
        self.log = log
        self.log.debug(f"Creating {self.__class__.__name__}")
        self.analysis_results = analysis_results
        self.sha256 = sha256
        self.exporters = exporters or []
        self.index_prefix = index_prefix
        self.scraper = IOCScraper(
            tld_file, suppress_types=suppress_types, js_context=js_context,
        )
        self.extracted_iocs: List[ExtractedIOC] = []

    def extract(self) -> List[ExtractedIOC]:
        """
        Extract IOCs from strings and decompiled functions in analysis_results.

        Returns:
            List of ExtractedIOC objects
        """
        self.log.debug(inspect.currentframe().f_code.co_name)
        self.extracted_iocs = []

        # Extract from strings
        strings_count = self._extract_from_strings()

        # Extract from decompiled functions
        functions_count = self._extract_from_decompiled()

        # Extract from text-based artefact surfaces (JS, PowerShell, etc.)
        text_count = self._extract_from_text()

        self.log.info(
            f"Extracted {len(self.extracted_iocs)} IOCs for {self.sha256[:16]}... "
            f"(strings: {strings_count}, functions: {functions_count}, "
            f"text: {text_count})"
        )

        return self.extracted_iocs

    def _extract_from_strings(self) -> int:
        """Extract IOCs from sample's strings."""
        count = 0
        strings = self.analysis_results.get("strings", [])

        for s in strings:
            string_value = s.get("string", "")
            string_offset = s.get("string_offset", 0)

            if isinstance(string_value, bytes):
                string_value = string_value.decode('utf-8', errors='replace')

            for ioc in self.scraper.scrape(string_value, SourceType.STRING, str(string_offset)):
                self.extracted_iocs.append(ioc)
                count += 1

        return count

    def _extract_from_decompiled(self) -> int:
        """Extract IOCs from sample's decompiled functions.

        Supports both Binja format (key: "decompiled", fields: "decompiled_function",
        "decompiled_function_hash", "function_type") and APK format (key:
        "decompiled_content", fields: "decompiled_method", "decompiled_method_hash",
        "method_type").
        """
        count = 0

        # Binja format
        decompiled = self.analysis_results.get("decompiled", [])
        for func in decompiled:
            func_type = func.get("function_type", "UNKNOWN")
            if func_type in ("LIBRARY", "THUNK"):
                continue

            func_content = func.get("decompiled_function", "")
            func_hash = func.get("decompiled_function_hash", "unknown")

            if isinstance(func_content, bytes):
                func_content = func_content.decode('utf-8', errors='replace')

            for ioc in self.scraper.scrape(func_content, SourceType.DECOMPILED_FUNCTION, func_hash):
                self.extracted_iocs.append(ioc)
                count += 1

        # APK format (decompiled_content with method-level fields)
        decompiled_content = self.analysis_results.get("decompiled_content", [])
        for func in decompiled_content:
            func_type = func.get("method_type", "UNKNOWN")
            if func_type in ("LIBRARY", "THUNK"):
                continue

            func_content = func.get("decompiled_method", "")
            func_hash = func.get("decompiled_method_hash", "unknown")

            if isinstance(func_content, bytes):
                func_content = func_content.decode('utf-8', errors='replace')

            for ioc in self.scraper.scrape(func_content, SourceType.DECOMPILED_FUNCTION, func_hash):
                self.extracted_iocs.append(ioc)
                count += 1

        return count

    def _extract_from_text(self) -> int:
        """Extract IOCs from text-based artefact surfaces.

        Walks `analysis_results["text_raw"]` and `analysis_results["text_normalized"]`,
        each a list of `{"content": str, "content_hash": str}` dicts. Each
        list is routed through its own SourceType (`TEXT_RAW` /
        `TEXT_NORMALIZED`) so analysts can distinguish IOCs that were already
        present in the raw source from those exposed only after normalisation
        (deobfuscation/beautification). Generic across text-based formats —
        used by JS today, intended for PowerShell, Python, email body,
        extracted PDF/Office text in the future.
        """
        count = 0

        for key, source_type in (
            ("text_raw", SourceType.TEXT_RAW),
            ("text_normalized", SourceType.TEXT_NORMALIZED),
        ):
            for entry in self.analysis_results.get(key, []):
                content = entry.get("content", "")
                content_hash = entry.get("content_hash", "unknown")

                if isinstance(content, bytes):
                    content = content.decode('utf-8', errors='replace')

                for ioc in self.scraper.scrape(content, source_type, content_hash):
                    self.extracted_iocs.append(ioc)
                    count += 1

        return count

    def prepare_export_data(self, exporter_type: str) -> Any:
        """
        Prepare data for specific export type.

        Returns tuple for ClickHouse or list of dicts for Print/Elasticsearch.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        if not self.extracted_iocs:
            return None

        now = datetime.now(timezone.utc)

        if exporter_type == "ClickHouseExporter":
            data = [
                [
                    self.sha256,
                    ioc.ioc_type.value,
                    ioc.ioc_value,
                    ioc.source_type.value,
                    ioc.source_identifier,
                    now,
                ]
                for ioc in self.extracted_iocs
            ]

            column_names = [
                "sha256",
                "ioc_type",
                "ioc_value",
                "source_type",
                "source_identifier",
                "extracted_at",
            ]

            column_type_names = [
                "FixedString(64)",
                "Enum8('ipv4'=1, 'ipv6'=2, 'fqdn'=3, 'url'=4, 'email'=5, 'server'=6, "
                "'hash_md5'=10, 'hash_sha1'=11, 'hash_sha256'=12, 'cve'=20, 'cwe'=21, 'cpe'=22, "
                "'crypto_btc'=30, 'crypto_eth'=31, 'crypto_xrp'=32, 'crypto_bch'=33, "
                "'crypto_ada'=34, 'crypto_substrate'=35, 'path_linux'=40, 'path_windows'=41, "
                "'registry_key'=42, 'onion'=50)",
                "String",
                "Enum8('decompiled_function'=1, 'disassembled_function'=2, 'string'=3, "
                "'text_raw'=4, 'text_normalized'=5)",
                "String",
                "DateTime64(3, 'UTC')",
            ]

            return (data, column_names, column_type_names)

        else:
            # For PrintExporter and others - return list of dicts
            return [
                {
                    "sha256": self.sha256,
                    "ioc_type": ioc.ioc_type.value,
                    "ioc_value": ioc.ioc_value,
                    "source_type": ioc.source_type.value,
                    "source_identifier": ioc.source_identifier,
                    "extracted_at": now.isoformat(),
                }
                for ioc in self.extracted_iocs
            ]

    def get_clickhouse_table(self) -> str:
        """Return the ClickHouse table name for IOCs."""
        return "redb_iocs"

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.IOC.value if hasattr(Tag, 'IOC') else "ioc"

    def export_data(self) -> bool:
        """
        Export extracted IOCs to all configured exporters.

        Returns:
            True if export succeeded, False if failed, None if no data
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        # First extract the IOCs
        extracted = self.extract()

        if not extracted:
            self.log.debug("No IOCs extracted, skipping export")
            return None

        success = True

        from redb.extractors.database_exporters import PrintExporter, ClickHouseExporter

        for exporter in self.exporters:
            try:
                if isinstance(exporter, PrintExporter):
                    # For PrintExporter, pass the list of dicts
                    export_data = self.prepare_export_data("PrintExporter")
                    success &= exporter.export(export_data)

                elif isinstance(exporter, ClickHouseExporter):
                    # For ClickHouse, pass tuple with table info
                    export_data = self.prepare_export_data("ClickHouseExporter")
                    if export_data:
                        success &= exporter.export(
                            export_data,
                            table=self.get_clickhouse_table(),
                            column_names=export_data[1],
                            column_type_names=export_data[2]
                        )

            except Exception as e:
                self.log.error(f"Error exporting IOCs to {exporter.__class__.__name__}: {e}")
                success = False

        return success