Carlos R. Baier

65 papers C 27Journal 24Unranked 14
YearRankTypeTitle / Venue / Authors
2026 J jnl
Internet Things
Francisco Jose Sánchez Sutil, Antonio Cano Ortega, Jesús C. Hernández, Carlos Gilabert-Torres, Carlos R. Baier
2025 J jnl
IEEE Trans. Ind. Informatics
Roberto M. Fuentes, Esteban I. Marciel, Carlos R. Baier, Gabriela Werner Gabriel, Cecília F. Morais, Márcio J. Lacerda, Jonathan M. Palma
2025 J jnl
IEEE Access
Carlos A. Munoz, Carlos R. Baier, Jesús C. Hernández, Esteban I. Marciel, Pedro E. Melin
2024 J jnl
IEEE Trans. Ind. Electron.
Alvaro Carreno, Mariusz Malinowski, Marcelo A. Pérez, Carlos R. Baier
2024 J jnl
IEEE Access
Eduardo E. Espinosa, Matías Veillón, Christian A. Rojas, Jesús C. Hernández, Pedro E. Melin, Galina Mirzaeva, Carlos R. Baier, Roberto O. Ramírez, Federico Martin Serra, Mauricio Arenas
2024 J jnl
Sensors
Matías Veillón, Eduardo E. Espinosa, Pedro E. Melin, Galina Mirzaeva, Marco Rivera, Carlos R. Baier, Roberto O. Ramírez
2023 J jnl
IEEE Access
Carlos R. Baier, Felipe A. Villarroel, Miguel A. Torres, Marcelo A. Pérez, Jesús C. Hernández, Eduardo E. Espinosa
2023 J jnl
Sensors
Carlos R. Baier, Jesús C. Hernández, Patrick Wheeler
2023 J jnl
Sensors
Ricardo Pérez, Marco Rivera, Yamisleydi Salgueiro, Carlos R. Baier, Patrick Wheeler
2023 conf
ICIT
Eduardo E. Espinosa, Matías Veillón, Pedro E. Melin, Carlos R. Baier, José R. Espinoza, Jesús C. Hernández
2022 J jnl
IEEE Access
Felipe A. Villarroel, José R. Espinoza, Marcelo A. Pérez, Carlos R. Baier, Jaime Addin Rohten, Roberto O. Ramírez, Esteban S. Pulido, José J. Silva
2022 C conf
IECON
Eduardo E. Espinosa, Matías Veillón, Pedro E. Melin, Carlos R. Baier, Javier Muñoz, José R. Espinoza, Jesús C. Hernández
2022 C conf
IECON
Felipe Villarroel, José R. Espinoza, Marcelo A. Pérez, Daniel G. Sbarbaro-Hofer, Roberto O. Ramírez, Carlos R. Baier
2022 J jnl
Sensors
Manuel Diaz-Bustos, Carlos R. Baier, Miguel A. Torres, Pedro E. Melin, Pablo Acuña
2022 J jnl
IEEE Access
Pedro E. Melin, Carlos R. Baier, Eduardo E. Espinosa, Javier Riedemann, José R. Espinoza, Rubén Peña
2021 J jnl
IEEE Access
Eduardo E. Espinosa, Pedro E. Melin, Hugo O. Garcés, Carlos R. Baier, José R. Espinoza
2020 J jnl
IEEE Access
Roberto O. Ramírez, Carlos R. Baier, Felipe Villarroel, José R. Espinoza, Josep Pou, José Rodríguez
2020 J jnl
Sensors
Jesús C. Hernández, Francisco Jose Sánchez Sutil, Antonio Cano Ortega, Carlos R. Baier
2020 C conf
IECON
Alvaro Carreno, Marcelo A. Pérez, Carlos R. Baier, José R. Espinoza
2020 J jnl
IEEE Access
Miguel A. Torres, Reinaldo Tonkoski, Carlos R. Baier
2019 C conf
IECON
Manuel A. Díaz, Carlos R. Baier, Felipe Rojas, Alejandro Garcés, Miguel A. Torres, Marcelo A. Pérez
2019 C conf
IECON
Pedro E. Melin, Johan I. Guzman, Carlos R. Baier, Eduardo E. Espinosa, Ricardo Lizana, Ramón Blasco Giménez, Xiaoqiang Guo
2019 C conf
IECON
Alvaro Carreno, Marcelo A. Pérez, Carlos R. Baier, José R. Espinoza
2019 C conf
IECON
Rodrigo Morales, Matías Garbarino, Javier A. Muñoz, Carlos R. Baier, Jaime Addin Rohten, Vladimir Esparza, David Dewar
2019 C conf
IECON
Carlos R. Baier, Miguel A. Torres, Marcelo A. Pérez, Roberto Cárdenas, Roberto O. Ramírez, Pedro E. Melin
2019 C conf
IECON
Felipe Villarroel, José R. Espinoza, Marcelo A. Pérez, Roberto O. Ramírez, Carlos R. Baier, Luis Morán
2018 C conf
IECON
José J. Silva, José R. Espinoza, Miguel A. Torres, Jaime Addin Rohten, Carlos R. Baier, Javier A. Muñoz
2018 C conf
IECON
Pedro E. Melin, Johan I. Guzman, F. A. Hernandez, Carlos R. Baier, Javier A. Muñoz, José R. Espinoza, M. I. Gonzalez, Eduardo E. Espinosa
2017 J jnl
IEEE Trans. Ind. Electron.
Pablo Acuña, Ricardo P. Aguilera, Amer M. Y. M. Ghias, Marco Rivera, Carlos R. Baier, Vassilios G. Agelidis
2016 C conf
IECON
Roberto O. Ramírez, José R. Espinoza, Carlos R. Baier
2015 conf
ICIT
Marco Rivera, Fernando Morales, Carlos R. Baier, Javier A. Muñoz, Luca Tarisciotti, Pericle Zanchetta, Pat Wheeler
2015 conf
ISIE
Carlos R. Baier, Miguel A. Torres, Javier A. Muñoz, Marco E. Rivera, Eduardo E. Espinosa, Pablo Acuña
2015 conf
ISIE
Miguel A. Torres, Carlos R. Baier
2015 conf
ISIE
Javier Muñoz, Jaime Addin Rohten, Carlos R. Baier, Marco Rivera, Eduardo E. Espinosa, Roberto O. Ramírez
2015 conf
ICIT
Juan M. Mauricio, Miguel A. Torres, Carlos R. Baier, José Silva
2015 conf
ICIT
Miguel A. Torres, Carlos R. Baier, Juan M. Mauricio, José Silva
2015 conf
ICIT
Carlos R. Baier, Miguel A. Torres, Javier A. Muñoz, Juan M. Mauricio, Jaime Addin Rohten, Marco Rivera
2015 conf
ICIT
Jaime Addin Rohten, José R. Espinoza, José J. Silva, Javier Muñoz, Daniel Sbarbaro, Carlos R. Baier, Eduardo E. Espinosa
2015 conf
ISIE
Marco Rivera, Marcelo A. Pérez, Carlos R. Baier, Javier A. Muñoz, Venkata Yaramasu, Bin Wu, Luca Tarisciotti, Pericle Zanchetta, Pat Wheeler
2015 conf
ICIT
Javier A. Muñoz, Jaime Addin Rohten, José R. Espinoza, Pedro E. Melin, Carlos R. Baier, Marco Rivera
2014 C conf
IECON
Pedro E. Melin, José R. Espinoza, Jaime Addin Rohten, Eduardo E. Espinosa, Carlos R. Baier, Johan I. Guzman
2014 J jnl
IEEE Trans. Ind. Electron.
Javier A. Muñoz, José R. Espinoza, Carlos R. Baier, Luis Morán, Johan I. Guzman, Victor M. Cárdenas
2014 conf
ISIE
Jaime Addin Rohten, José R. Espinoza, Felipe Villarroel, Javier A. Muñoz, Pedro E. Melin, Carlos R. Baier, Marcelo A. Pérez
2014 J jnl
IEEE Trans. Ind. Electron.
Carlos R. Baier, José R. Espinoza, Marco Rivera, Javier A. Muñoz, Bin Wu, Pedro E. Melin, Venkata Yaramasu
2014 C conf
IECON
Miguel A. Torres, Carlos R. Baier, José J. Silva, José R. Espinoza
2014 conf
ISIE
Javier Muñoz, Carlos R. Baier, José R. Espinoza, Eduardo E. Espinosa, Johan I. Guzman, Marco Rivera
2014 C conf
IECON
Johan I. Guzman, Marcelo A. Pérez, Pedro E. Melin, José R. Espinoza, Carlos R. Baier
2014 C conf
IECON
Jaime Addin Rohten, Pedro E. Melin, José R. Espinoza, José J. Silva, Eduardo E. Espinosa, Javier Muñoz, Carlos R. Baier
2014 conf
ISIE
Marco Rivera, José R. Rodríguez, José R. Espinoza, Alejandro Olloqui, Pat Wheeler, Pericle Zanchetta, Carlos R. Baier, Javier A. Muñoz
2014 C conf
IECON
Carlos R. Baier, Miguel A. Torres, Javier A. Muñoz, Johan I. Guzman, Pedro E. Melin, Jaime Addin Rohten, Marco Rivera
2013 C conf
IECON
Carlos R. Baier, Pedro E. Melin, Johan I. Guzman, Marco Rivera, Javier A. Muñoz, Jaime Rothen, José R. Espinoza
2013 J jnl
IEEE Trans. Ind. Informatics
Johan I. Guzman, Pedro E. Melin, José R. Espinoza, Luis Morán, Carlos R. Baier, Javier A. Muñoz, Gonzalo A. Guinez
2013 J jnl
IEEE Trans. Ind. Informatics
Christian Alberto Garcia-Sepulveda, Javier A. Muñoz, José R. Espinoza, Miguel E. Figueroa, Carlos R. Baier
2013 C conf
IECON
Eduardo E. Espinosa, José R. Espinoza, Roberto O. Ramírez, Marcelo E. Reyes, Pedro E. Melin, Javier Muñoz, Carlos R. Baier
2013 C conf
IECON
Pedro E. Melin, Carlos R. Baier, José R. Espinoza, Javier A. Muñoz, Roberto O. Ramírez, Eduardo A. Maurelia
2013 C conf
IECON
Jaime Addin Rohten, José R. Espinoza, Felipe Villarroel, Javier A. Muñoz, Carlos R. Baier, Pedro E. Melin, Daniel Sbarbaro
2013 C conf
IECON
P. Zavala, Marco Rivera, Samir Kouro, José Rodríguez, Bin Wu, Venkata Yaramasu, Carlos R. Baier, Javier A. Muñoz, José R. Espinoza, Pedro E. Melin
2013 C conf
IECON
Javier A. Muñoz, Carlos R. Baier, José R. Espinoza, Marco Rivera, Johan I. Guzman, Jaime Addin Rohten
2012 C conf
IECON
Javier A. Muñoz, José R. Espinoza, Carlos R. Baier, Luis Morán, Johan I. Guzman, Jaime Addin Rohten
2012 C conf
IECON
Johan I. Guzman, Carlos R. Baier, José R. Espinoza, Pedro E. Melin, Javier A. Muñoz
2012 J jnl
IEEE Trans. Ind. Electron.
Javier A. Muñoz, José R. Espinoza, Carlos R. Baier, Luis Morán, Eduardo E. Espinosa, Pedro E. Melin, Daniel G. Sbarbaro
2012 C conf
IECON
Pedro E. Melin, José R. Espinoza, Carlos R. Baier, Jaime Addin Rohten, Roberto O. Ramírez, Luis A. Morán
2012 C conf
IECON
Carlos R. Baier, Javier A. Muñoz, Johan I. Guzman, José R. Espinoza, Pedro E. Melin
2010 J jnl
IEEE Trans. Ind. Electron.
Carlos R. Baier, José R. Espinoza, Javier A. Muñoz, Luis Morán, Pedro E. Melin
2007 J jnl
IEEE Trans. Ind. Electron.
Carlos R. Baier, Johan I. Guzman, José R. Espinoza, Marcelo A. Pérez, José R. Rodríguez
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"