Ipek Ozkaya

125 papers A* 6A 7B 2Journal 68Unranked 35
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Grace A. Lewis, Rachel A. Brower-Sinning, Robert Edman, Ipek Ozkaya, Sebastián Echeverría, Alex Derr, Collin Beaudoin, Katherine R. Maffey
2025 J jnl
CoRR
Paris Avgeriou, Ipek Ozkaya, Heiko Koziolek, Zadia Codabux, Neil A. Ernst
2025 conf
ICSA Companion
James Ivers, Ipek Ozkaya
2024 conf
ICSE (SEIS)
Heli Järvenpää, Patricia Lago, Justus Bogner, Grace A. Lewis, Henry Muccini, Ipek Ozkaya
2024 conf
ICSA-C
Kevin Pitstick, Marc Novakouski, Grace A. Lewis, Ipek Ozkaya
2024 J jnl
CoRR
Kevin Pitstick, Marc Novakouski, Grace A. Lewis, Ipek Ozkaya
2024 A conf
ICSME
James Ivers, Anwar Ghammam, Khouloud Gaaloul, Ipek Ozkaya, Marouane Kessentini, Wajdi Aljedaani
2024 ed.
AIware
Bram Adams, Thomas Zimmermann, Ipek Ozkaya, Dayi Lin, Jie M. Zhang
2024 J jnl
Dagstuhl Reports
Paris Avgeriou, Ipek Ozkaya, Heiko Koziolek, Zadia Codabux, Neil A. Ernst
2024 J jnl
CoRR
Paris Avgeriou, Ipek Ozkaya, Alexander Chatzigeorgiou, Marcus Ciolkowski, Neil A. Ernst, Ronald J. Koontz, Eltjo R. Poort, Forrest Shull
2024 conf
ICSA-C
Rachel A. Brower-Sinning, Grace A. Lewis, Sebastián Echeverría, Ipek Ozkaya
2024 J jnl
CoRR
Rachel A. Brower-Sinning, Grace A. Lewis, Sebastián Echeverría, Ipek Ozkaya
2023 J jnl
CoRR
Heli Järvenpää, Patricia Lago, Justus Bogner, Grace A. Lewis, Henry Muccini, Ipek Ozkaya
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2023 J jnl
IEEE Trans. Software Eng.
Thiago do Nascimento Ferreira, James Ivers, Jeffrey J. Yackley, Marouane Kessentini, Ipek Ozkaya, Khouloud Gaaloul
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2023 J jnl
Dagstuhl Reports
Grace A. Lewis, Henry Muccini, Ipek Ozkaya, Karthik Vaidhyanathan, Roland Weiss, Liming Zhu
2023 conf
ICSE-FoSE
Paris Avgeriou, Ipek Ozkaya, Alexander Chatzigeorgiou, Marcus Ciolkowski, Neil A. Ernst, Ronald J. Koontz, Eltjo R. Poort, Forrest Shull
2023 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
CoRR
Ipek Ozkaya, Zachary Kurtz, Robert L. Nord, Raghvinder S. Sangwan, Satish Mahadevan Srinivasan
2022 J jnl
PeerJ Comput. Sci.
Roberto Verdecchia, Ivano Malavolta, Patricia Lago, Ipek Ozkaya
2022 J jnl
CoRR
James Ivers, Robert L. Nord, Ipek Ozkaya, Chris Seifried, Christopher Steven Timperley, Marouane Kessentini
2022 conf
ESEC/SIGSOFT FSE
James Ivers, Robert L. Nord, Ipek Ozkaya, Chris Seifried, Christopher Steven Timperley, Marouane Kessentini
2022 conf
ICSE (SEIP)
James Ivers, Robert L. Nord, Ipek Ozkaya, Chris Seifried, Christopher Steven Timperley, Marouane Kessentini
2022 J jnl
IEEE Trans. Software Eng.
Mashel Albarak, Rami Bahsoon, Ipek Ozkaya, Robert L. Nord
2022 J jnl
IEEE Trans. Software Eng.
Raghvinder S. Sangwan, Ashkan Negahban, Robert L. Nord, Ipek Ozkaya
2022 J jnl
J. Syst. Softw.
Ivano Malavolta, Henry Muccini, Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 J jnl
IEEE Softw.
Ipek Ozkaya
2022 A conf
ICSA
James Ivers, Chris Seifried, Ipek Ozkaya
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2021 J jnl
Computer
Raghvinder S. Sangwan, Robert L. Nord, Ipek Ozkaya
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2021 conf
WAIN@ICSE
Grace A. Lewis, Stephany Bellomo, Ipek Ozkaya
2021 J jnl
CoRR
Grace A. Lewis, Stephany Bellomo, Ipek Ozkaya
2021 A* conf
ASE
Chaima Abid, James Ivers, Thiago do Nascimento Ferreira, Marouane Kessentini, Fares E. Kahla, Ipek Ozkaya
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2021 A conf
ICSME
Grace A. Lewis, Ipek Ozkaya, Xiwei Xu
2021 J jnl
IEEE Softw.
Ipek Ozkaya
2020 B conf
ENASE
Roberto Verdecchia, Patricia Lago, Ivano Malavolta, Ipek Ozkaya
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2020 conf
ESEC/SIGSOFT FSE
James Ivers, Ipek Ozkaya, Robert L. Nord, Chris Seifried
2020 B ed.
ECSA
Anton Jansen, Ivano Malavolta, Henry Muccini, Ipek Ozkaya, Olaf Zimmermann
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2020 J jnl
IEEE Softw.
Ipek Ozkaya
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2019 conf
ASE Workshops
James Ivers, Ipek Ozkaya, Robert L. Nord
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2019 J jnl
CoRR
Lena Pons, Ipek Ozkaya
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2019 J jnl
IEEE Softw.
Ipek Ozkaya
2018 J jnl
IEEE Softw.
Claire Le Goues, Ciera Jaspan, Ipek Ozkaya, Mary Shaw, Kathryn T. Stolee
2018 J jnl
ACM SIGSOFT Softw. Eng. Notes
Linda M. Northrop, Ipek Ozkaya, George Fairbanks, Michael Keeling
2018 J jnl
ACM SIGSOFT Softw. Eng. Notes
Lina Northrop, Ipek Ozkaya, George Fairbanks, Michael Keeling
2018 conf
ICSA Companion
Ipek Ozkaya, Liming Zhu
2017 J jnl
ACM SIGSOFT Softw. Eng. Notes
Clemente Izurieta, Ipek Ozkaya, Carolyn B. Seaman, Will Snipes
2017 A conf
ICSA
Neil A. Ernst, Stephany Bellomo, Ipek Ozkaya, Robert L. Nord
2017 J jnl
CoRR
Neil A. Ernst, Stephany Bellomo, Ipek Ozkaya, Robert L. Nord
2016 conf
CSET @ USENIX Security Symposium
Robert L. Nord, Ipek Ozkaya, Edward J. Schwartz, Forrest Shull, Rick Kazman
2016 A conf
MSR
Stephany Bellomo, Robert L. Nord, Ipek Ozkaya, Mary Popeck
2016 J jnl
Dagstuhl Reports
Paris Avgeriou, Philippe Kruchten, Ipek Ozkaya, Carolyn B. Seaman
2016 conf
WICSA
Robert L. Nord, Raghvinder S. Sangwan, Julien Delange, Peter H. Feiler, Luke Thomas, Ipek Ozkaya
2016 conf
QuASoQ/TDA@APSEC
Clemente Izurieta, Ipek Ozkaya, Carolyn B. Seaman, Philippe Kruchten, Robert L. Nord, Will Snipes, Paris Avgeriou
2016 J jnl
IEEE Softw.
Paris Avgeriou, Philippe Kruchten, Robert L. Nord, Ipek Ozkaya, Carolyn B. Seaman
2016 conf
SecDev
Robert L. Nord, Ipek Ozkaya
2016 J jnl
IEEE Softw.
Gregor Hohpe, Ipek Ozkaya, Uwe Zdun, Olaf Zimmermann
2015 ed.
SAM@ICSE
Ipek Ozkaya, Robert L. Nord, Heiko Koziolek, Paris Avgeriou
2015 conf
ESEC/SIGSOFT FSE
Neil A. Ernst, Stephany Bellomo, Ipek Ozkaya, Robert L. Nord, Ian Gorton
2015 ed.
QoSA
Philippe Kruchten, Ipek Ozkaya, Heiko Koziolek
2015 conf
ICSE (2)
Ipek Ozkaya, Robert L. Nord, Heiko Koziolek, Paris Avgeriou
2015 J jnl
ACM SIGSOFT Softw. Eng. Notes
Carolyn B. Seaman, Robert L. Nord, Philippe Kruchten, Ipek Ozkaya
2015 J jnl
ACM SIGSOFT Softw. Eng. Notes
Ipek Ozkaya, Robert L. Nord, Heiko Koziolek, Paris Avgeriou
2014 conf
XP Workshops
Robert L. Nord, Ipek Ozkaya, Philippe Kruchten
2014 conf
ICSE Companion
Robert L. Nord, Ipek Ozkaya, Raghvinder S. Sangwan, Ronald J. Koontz
2014 A conf
ICSME
Stephany Bellomo, Neil A. Ernst, Robert L. Nord, Ipek Ozkaya
2014 conf
CESI
Ipek Ozkaya
2014 J jnl
ACM SIGSOFT Softw. Eng. Notes
Robert L. Nord, Ipek Ozkaya, Heiko Koziolek, Paris Avgeriou
2014 J jnl
ACM SIGSOFT Softw. Eng. Notes
Davide Falessi, Philippe Kruchten, Robert L. Nord, Ipek Ozkaya
2013 A* conf
ICSE
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya
2013 A* conf
ICSE
Stephany Bellomo, Robert L. Nord, Ipek Ozkaya
2013 conf
TwinPeaks@ICSE
Stephany Bellomo, Robert L. Nord, Ipek Ozkaya
2013 A conf
ESEM
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya, Davide Falessi
2013 ed.
MTD@ICSE
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya
2013 conf
SPLASH (Companion Volume)
Steven Fraser, Dennis Mancl, Bill Opdyke, Judith Bishop, Pradeep Kathail, Junilu Lacar, Ipek Ozkaya, Alexandra Szynkarski
2013 A* conf
ICSE
Steven Fraser, Judith Bishop, Barry W. Boehm, Pradeep Kathail, Philippe Kruchten, Ipek Ozkaya, Alexandra Szynkarski
2013 J jnl
ACM SIGSOFT Softw. Eng. Notes
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya, Davide Falessi
2013 conf
TwinPeaks@RE
Neil A. Ernst, Ipek Ozkaya, Robert L. Nord, Julien Delange, Stephany Bellomo, Ian Gorton
2013 conf
ICSM
Robert L. Nord, Ipek Ozkaya, Raghvinder S. Sangwan, Julien Delange, Marco A. Gonzalez, Philippe Kruchten
2012 conf
WICSA/ECSA
Robert L. Nord, Ipek Ozkaya, Philippe Kruchten, Marco Gonzalez-Rojas
2012 J jnl
IEEE Softw.
Robert L. Nord, Ipek Ozkaya, Raghvinder S. Sangwan
2012 ed.
MTD@ICSE
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya, Joost Visser
2012 J jnl
IEEE Softw.
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya
2012 J jnl
ACM SIGSOFT Softw. Eng. Notes
Philippe Kruchten, Robert L. Nord, Ipek Ozkaya, Joost Visser
2011 conf
WICSA
Nanette Brown, Robert L. Nord, Ipek Ozkaya, Manuel Pais
2011 conf
SHARK@ICSE
Robert L. Nord, Nanette Brown, Ipek Ozkaya
2011 conf
OSS
Len Bass, Rick Kazman, Ipek Ozkaya
2011 conf
CSEE&T
Nanette Brown, Robert L. Nord, Ipek Ozkaya, Philippe Kruchten, Erin Lim
2011 J jnl
ACM SIGSOFT Softw. Eng. Notes
Ipek Ozkaya, Philippe Kruchten, Robert L. Nord, Nanette Brown
2011 ed.
MTD@ICSE
Ipek Ozkaya, Philippe Kruchten, Robert L. Nord, Nanette Brown
2011 A* conf
ICSE
Ipek Ozkaya, Philippe Kruchten, Robert L. Nord, Nanette Brown
2010 conf
ICSE (2)
S. Jeromy Carrière, Rick Kazman, Ipek Ozkaya
2010 conf
SHARK@ICSE
Ipek Ozkaya, Peter Wallin, Jakob Axelsson
2010 ch.
Encyclopedia of Software Engineering
Len Bass, Robert L. Nord, Ipek Ozkaya
2010 conf
FoSER
Nanette Brown, Yuanfang Cai, Yuepu Guo, Rick Kazman, Miryung Kim, Philippe Kruchten, Erin Lim, Alan MacCormack, Robert L. Nord, Ipek Ozkaya, Raghvinder S. Sangwan, Carolyn B. Seaman, Kevin J. Sullivan, Nico Zazworka
2010 conf
CSMR
Ipek Ozkaya, J. Andrés Díaz Pace, Arie Gurfinkel, Sagar Chaki
2009 conf
MiSE@ICSE
Sagar Chaki, J. Andrés Díaz Pace, David Garlan, Arie Gurfinkel, Ipek Ozkaya
2008 J jnl
J. Syst. Softw.
Len Bass, Robert L. Nord, William Wood, David Zubrow, Ipek Ozkaya
2008 J jnl
IEEE Softw.
Ipek Ozkaya, Len Bass, Robert L. Nord, Raghvinder S. Sangwan
2005 conf
Software Education and Training Sessions @ ICSE
Mary Shaw, James D. Herbsleb, Ipek Ozkaya, David Root
2005 A* conf
ICSE
Mary Shaw, James D. Herbsleb, Ipek Ozkaya
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