Hae Won Park

105 papers A* 24A 3B 13Misc 3Journal 43Unranked 16
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Dong Won Lee, Sarah Gillet, Louis-Philippe Morency, Cynthia Breazeal, Hae Won Park
2026 J jnl
CoRR
Zhiyuan Hu, Yunhai Hu, Juncheng Liu, Shuyue Stella Li, Yucheng Wang, Zhen Xu, See-Kiong Ng, Anh Tuan Luu, Xinxing Xu, Bryan Hooi, Cynthia Breazeal, Hae Won Park
2026 A* conf
HRI
Hae Won Park, Georgia D. van de Zande, Xiajie Zhang, Dawn Wendell, Jessica Hodgins
2026 J jnl
CoRR
Zhiyuan Hu, Yucheng Wang, Yufei He, Jiaying Wu, Yilun Zhao, See-Kiong Ng, Cynthia Breazeal, Anh Tuan Luu, Hae Won Park, Bryan Hooi
2026 J jnl
CoRR
Jocelyn Shen, Amina Luvsanchultem, Jessica Kim, Kynnedy Smith, Valdemar Danry, Kantwon Rogers, Hae Won Park, Maarten Sap, Cynthia Breazeal
2025 J jnl
CoRR
Dong Won Lee, Hae Won Park, Cynthia Breazeal, Louis-Philippe Morency
2025 J jnl
CoRR
Yubin Kim, Zhiyuan Hu, Hyewon Jeong, Eugene Park, Shuyue Stella Li, Chanwoo Park, Shiyun Xiong, Mingyu Lu, Hyeonhoon Lee, Xin Liu, Daniel McDuff, Cynthia Breazeal, Samir Tulebaev, Hae Won Park
2025 conf
EMNLP (Findings)
Yubin Kim, Zhiyuan Hu, Hyewon Jeong, Eugene Park, Shuyue Stella Li, Chanwoo Park, Shiyun Xiong, Mingyu Lu, Hyeonhoon Lee, Xin Liu, Daniel McDuff, Cynthia Breazeal, Samir Tulebaev, Hae Won Park
2025 J jnl
CoRR
Yubin Kim, Taehan Kim, Eugene Park, Chunjong Park, Cynthia Breazeal, Daniel McDuff, Hae Won Park
2025 J jnl
CoRR
Yubin Kim, Hyewon Jeong, Shan Chen, Shuyue Stella Li, Mingyu Lu, Kumail Alhamoud, Jimin Mun, Cristina Grau, Minseok Jung, Rodrigo Gameiro, Lizhou Fan, Eugene Park, Tristan Lin, Joonsik Yoon, Wonjin Yoon, Maarten Sap, Yulia Tsvetkov, Paul Liang, Xuhai Xu, Xin Liu, Daniel McDuff, Hyeonhoon Lee, Hae Won Park, Samir Tulebaev, Cynthia Breazeal
2025 A* conf
HRI
Jocelyn Shen, Audrey Lee, Sharifa Alghowinem, River Adkins, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Jocelyn Shen, Audrey Lee, Sharifa Alghowinem, River Adkins, Cynthia Breazeal, Hae Won Park
2025 J jnl
Sci. Robotics
Huili Chen, Yubin Kim, Kejia Patterson, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Dong Won Lee, Yubin Kim, Denison Guvenoz, Sooyeon Jeong, Parker Malachowsky, Louis-Philippe Morency, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Yubin Kim, Hyewon Jeong, Chanwoo Park, Eugene Park, Haipeng Zhang, Xin Liu, Hyeonhoon Lee, Daniel McDuff, Marzyeh Ghassemi, Cynthia Breazeal, Samir Tulebaev, Hae Won Park
2025 A* conf
HRI
Safinah Arshad Ali, Ayat Abodayeh, Zahra Dhuliawala, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Yubin Kim, Ken Gu, Chanwoo Park, Chunjong Park, Samuel Schmidgall, A. Ali Heydari, Yao Yan, Zhihan Zhang, Yuchen Zhuang, Mark Malhotra, Paul Pu Liang, Hae Won Park, Yuzhe Yang, Xuhai Xu, Yilun Du, Shwetak N. Patel, Tim Althoff, Daniel McDuff, Xin Liu
2025 A conf
INTERSPEECH
Yubin Kim, Taehan Kim, Wonjune Kang, Eugene Park, Joonsik Yoon, Dongjae Lee, Xin Liu, Daniel McDuff, Hyeonhoon Lee, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Yubin Kim, Taehan Kim, Wonjune Kang, Eugene Park, Joonsik Yoon, Dongjae Lee, Xin Liu, Daniel McDuff, Hyeonhoon Lee, Cynthia Breazeal, Hae Won Park
2025 J jnl
CoRR
Jocelyn Shen, Akhila Yerukola, Xuhui Zhou, Cynthia Breazeal, Maarten Sap, Hae Won Park
2024 J jnl
CoRR
Yubin Kim, Chanwoo Park, Hyewon Jeong, Cristina Grau-Vilchez, Yik Siu Chan, Xuhai Xu, Daniel McDuff, Hyeonhoon Lee, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Yubin Kim, Chanwoo Park, Hyewon Jeong, Yik Siu Chan, Xuhai Xu, Daniel McDuff, Cynthia Breazeal, Hae Won Park
2024 conf
ACL (Findings)
Jocelyn Shen, Yubin Kim, Mohit Hulse, Wazeer Zulfikar, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Jocelyn Shen, Yubin Kim, Mohit Hulse, Wazeer Zulfikar, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Jocelyn Shen, Joel Mire, Hae Won Park, Cynthia Breazeal, Maarten Sap
2024 conf
CHIL
Yubin Kim, Xuhai Xu, Daniel McDuff, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Yubin Kim, Xuhai Xu, Daniel McDuff, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Dong Won Lee, Hae Won Park, Yoon Kim, Cynthia Breazeal, Louis-Philippe Morency
2024 A* conf
HRI
Huili Chen, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2024 J jnl
CoRR
Huili Chen, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2024 conf
HRI (Companion)
Hae Won Park, Cynthia Breazeal, Sharifa Alghowinem, Anastasia K. Ostrowski, Jon Ferguson, Xiajie Zhang, Dong Won Lee
2024 A* conf
NeurIPS
Yubin Kim, Chanwoo Park, Hyewon Jeong, Yik Siu Chan, Xuhai Xu, Daniel McDuff, Hyeonhoon Lee, Marzyeh Ghassemi, Cynthia Breazeal, Hae Won Park
2024 J jnl
Frontiers Robotics AI
Anastasia K. Ostrowski, Jenny Zhang, Cynthia Breazeal, Hae Won Park
2023 A* conf
HRI
Sooyeon Jeong, Laura Aymerich-Franch, Sharifa Alghowinem, Rosalind W. Picard, Cynthia Lynn Breazeal, Hae Won Park
2023 A* conf
HRI
Xiajie Zhang, Cynthia Breazeal, Hae Won Park
2023 conf
CHI Extended Abstracts
Jocelyn J. Shen, Kathryn Jin, Ann Zhang, Cynthia Breazeal, Hae Won Park
2023 J jnl
User Model. User Adapt. Interact.
Sooyeon Jeong, Laura Aymerich-Franch, Kika Arias, Sharifa Alghowinem, Àgata Lapedriza, Rosalind W. Picard, Hae Won Park, Cynthia Breazeal
2023 conf
ACIIW
Jocelyn Shen, Kimaya Lecamwasam, Hae Won Park, Cynthia Breazeal, Rosalind W. Picard
2023 J jnl
IEEE Trans. Affect. Comput.
Huili Chen, Sharifa Alghowinem, Soo Jung Jang, Cynthia Breazeal, Hae Won Park
2023 B conf
ACII
Felipe Moreno, Sharifa Alghowinem, Hae Won Park, Cynthia Breazeal
2023 conf
ACIIW
Jocelyn Shen, Ying Li, Javaria Hassan, Sharifa Alghowinem, Hae Won Park, Cynthia Breazeal, Rosalind W. Picard
2023 B conf
ICMI
Yubin Kim, Dong Won Lee, Paul Pu Liang, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2023 J jnl
CoRR
Yubin Kim, Dong Won Lee, Paul Pu Liang, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2023 A conf
AAMAS
Yubin Kim, Huili Chen, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2023 J jnl
CoRR
Jocelyn Shen, Maarten Sap, Pedro Colon-Hernandez, Hae Won Park, Cynthia Breazeal
2023 A* conf
IJCAI
Dong Won Lee, Yubin Kim, Rosalind W. Picard, Cynthia Breazeal, Hae Won Park
2023 J jnl
Frontiers Comput. Sci.
Sharifa Alghowinem, Xiajie Zhang, Cynthia Breazeal, Hae Won Park
2023 J jnl
CoRR
Dong Won Lee, Yubin Kim, Rosalind W. Picard, Cynthia Breazeal, Hae Won Park
2022 B conf
RO-MAN
Huili Chen, Anastasia K. Ostrowski, Soo Jung Jang, Cynthia Breazeal, Hae Won Park
2022 B conf
RO-MAN
Anastasia K. Ostrowski, Raechel Walker, Madhurima Das, Maria Yang, Cynthia Breazeal, Hae Won Park, Aditi Verma
2022 conf
HCI (35)
Siyu Liu, Catherine Lu, Sharifa Alghowinem, Lea Gotoh, Cynthia Breazeal, Hae Won Park
2022 J jnl
CoRR
Yubin Kim, Huili Chen, Sharifa Alghowinem, Cynthia Breazeal, Hae Won Park
2022 ch.
The Handbook on Socially Interactive Agents (2)
Jacqueline M. Kory Westlund, Hae Won Park, Ishaan Grover, Cynthia Breazeal
2022 A* conf
HRI
Anastasia K. Ostrowski, Cynthia Breazeal, Hae Won Park
2021 J jnl
Int. J. Child Comput. Interact.
Safinah Arshad Ali, Hae Won Park, Cynthia Breazeal
2021 B conf
FG
Sharifa Alghowinem, Sooyeon Jeong, Kika Arias, Rosalind W. Picard, Cynthia Breazeal, Hae Won Park
2021 B conf
FG
Sharifa Alghowinem, Huili Chen, Cynthia Breazeal, Hae Won Park
2021 J jnl
ACM Trans. Interact. Intell. Syst.
Maor Rosenberg, Hae Won Park, Rinat B. Rosenberg-Kima, Safinah Arshad Ali, Anastasia K. Ostrowski, Cynthia Breazeal, Goren Gordon
2021 J jnl
Frontiers Robotics AI
Samuel Spaulding, Jocelyn Shen, Hae Won Park, Cynthia Breazeal
2021 B conf
RO-MAN
Anastasia K. Ostrowski, Cynthia Breazeal, Hae Won Park
2021 conf
EMNLP (1)
Ishaan Grover, Matthew Huggins, Cynthia Breazeal, Hae Won Park
2021 J jnl
Frontiers Robotics AI
Anastasia K. Ostrowski, Christina N. Harrington, Cynthia Breazeal, Hae Won Park
2021 A* conf
HRI
Matthew Huggins, Sharifa Alghowinem, Sooyeon Jeong, Pedro Colon-Hernandez, Cynthia Breazeal, Hae Won Park
2021 A* conf
HRI
Anastasia K. Ostrowski, Vasiliki Zygouras, Hae Won Park, Cynthia Breazeal
2021 J jnl
Frontiers Robotics AI
Safinah Arshad Ali, Nisha Devasia, Hae Won Park, Cynthia Breazeal
2021 J jnl
Frontiers Robotics AI
Anastasia K. Ostrowski, Jenny Fu, Vasiliki Zygouras, Hae Won Park, Cynthia Breazeal
2021 J jnl
CoRR
Matthew Huggins, Anastasia K. Ostrowski, Andrew Rapo, Eric Woudenberg, Cynthia Breazeal, Hae Won Park
2021 A conf
AAMAS
Samuel Spaulding, Jocelyn Shen, Hae Won Park, Cynthia Breazeal
2020 B conf
RO-MAN
Sooyeon Jeong, Sharifa Alghowinem, Laura Aymerich-Franch, Kika Arias, Àgata Lapedriza, Rosalind W. Picard, Hae Won Park, Cynthia Breazeal
2020 J jnl
CoRR
Sooyeon Jeong, Sharifa Alghowinem, Laura Aymerich-Franch, Kika Arias, Àgata Lapedriza, Rosalind W. Picard, Hae Won Park, Cynthia Breazeal
2020 Misc conf
CHI PLAY
Safinah Arshad Ali, Hae Won Park, Cynthia Breazeal
2020 B conf
ICMI
Huili Chen, Yue Zhang, Felix Weninger, Rosalind W. Picard, Cynthia Breazeal, Hae Won Park
2020 J jnl
CoRR
Huili Chen, Yue Zhang, Felix Weninger, Rosalind W. Picard, Cynthia Breazeal, Hae Won Park
2020 A* conf
HRI
Huili Chen, Hae Won Park, Xiajie Zhang, Cynthia Breazeal
2020 J jnl
CoRR
Ravi Tejwani, Felipe Moreno, Sooyeon Jeong, Hae Won Park, Cynthia Breazeal
2020 B conf
RO-MAN
Ravi Tejwani, Felipe Moreno, Sooyeon Jeong, Hae Won Park, Cynthia Breazeal
2020 conf
CHI Extended Abstracts
Jaya Narain, Tina Quach, Monique Davey, Hae Won Park, Cynthia Breazeal, Rosalind W. Picard
2020 J jnl
Comput. Educ.
Huili Chen, Hae Won Park, Cynthia Breazeal
2019 A* conf
AAAI
Hae Won Park, Ishaan Grover, Samuel Spaulding, Louis Gomez, Cynthia Breazeal
2019 A* conf
IJCAI
Ishaan Grover, Hae Won Park, Cynthia Breazeal
2019 A* conf
CHI
Randi Williams, Hae Won Park, Cynthia Breazeal
2019 conf
SLaTE
Gary Yeung, Alison L. Bailey, Amber Afshan, Morgan Tinkler, Marlen Q. Pérez, Alejandra Martin, Anahit A. Pogossian, Samuel Spaulding, Hae Won Park, Manushaqe Muco, Abeer Alwan, Cynthia Breazeal
2019 J jnl
IEEE Robotics Autom. Mag.
Anastasia K. Ostrowski, Daniella DiPaola, Erin Partridge, Hae Won Park, Cynthia Breazeal
2019 conf
CVPR Workshops
Ognjen (Oggi) Rudovic, Hae Won Park, John Busche, Björn W. Schuller, Cynthia Breazeal, Rosalind W. Picard
2019 A* conf
AAAI
Randi Williams, Hae Won Park, Lauren Oh, Cynthia Breazeal
2018 Misc conf
IDC
Stefania Druga, Randi Williams, Hae Won Park, Cynthia Breazeal
2018 Misc conf
IDC
Jacqueline M. Kory Westlund, Hae Won Park, Randi Williams, Cynthia Breazeal
2018 conf
HRI (Companion)
Wafa Johal, James Kennedy, Vicky Charisi, Hae Won Park, Ginevra Castellano, Pierre Dillenbourg
2017 A* conf
ICRA
Hae Won Park, Mirko Gelsomini, Jin Joo Lee, Tonghui Zhu, Cynthia Breazeal
2017 conf
HRI (Companion)
Mirko Gelsomini, Hae Won Park, Jin Joo Lee, Cynthia Breazeal
2017 A* conf
HRI
Hae Won Park, Rinat B. Rosenberg-Kima, Maor Rosenberg, Goren Gordon, Cynthia Breazeal
2017 J jnl
Auton. Robots
Samer Mohammed, Hae Won Park, Chung Hyuk Park, Yacine Amirat, Brenna D. Argall
2017 A* conf
HRI
Hae Won Park, Mirko Gelsomini, Jin Joo Lee, Cynthia Breazeal
2016 B conf
ICSR
Bi Ge, Hae Won Park, Ayanna M. Howard
2015 A* conf
ICRA
Hae Won Park, Ayanna M. Howard
2015
Hae Won Park
2014 ch.
Technologies of Inclusive Well-Being
Sergio García-Vergara, LaVonda Brown, Hae Won Park, Ayanna M. Howard
2014 conf
AAAI Fall Symposia
Hae Won Park, Ayanna M. Howard
2014 A* conf
ICRA
Hae Won Park, Richard A. Coogle, Ayanna M. Howard
2013 A* conf
HRI
Hae Won Park, Ayanna M. Howard
2012 conf
EMBC
Luke Roberts, Hae Won Park, Ayanna M. Howard
2012 B conf
ICMI
Hae Won Park
2010 A* conf
ICRA
Hae Won Park, Ayanna M. Howard
2009 A* conf
ICRA
Alexander J. Trevor, Hae Won Park, Ayanna M. Howard, Charles C. Kemp
2008 B conf
RO-MAN
Ayanna M. Howard, Hae Won Park, Charles C. Kemp
redb/extractors/apk_extractors/apk_resources.py
← Index redb/extractors/apk_extractors/apk_resources.py python
import hashlib
import inspect
import os
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 APKResource


