Xianghao Zhan

36 papers Misc 1Journal 34Unranked 1
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Biomed. Eng.
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Jessica Towns, Ashlyn A. Callan, Olivier Gevaert, Michael M. Zeineh, David B. Camarillo
2026 J jnl
IEEE Internet Things J.
Xianghao Zhan, Nafiul Rashid, Ebrahim Nemati, Mohsin Y. Ahmed, Sharath Chandrashekhara, Jilong Kuang
2026 J jnl
CoRR
Xianghao Zhan, Jingyu Xu, Yuanning Zheng, Zinaida Good, Olivier Gevaert
2026 J jnl
Informatics
Juntao Lin, Xianghao Zhan
2025 J jnl
CoRR
Qinmei Xu, Yiheng Li, Xianghao Zhan, Ahmet Gorkem Er, Brittany Dashevsky, Chuanjun Xu, Mohammed Alawad, Mengya Yang, Liu Ya, Changsheng Zhou, Xiao Li, Haruka Itakura, Olivier Gevaert
2025 Misc conf
ICASSP
Xianghao Zhan, Nafiul Rashid, Ebrahim Nemati, Mohsin Y. Ahmed, Jilong Kuang
2025 J jnl
Comput. Biol. Medicine
Xianghao Zhan, Yuzhe Liu, August G. Domel, Michael Fanton, Zhou Zhou, Samuel J. Raymond, Hossein Vahid Alizadeh, Nicholas J. Cecchi, Michael M. Zeineh, Gerald G. Grant, David B. Camarillo, Svein Kleiven
2025 J jnl
PLoS Comput. Biol.
Xianghao Zhan, Qinmei Xu, Yuanning Zheng, Guangming Lu, Olivier Gevaert
2025 J jnl
CoRR
Juntao Lin, Xianghao Zhan
2024 J jnl
IEEE Trans. Biomed. Eng.
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Ashlyn A. Callan, Enora Le Flao, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2024 J jnl
IEEE Trans. Biomed. Eng.
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2024 J jnl
CoRR
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Jessica Towns, Ashlyn A. Callan, Olivier Gevaert, Michael M. Zeineh, David B. Camarillo
2023 J jnl
CoRR
Xianghao Zhan, Qinmei Xu, Yuanning Zheng, Guangming Lu, Olivier Gevaert
2023 J jnl
IEEE Trans. Reliab.
Xianghao Zhan, Liang Kou, Meiting Xue, Jilin Zhang, Li Zhou
2023 J jnl
CoRR
Xianghao Zhan, Jiawei Sun, Yuzhe Liu, Nicholas J. Cecchi, Enora Le Flao, Olivier Gevaert, Michael M. Zeineh, David B. Camarillo
2022 J jnl
Sensors
Lifeng Lei, Liang Kou, Xianghao Zhan, Jilin Zhang, Yongjian Ren
2022 J jnl
IEEE Trans. Instrum. Meas.
Li Liu, Xianghao Zhan, Xikai Yang, Xiaoqing Guan, Rumeng Wu, Zhan Wang, Zhiyuan Luo, You Wang, Guang Li
2022 J jnl
CoRR
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Ashlyn A. Callan, Enora Le Flao, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2022 J jnl
CoRR
Xianghao Zhan, Fanjin Wang, Olivier Gevaert
2022 J jnl
IEEE Trans. Biomed. Eng.
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2022 J jnl
IEEE J. Biomed. Health Informatics
Xianghao Zhan, Fanjin Wang, Olivier Gevaert
2022 J jnl
IEEE Trans. Instrum. Meas.
Hengyang Wang, Xianghao Zhan, Li Liu, Asif Ullah, Huiyan Li, Han Gao, You Wang, Ruifen Hu, Guang Li
2021 J jnl
npj Digit. Medicine
Qinmei Xu, Xianghao Zhan, Zhen Zhou, Yiheng Li, Peiyi Xie, Shu Zhang, Xiuli Li, Yizhou Yu, Changsheng Zhou, Longjiang Zhang, Olivier Gevaert, Guangming Lu
2021 conf
QRS Companion
Xianghao Zhan, Lifeng Lei, Liang Kou
2021 J jnl
CoRR
Li Liu, Xianghao Zhan, Rumeng Wu, Xiaoqing Guan, Zhan Wang, Wei Zhang, You Wang, Zhiyuan Luo, Guang Li
2021 J jnl
CoRR
Xianghao Zhan, Yiheng Li, Yuzhe Liu, Nicholas J. Cecchi, Samuel J. Raymond, Zhou Zhou, Hossein Vahid Alizadeh, Jesse Ruan, Saeed Barbat, Stephen Tiernan, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
CoRR
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
CoRR
Xianghao Zhan, Yiheng Li, Yuzhe Liu, Nicholas J. Cecchi, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
CoRR
Xianghao Zhan, Yiheng Li, Yuzhe Liu, August G. Domel, Hossein Vahid Alizadeh, Zhou Zhou, Nicholas J. Cecchi, Stephen Tiernan, Jesse Ruan, Saeed Barbat, Olivier Gevaert, Michael Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
IEEE Trans. Biomed. Eng.
Xianghao Zhan, Yuzhe Liu, Samuel J. Raymond, Hossein Vahid Alizadeh, August G. Domel, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
CoRR
Xianghao Zhan, Yuzhe Liu, Nicholas J. Cecchi, Olivier Gevaert, Michael M. Zeineh, Gerald A. Grant, David B. Camarillo
2021 J jnl
Patterns
Xianghao Zhan, Marie Humbert-Droz, Pritam Mukherjee, Olivier Gevaert
2021 J jnl
CoRR
Hengyang Wang, Xianghao Zhan, Li Liu, Asif Ullah, Huiyan Li, Han Gao, You Wang, Guang Li
2020 J jnl
CoRR
Xianghao Zhan, Yuzhe Liu, Samuel J. Raymond, Hossein Vahid Alizadeh, August G. Domel, Olivier Gevaert, Michael Zeineh, Gerald A. Grant, David B. Camarillo
2020 J jnl
CoRR
Xianghao Zhan, Yiheng Li, Yuzhe Liu, August G. Domel, Hossein Vahid Alizadeh, Samuel J. Raymond, Jesse Ruan, Saeed Barbat, Stephen Tiernan, Olivier Gevaert, Michael Zeineh, Gerald A. Grant
2018 J jnl
Sensors
Xianghao Zhan, Xiaoqing Guan, Rumeng Wu, Zhan Wang, You Wang, Guang Li
redb/extractors/apk_extractors/apk_features.py
← Index redb/extractors/apk_extractors/apk_features.py python
import inspect
import zipfile
from datetime import datetime, timezone
from typing import Any

