Weiqiang Kong

67 papers B 2C 13Misc 2Journal 31Unranked 19
YearRankTypeTitle / Venue / Authors
2026 J jnl
Pattern Anal. Appl.
Anjum Iqbal, Weiqiang Kong, Yasir Iqbal
2026 J jnl
Neurocomputing
Anjum Iqbal, Weiqiang Kong, Yasir Iqbal, Maozhen Zhang, Ijaz Hussain
2026 J jnl
CoRR
Dali Chang, Chong Zhang, Kaiqi Zhang, Mingguan Yang, Huiyuan Li, Weiqiang Kong
2025 J jnl
Eng. Appl. Artif. Intell.
Abdelkarim Smaili, Yanan Zhang, Mekkaoui Djamel Eddine, Mohamed Amine Midoun, Mohamed Zakariya Talhaoui, Hamidaoui Meryem, Weiqiang Kong
2025 J jnl
ACM Trans. Softw. Eng. Methodol.
Yuan Zhang, Lei Qu, Yifei Wu, Leihuan Wu, Tingting Yu, Rui Chen, Weiqiang Kong
2025 J jnl
Vis. Comput.
Anjum Iqbal, Weiqiang Kong, Yasir Iqbal, Umer Sadiq Khan, Shah Fahad Khan, Ijaz Hussain
2025 J jnl
Int. J. Intell. Syst.
Maseeh Ullah Khan, Muhammad Farhat Ullah, Sabeeh Ullah Khan, Weiqiang Kong
2025 J jnl
Neurocomputing
Yueyuan Qin, Gang Hou, Tingting Yu, Bing Gao, Weiqiang Kong, Xiaoshan Liu
2024 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Huanzhang Xiong, Gang Hou, Yueyuan Qin, Jie Wang, Weiqiang Kong
2023 C conf
APSEC
Huanzhang Xiong, Gang Hou, Long Zhu, Jie Wang, Weiqiang Kong
2023 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Xiaozhen Zhang, Zhaoming Yang, Hui Kong, Weiqiang Kong
2022 C conf
APSEC
Xiaozhen Zhang, Zhaoming Yang, Hui Kong, Weiqiang Kong
2022 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Yixuan Tang, Zhilei Ren, He Jiang, Lei Qiao, Dong Liu, Zhide Zhou, Weiqiang Kong
2022 J jnl
IEEE Trans. Software Eng.
Yixuan Tang, He Jiang, Zhide Zhou, Xiaochen Li, Zhilei Ren, Weiqiang Kong
2022 C conf
QRS
Xiaozhen Zhang, Zhaoming Yang, Hui Kong, Weiqiang Kong
2021 J jnl
J. Comput. Sci. Technol.
Yixuan Tang, Zhilei Ren, He Jiang, Xiao-Chen Li, Weiqiang Kong
2021 J jnl
Formal Aspects Comput.
Huihui Wu, Deyun Lv, Tengxiang Cui, Gang Hou, Masahiko Watanabe, Weiqiang Kong
2020 Misc conf
TASE
Zhen Wang, Xiaoning Han, Weiqiang Kong, Yong Piao, Gang Hou, Masahiko Watanabe, Akira Fukuda
2020 J jnl
Frontiers Comput. Sci.
Yixuan Tang, Zhilei Ren, Weiqiang Kong, He Jiang
2019 conf
DSA
Yuan Yuan, Weiqiang Kong, Gang Hou, Yan Hu, Masahiko Watanabe, Akira Fukuda
2019 conf
DSA
Kun Liu, Xiaozhen Zhang, Weiqiang Kong, Gang Hou, Masahiko Watanabe, Akira Fukuda
2019 conf
CITS
Zhen Wang, Kai Li, Yan Hu, Akira Fukuda, Weiqiang Kong
2019 B conf
ICPADS
Gang Hou, Weiqiang Kong, Kuanjiu Zhou, Jie Wang, Chi Lin
2019 J jnl
IEEE Trans. Serv. Comput.
He Jiang, Liming Nie, Zeyi Sun, Zhilei Ren, Weiqiang Kong, Tao Zhang, Xiapu Luo
2019 Misc conf
TASE
Xiaozhen Zhang, Weiqiang Kong, Jianguo Jiang, Gang Hou, Akira Fukuda
2018 conf
IIAI-AAI
Kun Liu, Weiqiang Kong, Gang Hou, Akira Fukuda
2018 conf
IIAI-AAI
Gang Hou, Weiqiang Kong, Kuanjiu Zhou, Jie Wang, Xun Cao, Akira Fukuda
2018 J jnl
CoRR
Yixuan Tang, Zhilei Ren, Weiqiang Kong, He Jiang
2018 conf
DSA
Yan Hu, Weiqiang Kong, Deng Ding, Jun Yan
2018 conf
IIAI-AAI
Akira Fukuda, Tsuneo Nakanishi, Kenji Hisazumi, Kunihiko Kaneko, Shigeaki Tagashira, Tsunenori Mine, Yutaka Arakawa, Shigemi Ishida, Takahiro Ando, Shuichi Ashihara, Masakatsu Ura, Yoshimichi Nakamura, Soichiro Nakamura, Weiqiang Kong, Guoqiang Li
2018 conf
DSA
Takahiro Ando, Bo Wang, Kenji Hisazumi, Weiqiang Kong, Akira Fukuda, Yasutaka Michiura, Keita Sakemi, Michihiro Matsumoto
2017 J jnl
IEEE Access
Yan Hu, Weiqiang Kong, Yizhi Ren, Kim-Kwang Raymond Choo
2017 J jnl
IEEE Access
Gang Hou, Kuanjiu Zhou, Tie Qiu, Weiqiang Kong, Mingchu Li
2017 J jnl
CoRR
He Jiang, Liming Nie, Zeyi Sun, Zhilei Ren, Weiqiang Kong, Tao Zhang, Xiapu Luo
2016 J jnl
J. Inf. Secur. Appl.
Weiqiang Kong, Gang Hou, Xiangpei Hu, Takahiro Ando, Kenji Hisazumi, Akira Fukuda
2016 conf
IIAI-AAI
Akira Fukuda, Kenji Hisazumi, Shigemi Ishida, Tsunenori Mine, Tsuneo Nakanishi, Hiroki Furusho, Shigeaki Tagashira, Yutaka Arakawa, Kunihiko Kaneko, Weiqiang Kong
2016 conf
ICA
Weiqiang Kong, Gang Hou, Xiangpei Hu, Yasuhito Arimoto, Masahiko Watanabe, Takahiro Ando, Kenji Hisazumi, Akira Fukuda
2015 J jnl
Comput. J.
Weiqiang Kong, Leyuan Liu, Takahiro Ando, Hirokazu Yatsu, Kenji Hisazumi, Akira Fukuda
2015 conf
COMPSAC Workshops
He Jiang, Xin Chen, Shuwei Zhang, Xin Zhang, Weiqiang Kong, Tao Zhang
2015 J jnl
CoRR
He Jiang, Xin Chen, Shuwei Zhang, Xin Zhang, Weiqiang Kong, Tao Zhang
2014 J jnl
Formal Aspects Comput.
Yoriyuki Yamagata, Weiqiang Kong, Akira Fukuda, Nguyen Van Tang, Hitoshi Ohsaki, Kenji Taguchi
2014 J jnl
Int. J. Web Inf. Syst.
Takahiro Ando, Hirokazu Yatsu, Weiqiang Kong, Kenji Hisazumi, Akira Fukuda
2013 conf
ICCSA (3)
Takahiro Ando, Hirokazu Yatsu, Weiqiang Kong, Kenji Hisazumi, Akira Fukuda
2013 conf
APSEC (1)
Weiqiang Kong, Leyuan Liu, Takahiro Ando, Hirokazu Yatsu, Kenji Hisazumi, Akira Fukuda
2013 conf
ICST Workshops
Hirokazu Yatsu, Takahiro Ando, Weiqiang Kong, Kenji Hisazumi, Akira Fukuda, Toshiaki Aoki, Kokichi Futatsugi
2012 C conf
IPIN
Ming Li, Long Han, Weiqiang Kong, Shigeaki Tagashira, Yutaka Arakawa, Akira Fukuda
2012 C conf
CIT
Leyuan Liu, Weiqiang Kong, Shijie Zhou, Zhiguang Qin, Akira Fukuda
2012 J jnl
ACM SIGSOFT Softw. Eng. Notes
Yoriyuki Yamagata, Weiqiang Kong, Akira Fukuda, Nguyen Van Tang, Hitoshi Ohsaki, Kenji Taguchi
2012 C conf
APSEC
Weiqiang Kong, Leyuan Liu, Yoriyuki Yamagata, Kenji Taguchi, Hitoshi Ohsaki, Akira Fukuda
2011 conf
ICCSA Workshops
Weiqiang Kong, Noriyuki Katahira, Wanpeng Qian, Masahiko Watanabe, Tetsuro Katayama, Akira Fukuda
2011 J jnl
IEICE Trans. Inf. Syst.
Weiqiang Kong, Tomohiro Shiraishi, Noriyuki Katahira, Masahiko Watanabe, Tetsuro Katayama, Akira Fukuda
2011 C conf
APSEC
Weiqiang Kong, Noriyuki Katahira, Masahiko Watanabe, Tetsuro Katayama, Kenji Hisazumi, Akira Fukuda
2010 conf
ICCSA Workshops
Weiqiang Kong, Tomohiro Shiraishi, Yuki Mizushima, Noriyuki Katahira, Akira Fukuda, Masahiko Watanabe
2010 conf
Software Engineering Research and Practice
Tomohiro Shiraishi, Weiqiang Kong, Yuki Mizushima, Noriyuki Katahira, Michihiro Matsumoto, Masahiko Watanabe, Tetsuro Katayama, Akira Fukuda
2010 J jnl
IEICE Trans. Inf. Syst.
Weiqiang Kong, Kazuhiro Ogata, Kokichi Futatsugi
2008 J jnl
IEICE Trans. Inf. Syst.
Masaki Nakamura, Weiqiang Kong, Kazuhiro Ogata, Kokichi Futatsugi
2008 C conf
CIT
Weiqiang Kong, Kazuhiro Ogata, Jian Cheng, Kokichi Futatsugi
2007 B conf
IFM
Weiqiang Kong, Kazuhiro Ogata, Kokichi Futatsugi
2007 conf
ICEGOV
Xiaoyi Chen, Weiqiang Kong, Kokichi Futatsugi
2007 J jnl
Inf. Media Technol.
Jianwen Xiang, Kazuhiro Ogata, Weiqiang Kong, Kokichi Futatsugi
2007 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Weiqiang Kong, Kazuhiro Ogata, Kokichi Futatsugi
2006 conf
WEBIST (2)
Jianwen Xiang, Weiqiang Kong, Kokichi Futatsugi, Kazuhiro Ogata
2006 C conf
SEKE
Kazuhiro Ogata, Weiqiang Kong, Kokichi Futatsugi
2006 C conf
ICFEM
Kazuhiro Ogata, Masahiro Nakano, Weiqiang Kong, Kokichi Futatsugi
2005 C conf
APSEC
Weiqiang Kong, Takahiro Seino, Kokichi Futatsugi, Kazuhiro Ogata
2005 C conf
SEKE
Weiqiang Kong, Kazuhiro Ogata, Kokichi Futatsugi
2004 C conf
CIT
Weiqiang Kong, Kazuhiro Ogata, Jianwen Xiang, Kokichi Futatsugi
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