Nan Qi

75 papers B 5C 1Journal 58Unranked 11
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Wirel. Commun.
Wei Li, Jian Wu, Yingwu Chen, Luliang Jia, Lijian Sun, Quan Chen, Jungang Yan, Nan Qi
2026 J jnl
IEEE Trans. Mob. Comput.
Xiaojie Li, Zhijie Cai, Nan Qi, Chao Dong, Guangxu Zhu, Haixia Ma, Qihui Wu, Shi Jin
2026 J jnl
IEEE Commun. Lett.
Boya Li, Luliang Jia, Lin Zhang, Nan Qi, Wanbin Tang, Fumiyuki Adachi
2026 J jnl
IEEE Internet Things J.
Hongyu Zhou, Luliang Jia, Feihuang Chu, Nan Qi, Lin Zhang
2025 J jnl
CoRR
Xiaojie Li, Zhijie Cai, Nan Qi, Chao Dong, Guangxu Zhu, Haixia Ma, Qihui Wu, Shi Jin
2025 J jnl
IEEE Internet Things J.
Wei Li, Luliang Jia, Yingwu Chen, Quan Chen, Jungang Yan, Nan Qi
2025 J jnl
CoRR
Nan Qi, Haoxuan Liu, Theodoros A. Tsiftsis, Alexandros-Apostolos A. Boulogeorgos, Fuhui Zhou, Shi Jin, Qihui Wu
2025 J jnl
CoRR
Xueyu Kang, Nan Qi, Lu Lv, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Hongwu Liu
2025 J jnl
IEEE Trans. Veh. Technol.
Xueyu Kang, Nan Qi, Lu Lv, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Hongwu Liu
2025 J jnl
IEEE Commun. Surv. Tutorials
Luliang Jia, Nan Qi, Zhe Su, Feihuang Chu, Shengliang Fang, Kai-Kit Wong, Chan-Byoung Chae
2025 J jnl
IEEE Internet Things J.
Nan Qi, Shuqi Wang, Daolong Wu, Lei Zhang, Luliang Jia, Chang Tian, Ming Zhan
2025 B conf
WCNC
Haoxuan Liu, Nan Qi, Xiaojie Li, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Ming Xiao, Juha Röning
2025 B conf
WCNC
Xiaojie Li, Hang Li, Xiaoyang Li, Guangxu Zhu, Nan Qi, Ming Xiao
2025 conf
VTC2025-Spring
Wen-Jing Wang, Jinguo Zhang, Shutian Li, Tao Zhang, Nan Qi
2024 J jnl
IEEE Trans. Veh. Technol.
Nan Qi, Zhe Su, Wen-Jing Wang, Rugui Yao, Theodoros A. Tsiftsis
2024 J jnl
IEEE Wirel. Commun. Lett.
Yifan Du, Nan Qi, Xiaojie Li, Ming Xiao, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Qihui Wu
2024 J jnl
IET Commun.
Yifan Du, Nan Qi, Kewei Wang, Ming Xiao, Wenjing Wang
2024 J jnl
Phys. Commun.
Haoxuan Liu, Nan Qi, Kewei Wang, Theodoros A. Tsiftsis, Wenjing Wang, Yawen Liu
2024 J jnl
IEEE Trans. Wirel. Commun.
Xiaojie Li, Songyang Zhang, Hang Li, Xiaoyang Li, Lexi Xu, Haigao Xu, Hui Mei, Guangxu Zhu, Nan Qi, Ming Xiao
2024 J jnl
CoRR
Xiaojie Li, Songyang Zhang, Hang Li, Xiaoyang Li, Lexi Xu, Haigao Xu, Hui Mei, Guangxu Zhu, Nan Qi, Ming Xiao
2024 J jnl
IEEE Wirel. Commun. Lett.
Kewei Wang, Nan Qi, Haoxuan Liu, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Ming Xiao, Kai-Kit Wong
2024 J jnl
IEEE Trans. Mob. Comput.
Xiaozhen Lu, Liang Xiao, Yilin Xiao, Wei Wang, Nan Qi, Qian Wang
2024 B conf
PIMRC
Vasileios Kouvakis, Stylianos E. Trevlakis, Alexandros-Apostolos A. Boulogeorgos, Theodoros A. Tsiftsis, Keshav Singh, Nan Qi
2023 J jnl
IEEE Trans. Mob. Comput.
Nan Qi, Zanqi Huang, Fuhui Zhou, Qingjiang Shi, Qihui Wu, Ming Xiao
2023 J jnl
IET Commun.
Peijie Yan, Feihuang Chu, Luliang Jia, Nan Qi
2023 J jnl
Digit. Commun. Networks
Yunpeng Zhang, Luliang Jia, Nan Qi, Yifan Xu, Meng Wang
2023 J jnl
IEEE Trans. Mob. Comput.
Nan Qi, Zanqi Huang, Wen Sun, Shi Jin, Xiang Su
2023 J jnl
IEEE Open J. Commun. Soc.
Yeting Huang, Nan Qi, Zanqi Huang, Luliang Jia, Qihui Wu, Rugui Yao, Wen-Jing Wang
2023 C conf
ICCC
Kewei Wang, Nan Qi, Ming Xiao, Sha Hu, Bjorn Sihlbom
2023 J jnl
IET Commun.
Rugui Yao, Yongsong Yu, Peng Wang, Ye Fan, Xudong Li, Xiaoya Zuo, Nan Qi, Nikolaos I. Miridakis, Theodoros A. Tsiftsis
2023 J jnl
IEEE Trans. Veh. Technol.
Runfeng Chen, Jin Chen, Haichao Wang, Xiaobing Tong, Yifan Xu, Nan Qi, Yuhua Xu
2023 J jnl
IEEE Commun. Lett.
Yijia Liu, Nan Qi, Zhibo Pang, Xinyu Zhang, Qihui Wu, Shi Jin, Kai-Kit Wong
2023 J jnl
IEEE Syst. J.
Kewei Wang, Nan Qi, Xin Guan, Qingjiang Shi, Ming Xiao, Shi Jin, Kai-Kit Wong
2022 J jnl
IET Commun.
Peijie Yan, Feihuang Chu, Luliang Jia, Nan Qi
2022 J jnl
IET Commun.
Zhe Su, Qihui Wu, Nan Qi, Luliang Jia, Zhiyong Du
2022 J jnl
IEEE Open J. Commun. Soc.
Wei Wang, Nan Qi, Luliang Jia, Chunguo Li, Theodoros A. Tsiftsis, Mei Wang
2022 J jnl
IEEE Commun. Mag.
Luliang Jia, Nan Qi, Feihuang Chu, Shengliang Fang, Ximing Wang, Shuli Ma, Shuo Feng
2022 J jnl
CoRR
Luliang Jia, Nan Qi, Feihuang Chu, Shengliang Fang, Ximing Wang, Shuli Ma, Shuo Feng
2022 J jnl
IEEE Trans. Mob. Comput.
Jiaxin Chen, Ping Chen, Yuhua Xu, Nan Qi, Tao Fang, Chao Dong, Qihui Wu
2022 J jnl
IEEE Internet Things J.
Qihui Wu, Jiaxin Chen, Yuhua Xu, Nan Qi, Tao Fang, Youming Sun, Luliang Jia
2022 conf
ICSPCC
Wanying Su, Rugui Yao, Ye Fan, Yi Xie, Nan Qi, Xiaoya Zuo
2022 J jnl
IEEE Trans. Veh. Technol.
Xudong Li, Ye Fan, Rugui Yao, Peng Wang, Nan Qi, Nikolaos I. Miridakis, Theodoros A. Tsiftsis
2022 conf
VTC Spring
Wen-Jing Wang, Yige Yan, Long Chen, Li Zhen, Nan Qi
2022 J jnl
IEEE Wirel. Commun. Lett.
Xudong Li, Rugui Yao, Ye Fan, Peng Wang, Nan Qi, Nikolaos I. Miridakis, Theodoros A. Tsiftsis
2022 conf
VTC Fall
Wen-Jing Wang, Ziyang Du, Sha Li, Guangyue Lu, Long Chen, Nan Qi
2022 B conf
GLOBECOM
Nan Qi, Yeting Huang, Wen Sun, Shi Jin, Theodoros A. Tsiftsis, Qihui Wu, Xiang Su
2021 J jnl
IEEE Trans. Veh. Technol.
Nan Qi, Wei Wang, Ming Xiao, Luliang Jia, Shi Jin, Qiuming Zhu, Theodoros A. Tsiftsis
2021 J jnl
IEEE Wirel. Commun. Lett.
Jiaxin Chen, Qihui Wu, Yuhua Xu, Nan Qi, Tao Fang, Luliang Jia, Chao Dong
2021 J jnl
IET Commun.
Yunpeng Zhang, Luliang Jia, Nan Qi, Yifan Xu, Xueqiang Chen
2021 J jnl
CoRR
Yueyue Su, Nan Qi, Zanqi Huang, Rugui Yao, Luliang Jia
2021 B conf
IWCMC
Rugui Yao, Qiannan Qin, Shengyao Wang, Nan Qi, Ye Fan, Xiaoya Zuo
2021 J jnl
IEEE Trans. Wirel. Commun.
Jiaxin Chen, Qihui Wu, Yuhua Xu, Nan Qi, Xin Guan, Yuli Zhang, Zhen Xue
2021 J jnl
IEEE Wirel. Commun.
Jiaxin Chen, Qihui Wu, Yuhua Xu, Nan Qi, Tao Fang, Dianxiong Liu
2021 J jnl
IEEE Trans. Commun.
Nan Qi, Wei Wang, Fuhui Zhou, Luliang Jia, Qihui Wu, Shi Jin, Ming Xiao
2020 J jnl
IEEE Access
Rugui Yao, Yuan Zhang, Qihong Wu, Theodoros A. Tsiftsis, Nan Qi, Xiaoya Zuo, Shuxia Guo
2020 conf
VTC Fall
Qiannan Qin, Rugui Yao, Yuxin Zhang, Nan Qi, Xiaoya Zuo
2020 J jnl
IEEE Access
Nan Qi, Mei Wang, Wen-Jing Wang, Theodoros A. Tsiftsis, Rugui Yao, Guanghua Yang
2020 conf
VTC Fall
Nan Qi, Mei Wang, Wei Wang, Wen-Jing Wang, Theodoros A. Tsiftsis, Rugui Yao, Guanghua Yang
2020 J jnl
IEEE Wirel. Commun. Lett.
Shengyao Wang, Rugui Yao, Theodoros A. Tsiftsis, Nikolaos I. Miridakis, Nan Qi
2020 J jnl
IEEE Trans. Commun.
Nan Qi, Nikolaos I. Miridakis, Ming Xiao, Theodoros A. Tsiftsis, Rugui Yao, Shi Jin
2020 conf
WCSP
Rugui Yao, Doudou Song, Lukun Yao, Theodoros A. Tsiftsis, Nikolaos I. Miridakis, Nan Qi, Xiaoya Zuo, Danian Lou
2019 conf
PACRIM
Rugui Yao, Shengyao Wang, Xiaoya Zuo, Juan Xu, Nan Qi
2019 J jnl
IEEE Wirel. Commun. Lett.
Rugui Yao, Yuxin Zhang, Shengyao Wang, Nan Qi, Nikolaos I. Miridakis, Theodoros A. Tsiftsis
2019 J jnl
IEEE Trans. Veh. Technol.
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Rugui Yao, Shahid Mumtaz
2019 J jnl
IEEE Trans. Veh. Technol.
Jiaxin Chen, Yuhua Xu, Qihui Wu, Yuli Zhang, Xueqiang Chen, Nan Qi
2019 conf
WCNC Workshops
Nan Qi, Nikolaos I. Miridakis, Theodoros A. Tsiftsis, Rugui Yao
2019 J jnl
CoRR
Nan Qi, Nikolaos I. Miridakis, Ming Xiao, Theodoros A. Tsiftsis, Rugui Yao, Shi Jin
2018 J jnl
IEEE Access
Rugui Yao, Yanan Lu, Theodoros A. Tsiftsis, Nan Qi, Tamer Mekkawy, Fei Xu
2018 J jnl
IEEE Trans. Veh. Technol.
Tamer Mekkawy, Rugui Yao, Nan Qi, Yanan Lu
2017 J jnl
IEEE Trans. Wirel. Commun.
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Lin Zhang, Mikael Skoglund, Huisheng Zhang
2017 conf
ICC
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Lin Zhang, Mikael Skoglund, Huisheng Zhang
2016 J jnl
CoRR
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Mikael Skoglund, Huisheng Zhang
2016 J jnl
CoRR
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Mikael Skoglund, Phuong Le Cao, Lixin Li
2016 J jnl
IEEE Trans. Commun.
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Mikael Skoglund, Phuong Le Cao, Lixin Li
2016 conf
ICT
Nan Qi, Ming Xiao, Theodoros A. Tsiftsis, Phuong Le Cao, Mikael Skoglund, Lixin Li
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