Vaskar Raychoudhury

78 papers A* 2B 11C 6Misc 10Journal 31Unranked 18
YearRankTypeTitle / Venue / Authors
2025 B conf
MASS
Asm Mobarak Hossain, Nadim Mahmud, Ethan Han, Neil Advani, Bibodh Baral, Md. Osman Gani, Vaskar Raychoudhury
2025 J jnl
CoRR
Hanna M. Noyce, Emily M. Olejniczak, Vaskar Raychoudhury, Roger O. Smith, Md. Osman Gani
2025 J jnl
CoRR
Siddhant Karki, Ethan Han, Nadim Mahmud, Suman Bhunia, John Femiani, Vaskar Raychoudhury
2024 J jnl
SN Comput. Sci.
Vihaan Misra, Shivashankar S. Menon, Snehanshu Saha, Archana Mathur, Haoxiang Yu, Vaskar Raychoudhury
2024 J jnl
IEEE Trans. Emerg. Top. Comput.
Aditi Seetha, Satyendra Singh Chouhan, Emmanuel S. Pilli, Vaskar Raychoudhury
2024 B conf
IJCNN
Ashman Mehra, Snehanshu Saha, Vaskar Raychoudhury, Archana Mathur
2024 J jnl
IEEE Trans. Comput. Soc. Syst.
Aditi Seetha, Satyendra Singh Chouhan, Emmanuel S. Pilli, Vaskar Raychoudhury, Snehanshu Saha
2024 B conf
COMPSAC
Rochishnu Banerjee, Ethan Han, Longze Li, Haoxiang Yu, Md. Osman Gani, Vaskar Raychoudhury, Roger O. Smith
2024 J jnl
IEEE Trans. Intell. Transp. Syst.
Ashman Mehra, Divyanshu Singh, Vaskar Raychoudhury, Archana Mathur, Snehanshu Saha
2024 conf
ECML/PKDD (9)
Alfiya M. Shaikh, Hrithik Nambiar, Kshitish Ghate, Swarnali Banik, Sougata Sen, Surjya Ghosh, Vaskar Raychoudhury, Niloy Ganguly, Snehanshu Saha
2023 J jnl
Inf. Process. Manag.
Jitendra Parmar, Satyendra Singh Chouhan, Vaskar Raychoudhury
2023 J jnl
IEEE Trans. Artif. Intell.
Haoxiang Yu, Vaskar Raychoudhury, Snehanshu Saha, Janick Edinger, Roger O. Smith, Md. Osman Gani
2023 J jnl
CoRR
Ashman Mehra, Snehanshu Saha, Vaskar Raychoudhury, Archana Mathur
2023 conf
MobiQuitous (2)
Thomas Nguyen, Md Fourkanul Islam, Rochishnu Banerjee, Hanna M. Noyce, Emily M. Olejniczak, Roger O. Smith, Md. Osman Gani, Vaskar Raychoudhury
2023 J jnl
ACM Comput. Surv.
Jitendra Parmar, Satyendra Singh Chouhan, Vaskar Raychoudhury, Santosh Singh Rathore
2022 J jnl
IEEE Trans. Intell. Transp. Syst.
Aishwarya Manjunath, Vaskar Raychoudhury, Snehanshu Saha, Saibal Kar, Anusha Kamath
2022 Misc conf
PAAMS
John Hata, Haoxiang Yu, Vaskar Raychoudhury, Snehanshu Saha, Huy Tran Quang
2022 conf
MSN
Rochishnu Banerjee, Md Fourkanul Islam, Shaswati Saha, Vaskar Raychoudhury, Md. Osman Gani
2021 B conf
COMPSAC
Valeria Mokrenko, Haoxiang Yu, Vaskar Raychoudhury, Janick Edinger, Roger O. Smith, Md. Osman Gani
2021 C conf
MobiQuitous
Haoxiang Yu, Vaskar Raychoudhury, Snehanshu Saha
2020 B conf
MASS
Shrawani Silwal, Vaskar Raychoudhury, Snehanshu Saha, Md. Osman Gani
2020 Misc conf
COMSNETS
Aishwarya Manjunath, Vaskar Raychoudhury, Snehanshu Saha
2020 conf
PerCom Workshops
Biplav Srivastava, Sandeep Singh Sandha, Vaskar Raychoudhury, Sukanya Randhawa, Viral Kapoor, Anmol Agrawal
2020 Misc conf
ICDCN
Haoxiang Yu, Vaskar Raychoudhury, Shrawani Silwal
2020 J jnl
Int. J. Commun. Syst.
Ankush Mishra, Snehanshu Saha, Simran Makhija, Sumana Sinha, Vaskar Raychoudhury, Sobin C. C.
2020 B conf
MASS
Divya Saxena, Vaskar Raychoudhury
2019 B conf
SMARTCOMP
Shrawani Silwal, Md. Osman Gani, Vaskar Raychoudhury
2019 Misc conf
HotMobile
John Hata, Md. Osman Gani, Vaskar Raychoudhury
2019 J jnl
IEEE Trans. Syst. Man Cybern. Syst.
Divya Saxena, Vaskar Raychoudhury
2019 conf
Q2SWinet
Nicholas Jarvis, John Hata, Nicholas Wayne, Vaskar Raychoudhury, Md. Osman Gani
2019 Misc conf
ICDCN
Divya Saxena, Suyash Mahar, Vaskar Raychoudhury, Jiannong Cao
2019 conf
BuildSys
Md. Osman Gani, Vaskar Raychoudhury, Janick Edinger, Valeria Mokrenko, Zheng Cao, Ce Zhang
2019 conf
PerCom Workshops
Janick Edinger, Alexandra Hofmann, Anton Wachner, Christian Becker, Vaskar Raychoudhury, Christian Krupitzer
2019 conf
PerCom Workshops
Manh Nguyen, Md. Osman Gani, Vaskar Raychoudhury
2018 J jnl
Int. J. Commun. Syst.
Sobin C. C., Vaskar Raychoudhury, Snehanshu Saha
2018 conf
ITSC
Anmol Agrawal, Vaskar Raychoudhury, Divya Saxena, Ajay D. Kshemkalyani
2018 conf
PerCom Workshops
Viral Kapoor, Divya Saxena, Vaskar Raychoudhury, Sandeep Kumar
2018 conf
ITSC
Kanika Bathla, Vaskar Raychoudhury, Divya Saxena, Ajay D. Kshemkalyani
2017 Misc conf
ICDCN
Sobin C. C., Vaskar Raychoudhury, Snehanshu Saha
2017 J jnl
Wirel. Pers. Commun.
Sobin C. C., Vaskar Raychoudhury, Snehanshu Saha
2017 Misc conf
ICDCN
Divya Saxena, Vaskar Raychoudhury, Christian Becker
2017 A* conf
PerCom
Janick Edinger, Dominik Schäfer, Christian Krupitzer, Vaskar Raychoudhury, Christian Becker
2017 Misc conf
ICDCN
Divya Saxena, Vaskar Raychoudhury, Christian Becker
2017 J jnl
J. Netw. Comput. Appl.
Tarun Kulshrestha, Divya Saxena, Rajdeep Niyogi, Vaskar Raychoudhury, Manoj Misra
2016 J jnl
J. Netw. Comput. Appl.
Sobin C. C., Vaskar Raychoudhury, Gustavo Marfia, Ankita Singla
2016 J jnl
CoRR
Biplav Srivastava, Sandeep Singh Sandha, Vaskar Raychoudhury, Sukanya Randhawa, Viral Kapoor, Anmol Agrawal
2016 J jnl
CoRR
Sobin C. C., Snehanshu Saha, Vaskar Raychoudhury, Hategekimana Fidele, Sumana Sinha
2016 J jnl
J. Netw. Comput. Appl.
Divya Saxena, Vaskar Raychoudhury
2016 J jnl
Comput. Sci. Rev.
Divya Saxena, Vaskar Raychoudhury, Neeraj Suri, Christian Becker, Jiannong Cao
2016 J jnl
J. Netw. Comput. Appl.
Divya Saxena, Vaskar Raychoudhury
2016 conf
CSE/EUC/DCABES
Divya Saxena, Vaskar Raychoudhury, Christian Becker, Neeraj Suri
2015 B conf
IWQoS
Weiping Zhu, Yi Hong, Vaskar Raychoudhury, Run Zhao, Dong Wang
2015 B conf
MASS
Weiping Zhu, Yi Hong, Vaskar Raychoudhury, Run Zhao, Dong Wang
2015 J jnl
IEEE Trans. Parallel Distributed Syst.
Vaskar Raychoudhury, Shikhar Shrivastav, Sandeep Singh Sandha, Jiannong Cao
2015 Misc conf
COMSNETS
Vaskar Raychoudhury, Divya Saxena, Mayank Chaudhary, Shivam Mangla
2014 J jnl
IEEE Trans. Parallel Distributed Syst.
Vaskar Raychoudhury, Ajay D. Kshemkalyani, Daqing Zhang, Jiannong Cao
2014 J jnl
IEEE Trans. Computers
Weiping Zhu, Jiannong Cao, Henry C. B. Chan, Xuefeng Liu, Vaskar Raychoudhury
2014 C conf
Healthcom
Preetika Rani, Vaskar Raychoudhury, Sandeep Singh Sandha, Dhaval Patel
2014 J jnl
CoRR
Deepak Uniyal, Vaskar Raychoudhury
2014 J jnl
Pervasive Mob. Comput.
Vaskar Raychoudhury, Jiannong Cao, Rajdeep Niyogi, Weigang Wu, Yi Lai
2014 C conf
PACLIC
Harsh Jhamtani, Suleep Kumar Bhogi, Vaskar Raychoudhury
2013 J jnl
Comput. J.
Daqiang Zhang, Zhijun Yang, Vaskar Raychoudhury, Zhe Chen, Jaime Lloret
2013 conf
SocialCom
Vaskar Raychoudhury, Ajay D. Kshemkalyani, Daqing Zhang, Jiannong Cao, Mohit Bakshi, Kanik Gupta, Vishal Mittal, Siddharth Maheshwari
2013 J jnl
Pervasive Mob. Comput.
Vaskar Raychoudhury, Jiannong Cao, Mohan Kumar, Daqiang Zhang
2013 J jnl
CoRR
Daqiang Zhang, Rongbo Zhu, Shuqiqiu Men, Vaskar Raychoudhury
2012 C conf
PDP
Vaskar Raychoudhury, Jiannong Cao, Weiping Zhu, Ajay D. Kshemkalyani
2011 conf
SocialCom/PASSAT
Daqing Zhang, Zhu Wang, Bin Guo, Xingshe Zhou, Vaskar Raychoudhury
2011 conf
ICC
Weiping Zhu, Jiannong Cao, Yi Xu, Vaskar Raychoudhury
2011 J jnl
Pervasive Mob. Comput.
Vaskar Raychoudhury, Jiannong Cao, Weigang Wu, Yi Lai, Canfeng Chen, Jian Ma
2011 conf
MidSens
Vaskar Raychoudhury, Ajay D. Kshemkalyani, Jiannong Cao
2011 C conf
PDP
Vaskar Raychoudhury, Jiannong Cao, Weigang Wu, Canfeng Chen
2010 Misc conf
ICDCN
Vaskar Raychoudhury, Jiannong Cao, Weigang Wu, Yi Lai, Canfeng Chen, Jian Ma
2009 B conf
ICPP
Daqiang Zhang, Jiannong Cao, Jingyu Zhou, Minyi Guo, Vaskar Raychoudhury
2009 A* conf
PerCom
Vaskar Raychoudhury
2008 B conf
ICCCN
Vaskar Raychoudhury, Jiannong Cao, Weigang Wu
2007 conf
ICDCS Workshops
Yu Zhou, Jiannong Cao, Vaskar Raychoudhury, Joanna Siebert, Jian Lu
2007 conf
SKG
Miaomiao Wang, Jiannong Cao, Joanna Izabela Siebert, Vaskar Raychoudhury, Jing Li
2007 C conf
EUC
Joanna Izabela Siebert, Jiannong Cao, Yu Zhou, Miaomiao Wang, Vaskar Raychoudhury
redb/extractors/decompiler/DecompileAPK.py
← Index redb/extractors/decompiler/DecompileAPK.py python
"""APK Code Analysis Extractor.

Decompiles and disassembles APK DEX bytecode at the method level,
producing per-method content and reference records analogous to
the Binary Ninja code_binja_* tables.

Uses androguard + JADX + apktool to replicate Binary Ninja analysis
depth for Android applications.
"""

