Rainer Stotzka

50 papers B 4C 5Misc 2Journal 6Unranked 33
YearRankTypeTitle / Venue / Authors
2021 conf
DAMDID/RCDL (Supplementary Proceedings)
Reetu Joseph, Aditya Chauhan, Catriona Eschke, Ahmad Zainul Ihsan, Mehrdad Jalali, Ute Jäntsch, Nicole Jung, C. N. Shyam Kumar, Christian Kübel, Christian Lucas, Matthias Mail, Andrey Mazilkin, Charlotte Neidiger, Mirco Panighel, Stefan Sandfeld, Rainer Stotzka, Richard Thelen, Rossella Aversa
2018 J jnl
Distributed Parallel Databases
Ajinkya Prabhune, Rainer Stotzka, Vaibhav Sakharkar, Jürgen Hesser, Michael Gertz
2018 J jnl
Distributed Parallel Databases
Ajinkya Prabhune, Aaron Zweig, Rainer Stotzka, Jürgen Hesser, Michael Gertz
2017 Misc conf
ICCS
Richard Grunzke, Maximilian Neumann, Thomas Ilsche, Volker Hartmann, Thomas Jejkal, Rainer Stotzka, Andreas Knüpfer, Wolfgang E. Nagel
2017 conf
DHd
Philipp Hegel, Danah Tonne, Albert Geukes, Michael Krewet, Andrea Rapp, Rainer Stotzka, Gyburg Uhlmann
2017 conf
HEALTHINF
Ajinkya Prabhune, Rainer Stotzka, Michael Gertz, Lei Zheng, Jürgen Hesser
2017 J jnl
PeerJ Prepr.
Richard Grunzke, Volker Hartmann, Thomas Jejkal, Ajinkya Prabhune, Hendrik Herold, Aline Deicke, Alexander Hoffmann, Torsten Schrade, Gotthard Meinel, Sonja Herres-Pawlis, Rainer Stotzka, Wolfgang E. Nagel
2016 Misc conf
Visualization and Data Analysis
Swati Chandna, Danah Tonne, Rainer Stotzka, Hannah Busch, Philipp Vanscheidt, Celia Krause
2016 J jnl
Autom.
Johannes Stegmaier, Benjamin Schott, Eduard Hübner, Manuel Traub, Maryam Shahid, Masanari Takamiya, Andrei Kobitski, Volker Hartmann, Rainer Stotzka, Jos van Wezel, Achim Streit, G. Ulrich Nienhaus, Uwe Strähle, Markus Reischl, Ralf Mikut
2016 conf
IEEE BigData
Ajinkya Prabhune, Hasebullah Ansari, Anil Keshav, Rainer Stotzka, Michael Gertz, Jürgen Hesser
2016 conf
IPAW
Ajinkya Prabhune, Aaron Zweig, Rainer Stotzka, Michael Gertz, Jürgen Hesser
2016 conf
LDAV
Swati Chandna, Francesca Rindone, Carsten Dachsbacher, Rainer Stotzka
2016 conf
IWSG
Richard Grunzke, Volker Hartmann, Thomas Jejkal, Ajinkya Prabhune, Hendrik Herold, Aline Deicke, Alexander Hoffmann, Torsten Schrade, Gotthard Meinel, Sonja Herres-Pawlis, Rainer Stotzka, Wolfgang E. Nagel
2015 conf
BigDataService
Ajinkya Prabhune, Rainer Stotzka, Thomas Jejkal, Volker Hartmann, Margund Bach, Eberhard Schmitt, Michael Hausmann, Jürgen Hesser
2015 conf
DRR
Swati Chandna, Danah Tonne, Thomas Jejkal, Rainer Stotzka, Celia Krause, Philipp Vanscheidt, Hannah Busch, Ajinkya Prabhune
2014 J jnl
Microprocess. Microsystems
Diana Goehringer, Hamid Sarbazi-Azad, Rainer Stotzka
2013 C conf
PDP
Xiaoli Yang, Thomas Jejkal, Halil Pasic, Rainer Stotzka, Achim Streit, Jos van Wezel, Tomy dos Santos Rolo
2012 C conf
PDP
Danah Tonne, Rainer Stotzka, Thomas Jejkal, Volker Hartmann, Halil Pasic, Andrea Rapp, Philipp Vanscheidt, Bernhard Neumair, Achim Streit, Ariel García, Daniel Kurzawe, Tibor Kálmán, Jedrzej Rybicki, Beatriz Sanchez Bribian
2012 J jnl
CoRR
Jos van Wezel, Achim Streit, Christopher Jung, Rainer Stotzka, Silke Halstenberg, Fabian Rigoll, Ariel García, Andreas Heiss, Kilian Schwarz, Martin Gasthuber, André Giesler
2012 C conf
PDP
Thomas Jejkal, Volker Hartmann, Rainer Stotzka, Jens C. Otte, Ariel García, Jos van Wezel, Achim Streit
2012 C ed.
PDP
Rainer Stotzka, Michael Schiffers, Yannis Cotronis
2011 conf
LDAV
A. O. García, Serguei Bourov, Ahmad Hammad, Volker Hartmann, Thomas Jejkal, Jens C. Otte, Sven Pfeiffer, T. Schenker, Christian Schmidt, Patrick Neuberger, Rainer Stotzka, Jos van Wezel, Bernhard Neumair, Achim Streit
2011 C conf
PDP
Rainer Stotzka, Volker Hartmann, Thomas Jejkal, Michael Sutter, Jos van Wezel, Marcus Hardt, Ariel García, Rainer Kupsch, Serguei Bourov
2011 conf
IPDPS Workshops
Ariel García, Serguei Bourov, Ahmad Hammad, Jos van Wezel, Bernhard Neumair, Achim Streit, Volker Hartmann, Thomas Jejkal, Patrick Neuberger, Rainer Stotzka
2008 conf
EUROMICRO-SEAA
Thomas Jejkal, Rainer Stotzka, Michael Sutter
2008 conf
Bildverarbeitung für die Medizin
Alexander Frank, Rainer Stotzka, Thomas Jejkal, Volker Hartmann, Michael Sutter, Nicole V. Ruiter, Michael Zapf
2007 conf
EUROMICRO-SEAA
Alexander Frank, Rainer Stotzka, Thomas Jejkal, Volker Hartmann, Michael Sutter, Hartmut Gemmeke
2006 B conf
e-Science
Tim O. Müller, Thomas Jejkal, Rainer Stotzka, Michael Sutter, Volker Hartmann, Hartmut Gemmeke
2005 conf
Bildverarbeitung für die Medizin
Michael Beller, Rainer Stotzka, Tim O. Müller, Hartmut Gemmeke
2005 conf
Bildverarbeitung für die Medizin
Rainer Stotzka, Nicole V. Ruiter, Tim O. Müller, R. Liu, Klaus Schlote-Holubek, Georg Göbel, Hartmut Gemmeke
2005 conf
Bildverarbeitung für die Medizin
Nicole V. Ruiter, Tim O. Müller, Rainer Stotzka, Hartmut Gemmeke
2005 conf
Bildverarbeitung für die Medizin
Tim O. Müller, Nicole V. Ruiter, Rainer Stotzka, Michael Beller, Wolfgang Eppler, Hartmut Gemmeke
2004 conf
Bildverarbeitung für die Medizin
Jorge F. Silva G., Rainer Stotzka, Nicole V. Ruiter, Peter Uetz
2004 conf
Bildverarbeitung für die Medizin
Nicole V. Ruiter, Tim O. Müller, Rainer Stotzka, Hartmut Gemmeke, Jürgen R. Reichenbach, Werner A. Kaiser
2004 conf
Bildverarbeitung für die Medizin
Michael Beller, Rainer Stotzka, Hartmut Gemmeke
2004 conf
Bildverarbeitung für die Medizin
Tim O. Müller, Rainer Stotzka, Michael Beller, Nicole V. Ruiter, Volker Hartmann
2004 conf
Bildverarbeitung für die Medizin
Rainer Stotzka, Tim O. Müller, Klaus Schlote-Holubek, Georg Göbel
2003 conf
Bildverarbeitung für die Medizin
Rainer Stotzka, Tim O. Müller, Klaus Schlote-Holubek, Thomas M. Deck, Susan Vaziri Elahi, Georg Göbel, Hartmut Gemmeke
2003 conf
Bildverarbeitung für die Medizin
Michael Beller, Rainer Stotzka, Hartmut Gemmeke, Karl-Friedrich Weibezahn, Gudrun Knedlitschek
2003 conf
Bildverarbeitung für die Medizin
Nicole V. Ruiter, Tim O. Müller, Rainer Stotzka, Hartmut Gemmeke, Jürgen R. Reichenbach, Werner A. Kaiser
2003 conf
CARS
Thomas Böttger, Nicole V. Ruiter, Rainer Stotzka, Rolf Bendl, Klaus K. Herfarth
2003 conf
Bildverarbeitung für die Medizin
Thomas Böttger, Nicole V. Ruiter, Rainer Stotzka, Rolf Bendl, Klaus K. Herfarth
2003 conf
Bildverarbeitung für die Medizin
Thomas M. Deck, Tim O. Müller, Rainer Stotzka, Hartmut Gemmeke
2001 conf
Bildverarbeitung für die Medizin
Nicole V. Ruiter, Tim O. Müller, Rainer Stotzka
2001 conf
Bildverarbeitung für die Medizin
Tim O. Müller, Rainer Stotzka, Dieter Höpfel, H. Yang
2000 B conf
Image Processing
Rainer Stotzka
1999 B conf
Image Processing
Rainer Stotzka, Jürgen Haase, Tim Oliver Müller
1998 conf
Digital Mammography / IWDM
Rainer Stotzka, Tim O. Müller, Wolfgang Eppler, Hartmut Gemmeke
1998 B conf
Image Processing
Rainer Stotzka, Tim Oliver Müller, Wolfgang Eppler, Hartmut Gemmeke
1998 conf
Digital Mammography / IWDM
Tim O. Müller, Rainer Stotzka, A. Hochmuth, Wolfgang Eppler, Hartmut Gemmeke
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"