Xiao-Feng Gong

56 papers Misc 13Journal 21Unranked 22
YearRankTypeTitle / Venue / Authors
2026 J jnl
Signal Process.
Guozhao Liao, Xiao-Feng Gong, Wei Liu, Hing Cheung So
2025 Misc conf
ICASSP
Lei Wang, Xiao-Feng Gong, Xi-Yuan Liu, Wei Feng, Qiu-Hua Lin
2025 Misc conf
ICASSP
Xi-Yuan Liu, Xiao-Feng Gong, Lei Wang, Wei Feng, Qiu-Hua Lin
2025 conf
VTC2025-Fall
Wei Feng, Xiao-Feng Gong, Lei Wang, Xi-Yuan Liu, Qiu-Hua Lin
2025 Misc conf
ICASSP
Guozhao Liao, Xiao-Feng Gong, Wei Liu, Hing Cheung So
2025 J jnl
CoRR
Guozhao Liao, Xiao-Feng Gong, Wei Liu, Hing Cheung So
2025 J jnl
J. Frankl. Inst.
Guozhao Liao, Rui-Xue Chen, Qiu-Hua Lin, Xiao-Feng Gong
2024 J jnl
Biomed. Signal Process. Control.
Yue Han, Qiu-Hua Lin, Li-Dan Kuang, Bin-Hua Zhao, Xiao-Feng Gong, Fengyu Cong, Yu-Ping Wang, Vince D. Calhoun
2024 Misc conf
ICASSP
Xin-Tong Liu, Xiao-Feng Gong, Dong Zhao, Qiu-Hua Lin
2024 Misc conf
ICASSP
Guozhao Liao, Xiao-Feng Gong, Qiu-Hua Lin
2023 conf
ICONIP (9)
Yue Han, Qiu-Hua Lin, Li-Dan Kuang, Ying-Guang Hao, Wei-Xing Li, Xiao-Feng Gong, Vince D. Calhoun
2022 J jnl
IEEE Trans. Medical Imaging
Yue Han, Qiu-Hua Lin, Li-Dan Kuang, Xiao-Feng Gong, Fengyu Cong, Yu-Ping Wang, Vince D. Calhoun
2022 J jnl
Signal Process.
Xiao-Feng Gong, Chen-Yu Xu, Rui-Xue Chen, Qiu-Hua Lin
2021 J jnl
CoRR
Lu-Ming Wang, Ya-Nan Wang, Xiao-Feng Gong, Qiu-Hua Lin, Fei Xiang
2021 Misc conf
ICASSP
Yue Han, Qiu-Hua Lin, Li-Dan Kuang, Xiao-Feng Gong, Fengyu Cong, Vince D. Calhoun
2020 J jnl
IEEE Trans. Medical Imaging
Li-Dan Kuang, Qiu-Hua Lin, Xiao-Feng Gong, Fengyu Cong, Yu-Ping Wang, Vince D. Calhoun
2019 conf
ISNN (1)
Jia-Xing Yang, Xiao-Feng Gong, Gui-Chen Yu
2019 conf
ISNN (2)
Jin-Wei Yang, Xiao-Feng Gong, Lu-Ming Wang, Qiu-Hua Lin
2019 conf
ISNN (2)
Yue Qiu, Qiu-Hua Lin, Li-Dan Kuang, Wenda Zhao, Xiao-Feng Gong, Fengyu Cong, Vince D. Calhoun
2019 J jnl
Signal Process. Image Commun.
Xiao-Feng Gong, Qiu-Hua Lin, Fengyu Cong, Lieven De Lathauwer
2019 J jnl
IEEE Access
Jin-Wei Yang, Xiao-Feng Gong, Chen-Yu Xu, Qiu-Hua Lin, Yougen Xu, Zhi-Wen Liu
2019 conf
ISNN (2)
Jia-Xing Yang, Xiao-Feng Gong, Hui Li, Yougen Xu, Zhiwen Liu
2019 conf
ISNN (2)
Gui-Chen Yu, Xiao-Feng Gong, Jia-Cheng Jiang, Zhiwen Liu, Yougen Xu
2018 J jnl
IEEE Access
Xiao-Feng Gong, Lei Mao, Yingliang Liu, Qiu-Hua Lin
2018 J jnl
IEEE Trans. Signal Process.
Xiao-Feng Gong, Qiu-Hua Lin, Fengyu Cong, Lieven De Lathauwer
2018 J jnl
IET Signal Process.
Xiao-Feng Gong, Jia-Cheng Jiang, Hui Li, Yougen Xu, Zhiwen Liu
2017 conf
ISNN (2)
Ce Zhang, Qiu-Hua Lin, Chao-Ying Zhang, Ying-Guang Hao, Xiao-Feng Gong, Fengyu Cong, Vince D. Calhoun
2017 conf
ISBI
Li-Dan Kuang, Qiu-Hua Lin, Xiao-Feng Gong, Yong-Gang Chen, Fengyu Cong, Vince D. Calhoun
2017 Misc conf
ICASSP
Li-Dan Kuang, Qiu-Hua Lin, Xiao-Feng Gong, Fengyu Cong, Vince D. Calhoun
2016 Misc conf
ICASSP
Li-Dan Kuang, Qiu-Hua Lin, Xiao-Feng Gong, Fengyu Cong, Vince D. Calhoun
2016 Misc conf
ICASSP
Xiao-Feng Gong, Qiu-Hua Lin, Otto Debals, Nico Vervliet, Lieven De Lathauwer
2015 conf
FSKD
Meijiao Ji, Xiao-Feng Gong, Qiu-Hua Lin
2015 J jnl
Int. J. Sens. Networks
Xiaoming Gou, Zhiwen Liu, Yougen Xu, Xiao-Feng Gong
2015 J jnl
IEEE Trans. Signal Process.
Xiao-Feng Gong, Xiulin Wang, Qiu-Hua Lin
2015 Misc conf
ICNC
Yingliang Liu, Xiao-Feng Gong, Qiu-Hua Lin
2014 conf
DSP
Xiulin Wang, Xiao-Feng Gong, Qiu-Hua Lin
2014 conf
ChinaSIP
Xiao-Feng Gong, Cheng-Yuan Wang, Ya-Na Hao, Qiu-Hua Lin
2013 J jnl
CoRR
Xiao-Feng Gong, Cheng-Yuan Wang, Ya-Na Hao, Qiu-Hua Lin
2013 conf
MLSP
Xiao-Feng Gong, Ya-Na Hao, Qiu-Hua Lin
2013 conf
ChinaSIP
Xiao-Feng Gong, Qiu-Hua Lin, Ke Wang
2013 conf
ChinaSIP
Li-Dan Kuang, Qiu-Hua Lin, Xiao-Feng Gong, Jing Fan, Fengyu Cong, Vince D. Calhoun
2012 conf
LVA/ICA
Ke Wang, Xiao-Feng Gong, Qiu-Hua Lin
2012 Misc conf
ICASSP
Xiao-Feng Gong, Ke Wang, Qiu-Hua Lin
2012 J jnl
Sensors
Xiao-Feng Gong, Ke Wang, Qiu-Hua Lin, Zhiwen Liu, Yougen Xu
2012 conf
iCAST
Long Li, Qiu-Hua Lin, Xiao-Feng Gong
2011 Misc conf
ICNC
Jian-Gang Lin, Qiu-Hua Lin, Xiao-Feng Gong
2011 conf
iCAST
Xirui Zhang, Zhiwen Liu, Yougen Xu, Xiao-Feng Gong
2011 conf
iCAST
Xiaoming Gou, Yougen Xu, Zhiwen Liu, Xiao-Feng Gong
2011 J jnl
IEEE Trans. Aerosp. Electron. Syst.
Xiao-Feng Gong, Zhiwen Liu, Yougen Xu
2011 J jnl
Signal Process.
Xiao-Feng Gong, Zhiwen Liu, Yougen Xu
2011 conf
MLSP
Qiu-Hua Lin, Jia-Cheng Wang, Xiao-Feng Gong, Jian-Lin Wu, Jun-Yu Chen, Vince D. Calhoun
2011 Misc conf
ICNC
Xiao-Feng Gong, Qiu-Hua Lin
2010 conf
LVA/ICA
Qiu-Hua Lin, Li-Dan Wang, Jian-Gang Lin, Xiao-Feng Gong
2010 conf
LVA/ICA
Xiao-Feng Gong, Qiu-Hua Lin
2009 J jnl
Signal Process.
Xiao-Feng Gong, Zhiwen Liu, Yougen Xu, Muhammad Ishtiaq Ahmad
2008 J jnl
EURASIP J. Adv. Signal Process.
Xiao-Feng Gong, Zhiwen Liu, Yougen Xu
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