import gc
import hashlib
import inspect
import logging
import os
import threading
import time
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor


class DecompileAPK(Extractor):
    """APK code analysis extractor — produces multi-table ClickHouse export.

    Follows the same pattern as DecompileBinja for consistency.
    """

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        known_benign=False,
        known_malicious=False,
        filetype=None,
        decompile_modules=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            known_benign=known_benign,
            known_malicious=known_malicious,
        )
        self.log.debug(inspect.currentframe().f_code.co_name)
        self.analysis_results = None
        self.analyzer = None
        self.filetype = filetype or "apk"
        self.decompile_modules = decompile_modules or {"all"}

        try:
            self.APK_DECOMPILE_TIMEOUT = int(
                os.getenv("APK_DECOMPILE_TIMEOUT", "600")
            )
        except ValueError:
            self.log.warning(
                "Invalid APK_DECOMPILE_TIMEOUT value, using default of 600 seconds"
            )
            self.APK_DECOMPILE_TIMEOUT = 600

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup_run()

    def calculate_md5(self, input_str):
        """Calculate MD5 hash of a string."""
        return hashlib.md5(input_str.encode("utf-8")).hexdigest()

    def cleanup_run(self):
        """Clean up after analysis."""
        try:
            if self.analyzer:
                self.analyzer.cleanup()
                self.analyzer = None
            gc.collect()
        except Exception as e:
            self.log.error(f"Error in cleanup: {e}")

    def analyze_apk(self) -> Optional[Dict[str, Any]]:
        """Run APK code analysis and return results."""
        self.log.debug("Starting APK code analysis")
        try:
            self.analyzer = APKCodeAnalyzer(
                filepath=self.filepath,
                timeout=self.APK_DECOMPILE_TIMEOUT,
                log=self.log,
                decompile_modules=self.decompile_modules,
            )
            results = self.analyzer.extract()
            return results
        except Exception as e:
            self.log.error(f"Error in APK code analysis: {e}")
            import traceback
            self.log.error(f"Traceback: {traceback.format_exc()}")
            return None
        finally:
            self.cleanup_run()

    def extract(self):
        """Extract and process all analysis results.

        Uses daemon thread with timeout, same pattern as DecompileBinja.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        extraction_completed = False
        extraction_result = False
        extraction_error = None

        def do_extraction():
            nonlocal extraction_completed, extraction_result, extraction_error
            try:
                results = self.analyze_apk()
                if not results:
                    extraction_result = False
                else:
                    self.analysis_results = results
                    self.analysis_results["sha256"] = self.sha256
                    self.analysis_results["sha1"] = self.sha1
                    self.analysis_results["md5"] = self.md5
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        extraction_thread = threading.Thread(target=do_extraction)
        extraction_thread.daemon = True
        extraction_thread.start()

        start_time = time.time()
        while (
            not extraction_completed
            and (time.time() - start_time) < self.APK_DECOMPILE_TIMEOUT
        ):
            time.sleep(1)

        if not extraction_completed:
            self.log.error(
                f"APK extraction timed out after {self.APK_DECOMPILE_TIMEOUT} seconds"
            )
            self.cleanup_run()
            return None

        if extraction_error:
            self.log.error(f"Error in APK extraction: {extraction_error}")
            return None

        return self.analysis_results if extraction_result else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        """Prepare data for database export."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        if not self.analysis_results:
            return None

        if exporter_type == "ClickHouseExporter":
            now = datetime.now(timezone.utc)
            export = {"multi_table": True}

            # Table 1: Decompiled method content
            if self.analysis_results.get("decompiled_content"):
                export["decompiled_content"] = {
                    "table": "code_apk_decompiled_methods_content",
                    "data": [
                        [
                            f["decompiled_method_hash"],
                            f["decompiled_method"],
                            f.get("decompiled_method_type", "UNKNOWN"),
                            1 if f.get("decompiled_has_string_encryption") else 0,
                            1 if f.get("decompiled_has_reflection_calls") else 0,
                            1 if f.get("decompiled_excessive_goto_count") else 0,
                            now,
                        ]
                        for f in self.analysis_results["decompiled_content"]
                    ],
                    "column_names": [
                        "decompiled_method_hash",
                        "decompiled_method",
                        "decompiled_method_type",
                        "decompiled_has_string_encryption",
                        "decompiled_has_reflection_calls",
                        "decompiled_excessive_goto_count",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 2: Decompiled method references
            if self.analysis_results.get("decompiled_refs"):
                export["decompiled_refs"] = {
                    "table": "code_apk_decompiled_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["decompiled_method_hash"],
                            f.get("smali_method_hash"),
                            f.get("decompiled_class_name", ""),
                            f.get("decompiled_method_name", ""),
                            f.get("decompiled_method_signature", ""),
                            f.get("decompiled_method_prototype", ""),
                            f.get("functions_caller", []),
                            f.get("functions_call", []),
                            now,
                        ]
                        for f in self.analysis_results["decompiled_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "decompiled_method_hash",
                        "smali_method_hash",
                        "decompiled_class_name",
                        "decompiled_method_name",
                        "decompiled_method_signature",
                        "decompiled_method_prototype",
                        "functions_caller",
                        "functions_call",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "String",
                        "Array(String)",
                        "Array(String)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 3: Smali method content
            if self.analysis_results.get("smali_content"):
                export["smali_content"] = {
                    "table": "code_apk_smali_methods_content",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f["smali_method"],
                            f.get("smali_method_type", "UNKNOWN"),
                            f.get("smali_instructions_count", 0),
                            f.get("smali_register_count", 0),
                            1 if f.get("smali_has_string_encryption") else 0,
                            1 if f.get("smali_has_reflection_calls") else 0,
                            1 if f.get("smali_excessive_goto_count") else 0,
                            f.get("smali_flattened_score", 0.0),
                            f.get("smali_mba_score", 0.0),
                            now,
                        ]
                        for f in self.analysis_results["smali_content"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "smali_method",
                        "smali_method_type",
                        "smali_instructions_count",
                        "smali_register_count",
                        "smali_has_string_encryption",
                        "smali_has_reflection_calls",
                        "smali_excessive_goto_count",
                        "smali_flattened_score",
                        "smali_mba_score",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt32",
                        "UInt16",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "Float64",
                        "Float64",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 4: Smali method references
            if self.analysis_results.get("smali_refs"):
                export["smali_refs"] = {
                    "table": "code_apk_smali_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["smali_method_hash"],
                            f.get("decompiled_method_hash"),
                            f.get("smali_class_name", ""),
                            f.get("smali_method_name", ""),
                            f.get("smali_method_signature", ""),
                            now,
                        ]
                        for f in self.analysis_results["smali_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "smali_method_hash",
                        "decompiled_method_hash",
                        "smali_class_name",
                        "smali_method_name",
                        "smali_method_signature",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5: Method similarity metrics (content-based fuzzy matching)
            if self.analysis_results.get("similarity_metrics"):
                export["method_similarity_metrics"] = {
                    "table": "code_apk_method_similarity_metrics",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f.get("ssdeep_smali"),
                            f.get("tlsh_smali"),
                            f.get("ssdeep_smali_normalized"),
                            f.get("tlsh_smali_normalized"),
                            f.get("minhash", []),
                            now,
                        ]
                        for f in self.analysis_results["similarity_metrics"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "ssdeep_smali",
                        "tlsh_smali",
                        "ssdeep_smali_normalized",
                        "tlsh_smali_normalized",
                        "minhash",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5b: CFG method features (structural/topological)
            if self.analysis_results.get("cfg"):
                export["cfg_methods"] = {
                    "table": "code_apk_cfg_methods",
                    "data": [
                        [
                            cfg["smali_method_hash"],
                            cfg["cfg_topology_hash"],
                            cfg["block_count"],
                            cfg["edge_count"],
                            cfg.get("cfg_instructions_count", 0),
                            cfg.get("call_count", 0),
                            cfg["cyclomatic_complexity"],
                            cfg.get("loop_count", 0),
                            cfg.get("max_depth", 0),
                            cfg.get("max_fan_out", 0),
                            cfg.get("md_index_topdown", 0),
                            cfg.get("md_index_bottomup", 0),
                            cfg.get("prime_product_smali", 0),
                            cfg.get("cfg_feature_tlsh"),
                            cfg.get("wl_minhash", []),
                            cfg.get("bb_features", []),
                            cfg.get("cfg_adjacency", []),
                            now,
                        ]
                        for cfg in self.analysis_results["cfg"]
                        if cfg is not None
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "cfg_topology_hash",
                        "block_count",
                        "edge_count",
                        "cfg_instructions_count",
                        "call_count",
                        "cyclomatic_complexity",
                        "loop_count",
                        "max_depth",
                        "max_fan_out",
                        "md_index_topdown",
                        "md_index_bottomup",
                        "prime_product_smali",
                        "cfg_feature_tlsh",
                        "wl_minhash",
                        "bb_features",
                        "cfg_adjacency",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(16)",
                        "UInt16",
                        "UInt16",
                        "UInt32",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt64",
                        "UInt64",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(Array(UInt16))",
                        "Array(UInt32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 6: Strings — reuse code_binja_strings_raw for cross-format correlation
            # DEX strings are MUTF-8; string_raw = string since no encoding difference
            if self.analysis_results.get("strings"):
                export["strings_raw"] = {
                    "table": "code_binja_strings_raw",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            s["string"],
                            s["string"],  # string_raw = string (MUTF-8 decoded to UTF-8)
                            s.get("string_encoding", "UTF8"),
                            s.get("string_offset", 0),
                            s.get("string_length", len(s["string"])),
                            s.get("string_length", len(s["string"])),  # string_raw_length = string_length
                            s.get("string_entropy", 0.0),
                        ]
                        for s in self.analysis_results["strings"]
                    ],
                    "column_names": [
                        "sha256",
                        "string",
                        "string_raw",
                        "string_encoding",
                        "string_offset",
                        "string_length",
                        "string_raw_length",
                        "string_entropy",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "LowCardinality(String)",
                        "UInt64",
                        "UInt32",
                        "UInt32",
                        "Float32",
                    ],
                }

            # Table 7: Analysis errors
            if self.analysis_results.get("analysis_errors"):
                export["analysis_errors"] = {
                    "table": "code_apk_analysis_errors",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f.get("class_name"),
                            f.get("method_name"),
                            f.get("error_location", "unknown"),
                            f.get("error_message", ""),
                            f.get("error_type", "unknown"),
                            self.calculate_md5(
                                f"{f.get('error_message', '')}"
                                f"{f.get('class_name', '')}"
                                f"{f.get('method_name', '')}"
                                f"{f.get('error_location', 'unknown')}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results["analysis_errors"]
                    ],
                    "column_names": [
                        "sha256",
                        "class_name",
                        "method_name",
                        "error_location",
                        "error_message",
                        "error_type",
                        "error_hash",
                        "status",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "LowCardinality(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "FixedString(32)",
                        "Enum8('new'=1, 'investigating'=2, 'fixed'=3, 'wontfix'=4)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            return export

        return None

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.APK_DECOMPILED.value

    def get_clickhouse_table(self) -> str:
        """Not used directly as we're handling multiple tables."""
        pass