# ─── Suspicious file types ──────────────────────────────────────────────
# File types that are suspicious when found inside res/ or assets/.
# Excludes javascript/html (extremely common in legitimate hybrid apps)
# and common media/font types that are normal APK content.
SUSPICIOUS_TYPES = {
    # Executables — no legitimate reason in assets/res
    "elf", "pebin", "macho", "dex", "apk",
    # Java containers — DexClassLoader target
    "jar",
    # Archives — rare in legitimate assets (~135:1 malware-to-benign ratio)
    "zip", "gzip", "7z", "xz", "tar", "bzip2", "rar", "7zip", "lzma",
    # Scripts with system execution capability
    "shell", "python", "powershell", "batch",
}

# ─── Entropy thresholds ─────────────────────────────────────────────────
# For unrecognized/unknown types: encrypted payloads typically land > 7.0
ENTROPY_HIGH_UNKNOWN = 7.0
# For recognized-but-non-image types: stricter threshold
ENTROPY_EXTREME = 7.85

# ─── Android-specific binary format magic bytes ─────────────────────────
# These formats are common in legitimate APKs but unknown to Magika,
# causing misclassification (e.g., AXML → "gzip", profm → "unknown").
AXML_MAGIC = b'\x03\x00\x08\x00'       # Android Binary XML (compiled res/*.xml)
ARSC_MAGIC = b'\x02\x00\x0c\x00'       # Android compiled resource table
ART_PROF_MAGIC = b'pro\x00'            # ART baseline profile
ART_PROFM_MAGIC = b'prm\x00'           # ART baseline profile metadata

