Vaduvur Bharghavan

68 papers A* 21A 1B 12C 4Journal 19Unranked 11
YearRankTypeTitle / Venue / Authors
2006 A* conf
MobiCom
Starsky H. Y. Wong, Songwu Lu, Hao Yang, Vaduvur Bharghavan
2005 J jnl
Wirel. Networks
Vaduvur Bharghavan, Andrew T. Campbell
2004 J jnl
Mob. Networks Appl.
Haiyun Luo, Songwu Lu, Vaduvur Bharghavan, Jerry Cheng, Gary Zhong
2004 J jnl
Comput. Networks
Thyagarajan Nandagopal, Kang-Won Lee, Jia-Ru Li, Vaduvur Bharghavan
2003 J jnl
Comput. Networks
Raghupathy Sivakumar, Prasun Sinha, Vaduvur Bharghavan
2002 J jnl
Wirel. Networks
Thyagarajan Nandagopal, Songwu Lu, Vaduvur Bharghavan
2002 J jnl
Multim. Tools Appl.
Songwu Lu, Kang-Won Lee, Vaduvur Bharghavan
2002 A* ed.
MobiCom
Ian F. Akyildiz, Jason Yi-Bing Lin, Ravi Jain, Vaduvur Bharghavan, Andrew T. Campbell
2002 J jnl
Wirel. Networks
Prasun Sinha, Thyagarajan Nandagopal, Narayanan Venkitaraman, Raghupathy Sivakumar, Vaduvur Bharghavan
2001 A* conf
INFOCOM
Jeffrey P. Monks, Vaduvur Bharghavan, Wen-mei W. Hwu
2001 B conf
GLOBECOM
Kang-Won Lee, Tae-Eun Kim, Vaduvur Bharghavan
2001 J jnl
IEEE Trans. Multim.
Rohit Puri, Kang-Won Lee, Kannan Ramchandran, Vaduvur Bharghavan
2001 A* conf
INFOCOM
Prasun Sinha, Raghupathy Sivakumar, Vaduvur Bharghavan
2001 J jnl
Signal Process. Image Commun.
Rohit Puri, Kannan Ramchandran, Kang-Won Lee, Vaduvur Bharghavan
2001 A* conf
INFOCOM
David Craig, Hwangnam Kim, Raghupathy Sivakumar, Vaduvur Bharghavan, Constantine D. Polychronopoulos
2001 J jnl
J. High Speed Networks
Xia Gao, Thyagarajan Nandagopal, Vaduvur Bharghavan
2000 A* conf
MobiCom
Haiyun Luo, Songwu Lu, Vaduvur Bharghavan
2000 B conf
GLOBECOM
Sungwon Ha, Sung-Wook Han, Vaduvur Bharghavan
2000 A* conf
MobiCom
Thyagarajan Nandagopal, Tae-Eun Kim, Xia Gao, Vaduvur Bharghavan
2000 A conf
ICDCS
Raghupathy Sivakumar, Tae-Eun Kim, Narayanan Venkitaraman, Jia-Ru Li, Vaduvur Bharghavan
2000 A* conf
INFOCOM
Kang-Won Lee, Rohit Puri, Tae-Eun Kim, Kannan Ramchandran, Vaduvur Bharghavan
2000 A* conf
ACM Multimedia
Kang-Won Lee, Sungwon Ha, Jia-Ru Li, Vaduvur Bharghavan
2000 J jnl
Wirel. Networks
Songwu Lu, Thyagarajan Nandagopal, Vaduvur Bharghavan
2000 A* conf
INFOCOM
Thyagarajan Nandagopal, Narayanan Venkitaraman, Raghupathy Sivakumar, Vaduvur Bharghavan
2000 B conf
LCN
Jeffrey P. Monks, Vaduvur Bharghavan, Wen-mei W. Hwu
1999 A* conf
MobiCom
Thyagarajan Nandagopal, Songwu Lu, Vaduvur Bharghavan
1999 conf
ICC
Sungwon Ha, Vaduvur Bharghavan
1999 B conf
ICCCN
Sungwon Ha, Kang-Won Lee, Vaduvur Bharghavan
1999 B conf
WCNC
Prasun Sinha, Narayanan Venkitaraman, Thyaga Nandagopal, Raghupathy Sivakumar, Vaduvur Bharghavan
1999 J jnl
Mob. Networks Appl.
Vaduvur Bharghavan, Chai-Keong Toh
1999 A* conf
INFOCOM
Prasun Sinha, Raghupathy Sivakumar, Vaduvur Bharghavan
1999 J jnl
IEEE J. Sel. Areas Commun.
Raghupathy Sivakumar, Prasun Sinha, Vaduvur Bharghavan
1999 J jnl
IEEE Wirel. Commun.
Vaduvur Bharghavan, Songwu Lu, Thyaga Nandagopal
1999 J jnl
IEEE/ACM Trans. Netw.
Songwu Lu, Vaduvur Bharghavan, Rayadurgam Srikant
1999 A* conf
INFOCOM
Jia-Ru Li, Sungwon Ha, Vaduvur Bharghavan
1999 A* conf
INFOCOM
Kang-Won Lee, Sungwon Ha, Vaduvur Bharghavan
1999 B conf
ICCCN
Tae-Eun Kim, Songwu Lu, Vaduvur Bharghavan
1999 B conf
WCNC
Prasun Sinha, Raghupathy Sivakumar, Vaduvur Bharghavan
1999 conf
Networked Group Communication
Tae-Eun Kim, Raghupathy Sivakumar, Kang-Won Lee, Vaduvur Bharghavan
1999 B conf
WCNC
Tae-Eun Kim, Vaduvur Bharghavan
1999 conf
ICC
Kang-Won Lee, Vaduvur Bharghavan
1999 conf
IWAN
Raghupathy Sivakumar, Narayanan Venkitaraman, Vaduvur Bharghavan
1999 A* conf
MobiCom
Prasun Sinha, Narayanan Venkitaraman, Raghupathy Sivakumar, Vaduvur Bharghavan
1998 A* conf
MobiCom
Songwu Lu, Thyagarajan Nandagopal, Vaduvur Bharghavan
1998 conf
ICMCS
Dane Dwyer, Sungwon Ha, Jia-Ru Li, Vaduvur Bharghavan
1998 conf
ICC
Michael Stangel, Vaduvur Bharghavan
1998 C conf
ISCC
Sungwon Ha, Kang-Won Lee, Vaduvur Bharghavan
1998 conf
ICC
Jayanth Mysore, Vaduvur Bharghavan
1998 J jnl
Clust. Comput.
Raghupathy Sivakumar, Bevan Das, Vaduvur Bharghavan
1998 J jnl
IEEE Wirel. Commun.
Vaduvur Bharghavan, Kang-Won Lee, Songwu Lu, Sungwon Ha, Jia-Ru Li, Dane Dwyer
1998 C conf
ISCC
Raghupathy Sivakumar, Bevan Das, Vaduvur Bharghavan
1997 J jnl
ACM SIGOPS Oper. Syst. Rev.
Dane Dwyer, Vaduvur Bharghavan
1997 A* conf
MobiCom
Jayanth Mysore, Vaduvur Bharghavan
1997 B conf
COMPSAC
Vaduvur Bharghavan, Vijay Gupta
1997 conf
USENIX Symposium on Internet Technologies and Systems
Tong Sau Loon, Vaduvur Bharghavan
1997 J jnl
Wirel. Pers. Commun.
Vaduvur Bharghavan
1997 conf
ICC (2)
Sueng-Yong Park, Vaduvur Bharghavan, Sung-Mo Kang
1997 A* conf
SIGCOMM
Songwu Lu, Vaduvur Bharghavan, Rayadurgam Srikant
1997 B conf
ICCCN
Bevan Das, Raghupathy Sivakumar, Vaduvur Bharghavan
1997 conf
ICC (1)
Bevan Das, Vaduvur Bharghavan
1996 A* conf
SIGCOMM
Songwu Lu, Vaduvur Bharghavan
1995 C conf
ISADS
Vaduvur Bharghavan, Chittoor V. Ramamoorthy
1994 A* conf
SIGCOMM
Vaduvur Bharghavan, Alan J. Demers, Scott Shenker, Lixia Zhang
1994 B conf
COMPSAC
Chye-Lin Chee, S. Ishihara, Vaduvur Bharghavan, Vikram Vij, C. V. Ramamoorthy
1994 A* conf
CCS
Vaduvur Bharghavan
1993 B conf
COMPSAC
Vaduvur Bharghavan, C. V. Ramamoorthy
1993 C conf
ISADS
Vaduvur Bharghavan, C. V. Ramamoorthy
1992 conf
INDC
S. V. Raghavan, Vaduvur Bharghavan, S. Satish
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