from redb.extractors.enum import Tag
from redb.extractors.apk_extractor import APKExtractor
from redb.models.dataclasses import APKFeatures


class APKFeaturesExtractor(APKExtractor):

    def __init__(
        self, filepath, log, exporters=None, index_prefix=None,
        known_benign=False, known_malicious=False,
        apk=None,
    ):
        super().__init__(
            filepath, log, exporters, index_prefix,
            known_benign, known_malicious, apk,
        )
        self.apk_features = None
        self.log.debug(inspect.currentframe().f_code.co_name)

    def tag(self):
        return Tag.APK_FEATURES.value

    def _extract_zip_timestamps(self):
        """Extract earliest and latest content modification from ZIP entries."""
        earliest = None
        latest = None
        try:
            zf = self._get_zip_file()
            if zf:
                with zf:
                    for info in zf.infolist():
                        try:
                            dt = datetime(*info.date_time)
                            if earliest is None or dt < earliest:
                                earliest = dt
                            if latest is None or dt > latest:
                                latest = dt
                        except (ValueError, TypeError):
                            continue
        except Exception as e:
            self.log.warning(f"Error extracting ZIP timestamps: {e}")
        return (
            earliest.isoformat() if earliest else None,
            latest.isoformat() if latest else None,
        )

    def _extract_supported_abis(self):
        """Determine supported ABIs from lib/ directory."""
        abis = set()
        for f in self._list_files():
            if f.startswith("lib/") and f.endswith(".so"):
                parts = f.split("/")
                if len(parts) >= 3:
                    abis.add(parts[1])
        return sorted(abis)

    def _count_dex_files(self):
        """Count DEX files and compute total size."""
        dex_count = 0
        total_size = 0
        try:
            zf = self._get_zip_file()
            if zf:
                with zf:
                    for info in zf.infolist():
                        if info.filename.endswith(".dex"):
                            dex_count += 1
                            total_size += info.file_size
        except Exception as e:
            self.log.warning(f"Error counting DEX files: {e}")
        return dex_count, total_size

    def _check_embedded_apk(self):
        """Check if the archive contains nested APK files."""
        for f in self._list_files():
            if f.lower().endswith(".apk"):
                return True
        return False

    def _safe_extract(self, field_name, func, default=None):
        """Extract a single field, logging and returning default on failure."""
        try:
            return func()
        except Exception as e:
            self.log.warning(
                f"Error extracting APK field '{field_name}' for "
                f"{self.hash.sha256}: {e}"
            )
            return default

    def extract(self):
        if not self._is_valid_apk():
            self.log.error(f"Invalid APK for {self.hash.sha256}")
            return None

        package_name = self._safe_extract(
            "package_name", lambda: self.apk.get_package()
        )
        app_name = self._safe_extract(
            "app_name", lambda: self.apk.get_app_name()
        )

        def _get_version_code():
            try:
                return int(self.apk.get_androidversion_code() or 0)
            except (ValueError, TypeError):
                return 0

        version_code = self._safe_extract("version_code", _get_version_code)
        version_name = self._safe_extract(
            "version_name", lambda: self.apk.get_androidversion_name()
        )

        def _get_sdk(getter):
            val = getter()
            return int(val) if val else None

        min_sdk = self._safe_extract(
            "min_sdk_version", lambda: _get_sdk(self.apk.get_min_sdk_version)
        )
        target_sdk = self._safe_extract(
            "target_sdk_version", lambda: _get_sdk(self.apk.get_target_sdk_version)
        )
        compile_sdk = self._safe_extract(
            "compile_sdk_version",
            lambda: _get_sdk(self.apk.get_effective_target_sdk_version),
        )

        main_activity = self._safe_extract(
            "main_activity", lambda: self.apk.get_main_activity()
        )

        is_debuggable = self._safe_extract(
            "is_debuggable",
            lambda: self.apk.get_attribute_value(
                "application", "debuggable"
            ) == "true",
            False,
        )
        allow_backup = self._safe_extract(
            "allow_backup",
            lambda: self.apk.get_attribute_value(
                "application", "allowBackup"
            ) != "false",
            True,
        )
        uses_cleartext = self._safe_extract(
            "uses_cleartext_traffic",
            lambda: self.apk.get_attribute_value(
                "application", "usesCleartextTraffic"
            ) == "true",
            False,
        )

        supported_abis = self._safe_extract(
            "supported_abis", self._extract_supported_abis, []
        )
        dex_count, total_dex_size = self._safe_extract(
            "dex_files", self._count_dex_files, (0, 0)
        )
        all_files = self._safe_extract("file_list", self._list_files, [])
        total_file_count = len(all_files)
        has_native_code = any(
            f.startswith("lib/") and f.endswith(".so") for f in all_files
        )
        has_assets = any(f.startswith("assets/") for f in all_files)
        contains_embedded_apk = self._safe_extract(
            "contains_embedded_apk", self._check_embedded_apk, False
        )

        uses_libraries = self._safe_extract(
            "uses_libraries",
            lambda: list(self.apk.get_libraries() or []),
            [],
        )

        earliest_mod, latest_mod = self._safe_extract(
            "zip_timestamps", self._extract_zip_timestamps, (None, None)
        )

        self.apk_features = APKFeatures(
            package_name=package_name,
            app_name=app_name,
            version_code=version_code,
            version_name=version_name,
            min_sdk_version=min_sdk,
            target_sdk_version=target_sdk,
            compile_sdk_version=compile_sdk,
            main_activity=main_activity,
            is_debuggable=is_debuggable,
            allow_backup=allow_backup,
            uses_cleartext_traffic=uses_cleartext,
            supported_abis=supported_abis,
            dex_count=dex_count,
            total_dex_size=total_dex_size,
            total_file_count=total_file_count,
            has_native_code=has_native_code,
            has_assets=has_assets,
            uses_libraries=uses_libraries,
            earliest_content_modification=earliest_mod,
            latest_content_modification=latest_mod,
            contains_embedded_apk=contains_embedded_apk,
        )
        return self.apk_features

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            if not self.apk_features:
                return None

            f = self.apk_features
            current_time = datetime.now(timezone.utc)
            data = [[
                self.sha256,
                f.package_name,
                f.app_name,
                f.version_code,
                f.version_name,
                f.min_sdk_version,
                f.target_sdk_version,
                f.compile_sdk_version,
                f.main_activity,
                int(f.is_debuggable),
                int(f.allow_backup),
                int(f.uses_cleartext_traffic),
                f.supported_abis,
                f.dex_count,
                f.total_dex_size,
                f.total_file_count,
                int(f.has_native_code),
                int(f.has_assets),
                f.uses_libraries,
                f.earliest_content_modification,
                f.latest_content_modification,
                int(f.contains_embedded_apk),
                current_time,
            ]]

            column_names = [
                "sha256",
                "package_name", "app_name", "version_code", "version_name",
                "min_sdk_version", "target_sdk_version", "compile_sdk_version",
                "main_activity",
                "is_debuggable", "allow_backup", "uses_cleartext_traffic",
                "supported_abis",
                "dex_count", "total_dex_size", "total_file_count",
                "has_native_code", "has_assets",
                "uses_libraries",
                "earliest_content_modification", "latest_content_modification",
                "contains_embedded_apk",
                "analysis_date",
            ]

            column_type_names = [
                "FixedString(64)",
                "Nullable(String)", "Nullable(String)", "Nullable(UInt32)", "Nullable(String)",
                "Nullable(UInt16)", "Nullable(UInt16)", "Nullable(UInt16)",
                "Nullable(String)",
                "UInt8", "UInt8", "UInt8",
                "Array(String)",
                "UInt16", "UInt64", "UInt32",
                "UInt8", "UInt8",
                "Array(String)",
                "Nullable(String)", "Nullable(String)",
                "UInt8",
                "DateTime64(3, 'UTC')",
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "redb_apk_features"