# ─── Allowlisted paths ──────────────────────────────────────────────────
# Fixed, hardcoded paths in the Android build system that are always benign.
# ART profiles at these exact paths are shipped by Jetpack ProfileInstaller.
ALLOWLISTED_PATHS = {
    "assets/dexopt/baseline.prof",
    "assets/dexopt/baseline.profm",
}

# ─── Image handling ─────────────────────────────────────────────────────
# Magika-confirmed image types: high entropy is expected (lossy codecs
# like VP8/JPEG arithmetic-code toward entropy ~7.95-8.0 by design).
IMAGE_MAGIKA_TYPES = {"png", "webp", "jpeg", "gif", "bmp", "tiff", "ico"}
IMAGE_EXTENSIONS = {".png", ".webp", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico"}

# ─── Types Magika assigns when it can't identify the content ────────────
UNRECOGNIZED_MAGIKA_TYPES = {"unknown", "empty"}

# ─── Resource scan limits ───────────────────────────────────────────────
MAX_RESOURCE_FILES = 5000


class APKResourceExtractor(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.resources = []
        self.suspicious_files = []
        self.log.debug(inspect.currentframe().f_code.co_name)

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

    # ─── Core classification logic ──────────────────────────────────────

    def _identify_android_format(self, header: bytes) -> str | None:
        """
        Identify Android-specific binary formats that Magika doesn't know.
        Returns a corrected type label, or None to fall through to Magika.
        """
        if len(header) < 4:
            return None

        magic4 = header[:4]

        # Android Binary XML — all res/*.xml in a compiled APK.
        # Magika often misclassifies this as "gzip".
        if magic4 == AXML_MAGIC:
            return "android_binary_xml"

        # Android compiled resource table (resources.arsc chunks)
        if magic4 == ARSC_MAGIC:
            return "android_resource_table"

        # ART baseline profiles — high entropy (zlib inside) but benign.
        # The format is inert (method reference bitmaps/metadata, not
        # executable code) and some build configs place them at varying paths.
        if magic4 == ART_PROF_MAGIC:
            return "android_art_profile"
        if magic4 == ART_PROFM_MAGIC:
            return "android_art_profile_metadata"

        return None

    def _is_suspicious_resource(
        self, path: str, magika_type: str, entropy: float,
        android_type: str | None,
    ) -> bool:
        """
        Determine if a resource file is suspicious.

        Detection layers:
        1. Allowlisted paths → always benign
        2. Android-specific format override → reclassify Magika mislabels
        3. Image extension vs Magika type mismatch → encrypted blob detection
        4. Magika-confirmed images → benign regardless of entropy
        5. Suspicious type match → flag known-dangerous types
        6. High-entropy unknown blobs → likely encrypted payloads
        """

        # ── Layer 1: Allowlisted paths (hardcoded Android build artifacts) ──
        if path in ALLOWLISTED_PATHS:
            return False

        # ── Layer 2: Android-specific format detection ──────────────────────
        # Override Magika's label for formats it doesn't recognize.
        # All Android-specific formats (AXML, ARSC, ART profiles) are
        # legitimate build artifacts — never suspicious.
        if android_type is not None:
            return False

        # ── Layer 3: Image extension / Magika type mismatch ─────────────────
        # If the file extension claims "image" but Magika's content analysis
        # disagrees, this is a strong signal for an encrypted payload with
        # a fake image extension (e.g., ErrorFather's "rbyypivsnw.png").
        ext = os.path.splitext(path)[1].lower()
        if ext in IMAGE_EXTENSIONS and magika_type not in IMAGE_MAGIKA_TYPES:
            # Exception: Magika might label a valid image as "unknown" if
            # the file is very small (< ~16 bytes). Don't flag tiny files.
            if entropy > 5.0:
                return True

        # ── Layer 4: Magika-confirmed images → benign ───────────────────────
        # Lossy codecs (VP8, JPEG) produce entropy up to ~8.0 by design.
        # If Magika confirms image structure, high entropy is expected.
        if magika_type in IMAGE_MAGIKA_TYPES:
            return False

        # ── Layer 5: Known suspicious file types ────────────────────────────
        if magika_type in SUSPICIOUS_TYPES:
            return True

        # ── Layer 6: High-entropy unrecognized blobs ────────────────────────
        # Files Magika can't identify with high entropy are likely encrypted
        # payloads. Most Android malware packers store encrypted DEX/SO
        # payloads as opaque blobs with random names and no valid magic.
        if magika_type in UNRECOGNIZED_MAGIKA_TYPES and entropy > ENTROPY_HIGH_UNKNOWN:
            return True

        # ── Layer 7: Extreme entropy on any non-image recognized type ───────
        # Catches edge cases where Magika assigns a benign label (e.g.,
        # "xml", "txt") but the entropy is impossibly high for that format.
        if magika_type not in IMAGE_MAGIKA_TYPES and entropy > ENTROPY_EXTREME:
            return True

        return False

    # ─── Extraction pipeline ────────────────────────────────────────────

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

        try:
            from magika import Magika
            magika = Magika()
        except Exception as e:
            self.log.error(f"Failed to initialize Magika for {self.hash.sha256}: {e}")
            magika = None

        self.resources = []
        self.suspicious_files = []
        scanned = 0

        zf = self._get_zip_file()
        if not zf:
            return None

        with zf:
            for info in zf.infolist():
                if info.is_dir():
                    continue
                if not (info.filename.startswith("res/") or
                        info.filename.startswith("assets/")):
                    continue

                if scanned >= MAX_RESOURCE_FILES:
                    self.log.warning(
                        f"Resource scan limit reached ({MAX_RESOURCE_FILES}), "
                        f"stopping resource enumeration"
                    )
                    break
                scanned += 1

                try:
                    data = zf.read(info.filename)
                except Exception as e:
                    self.log.warning(
                        f"Error reading resource {info.filename}: {e}"
                    )
                    continue

                try:
                    file_sha256 = hashlib.sha256(data).hexdigest()
                    file_entropy = round(self.calculate_entropy(data), 3)

                    # Read first bytes for Android-specific format detection
                    header = data[:16] if len(data) >= 16 else data

                    if magika:
                        try:
                            filetype = magika.identify_bytes(data).output.label
                        except Exception:
                            filetype = "unknown"
                    else:
                        filetype = "unknown"

                    # Identify Android-specific formats once, reuse for
                    # both stored type and suspicion classification
                    android_type = self._identify_android_format(header)
                    stored_type = android_type if android_type else filetype

                    suspicious = self._is_suspicious_resource(
                        path=info.filename,
                        magika_type=filetype,
                        entropy=file_entropy,
                        android_type=android_type,
                    )

                    resource = APKResource(
                        path=info.filename,
                        size=info.file_size,
                        sha256=file_sha256,
                        filetype_magika=stored_type,
                        entropy=file_entropy,
                    )

                    if suspicious:
                        resource.is_suspicious = True
                        self.suspicious_files.append(resource)

                    self.resources.append(resource)
                except Exception as e:
                    self.log.warning(
                        f"Error processing resource {info.filename}: {e}"
                    )
                    continue

        if not self.resources:
            return None

        return {
            "total_resource_count": len(self.resources),
            "total_resource_size": sum(r.size for r in self.resources),
            "suspicious_file_count": len(self.suspicious_files),
            "resources": self.resources,
            "suspicious_files": self.suspicious_files,
        }

    # ─── Export ──────────────────────────────────────────────────────────

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

            current_time = datetime.now(timezone.utc)
            data = []
            for res in self.resources:
                data.append([
                    self.sha256,
                    res.path,
                    res.size,
                    res.sha256,
                    res.filetype_magika,
                    res.entropy,
                    int(res.is_suspicious),
                    current_time,
                ])

            column_names = [
                'sha256', 'resource_path', 'resource_size',
                'resource_sha256', 'resource_magika', 'resource_entropy',
                'is_suspicious', 'analysis_date',
            ]

            column_type_names = [
                'FixedString(64)', 'String', 'UInt64',
                'FixedString(64)', 'LowCardinality(String)', 'Float32',
                'UInt8', "DateTime64(3, 'UTC')",
            ]

            return (data, column_names, column_type_names)

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