Vadim Azhmyakov

62 papers C 12Journal 22Unranked 28
YearRankTypeTitle / Venue / Authors
2025 J jnl
J. Frankl. Inst.
Vadim Azhmyakov, Warodom Werapun, Jakapan Suaboot
2024 C conf
CoDIT
Vadim Azhmyakov, Luz Adriana Guzman Trujillo, Ilya Shirokov
2023 C conf
CoDIT
Vadim Azhmyakov, Luz Adriana Guzman Trujillo, Fabian Sanchez Salazar, Ilya Shirokov
2022 J jnl
J. Frankl. Inst.
Vadim Azhmyakov, Erik I. Verriest, Moisés E. Bonilla, Stefan Pickl
2022 J jnl
IMA J. Math. Control. Inf.
Moisés E. Bonilla, N. A. Aguillón, Marco Antonio Ortiz Castillo, Jean Jacques Loiseau, Michel Malabre, Vadim Azhmyakov, Sergio Salazar
2021 conf
ECC
N. A. Aguillón, Moisés E. Bonilla, Sergio Salazar, Michel Malabre, Vadim Azhmyakov
2021 conf
ECC
L. A. Blas, Moisés E. Bonilla, Sergio Salazar, Michel Malabre, Vadim Azhmyakov
2020 conf
CDC
Vadim Azhmyakov, Erik I. Verriest, Camilo Londoño, Raymundo Juarez del Toro
2020 conf
CCE
Raymundo Juarez del Toro, Vadim Azhmyakov, Manuel Mera Hernandez, Francisco G. Salas Pérez
2020 J jnl
IMA J. Math. Control. Inf.
Raymundo Juarez, Vadim Azhmyakov, A. Tadeo Espinoza, Francisco G. Salas
2020 J jnl
J. Frankl. Inst.
Moisés E. Bonilla, L. A. Blas, Vadim Azhmyakov, Michel Malabre, Sergio Salazar
2019 conf
CDC
Vadim Azhmyakov, Magnus Egerstedt, Erik I. Verriest
2019 conf
ECC
L. A. Blas, Moisés E. Bonilla, Sergio Salazar, Michel Malabre, Vadim Azhmyakov
2018 conf
CDC
Vadim Azhmyakov, Erik I. Verriest, Luz Adriana Guzman Trujillo, Stefan Wolfgang Pickl
2017 conf
CDC
Erik I. Verriest, Vadim Azhmyakov
2016 conf
CCE
Vadim Azhmyakov, Raymundo Juarez, Suresh Kumar Gadi, Luz Adriana Guzman Trujillo
2016 C conf
ACC
Vadim Azhmyakov, Moisés E. Bonilla, Stefan Pickl, Luz Adriana Guzman Trujillo
2016 conf
CDC
Vadim Azhmyakov, Aftab Ahmed, Erik I. Verriest
2016 conf
CCE
Raymundo Juarez, Vadim Azhmyakov, Suresh Kumar Gadi, Francisco G. Salas
2015 conf
ECC
Moisés Bonilla Estrada, Michel Malabre, Vadim Azhmyakov
2015 conf
ADHS
Vadim Azhmyakov, Raymundo Juarez del Toro
2015 C conf
ACC
Vadim Azhmyakov, Javier Cabrera Martinez, Alexander S. Poznyak, Ruthber Rodriguez Serrezuela
2015 J jnl
IMA J. Math. Control. Inf.
Carlos Perez, Vadim Azhmyakov, Alexander S. Poznyak
2014 J jnl
J. Frankl. Inst.
M. Mehrpouya, Mostafa Shamsi, Vadim Azhmyakov
2014 C conf
IECON
Vadim Azhmyakov, Ruthber Rodriguez Serrezuela, Luz Adriana Guzman Trujillo
2014 J jnl
J. Frankl. Inst.
Vadim Azhmyakov, Andrey Polyakov, Alex Poznyak
2014 conf
ECC
Moisés E. Bonilla, Nohemi Jarquin-Alvarez, Michel Malabre, Vadim Azhmyakov
2014 J jnl
Kybernetika
Arturo Enrique Gil García, Vadim Azhmyakov, Michael V. Basin
2013 J jnl
J. Frankl. Inst.
Vadim Azhmyakov, Alex Poznyak, Raymundo Juarez del Toro
2013 conf
CASE
Javier Cabrera Martinez, Vadim Azhmyakov
2012 J jnl
Discret. Event Dyn. Syst.
Vadim Azhmyakov, Michael V. Basin, Jörg Raisch
2012 C conf
CCA
Vadim Azhmyakov, Michael V. Basin, Arturo Enrique Gil García
2012 conf
CCE
Manuel Mera, Alex Poznyak, Vadim Azhmyakov, Andrei Polyakov
2012 C conf
ACC
Vadim Azhmyakov, Alex Poznyak
2012 conf
ADHS
Vadim Azhmyakov, Félix A. Miranda-Villatoro
2012 conf
CCE
Carlos Manuel Perez, Alexander S. Poznyak, Vadim Azhmyakov
2012 J jnl
J. Frankl. Inst.
Vadim Azhmyakov
2012 conf
CCE
Arturo Enrique Gil García, Vadim Azhmyakov, Michael V. Basin
2012 conf
CCE
Raymundo Juarez del Toro, Vadim Azhmyakov, Alexander S. Poznyak
2011 J jnl
IMA J. Math. Control. Inf.
Vadim Azhmyakov
2011 J jnl
Int. J. Syst. Sci.
Vadim Azhmyakov, Marco Tulio Angulo
2011 conf
CCE
Raymundo Juarez, Alexander S. Poznyak, Vadim Azhmyakov
2011 conf
CDC/ECC
Vadim Azhmyakov
2011 C conf
ACC
Rosalba Galván-Guerra, Vadim Azhmyakov, Magnus Egerstedt
2011 J jnl
Int. J. Control
Alex Poznyak, Vadim Azhmyakov, Manuel Mera
2010 J jnl
Eur. J. Control
Vadim Azhmyakov, Rosalba Galván-Guerra, Ruben Velazquez, Alan Solon Ivor Zinober
2010 conf
CCE
Rosalba Galván-Guerra, Juan Eduardo Velázquez-Velázquez, Vadim Azhmyakov
2010 conf
WODES
Vadim Azhmyakov, Ruben Velazquez, Rosalba Galván-Guerra
2010 J jnl
Discret. Event Dyn. Syst.
Sid Ahmed Attia, Vadim Azhmyakov, Jörg Raisch
2010 C conf
ACC
Vadim Azhmyakov, Rosalba Galván-Guerra, Magnus Egerstedt
2010 J jnl
J. Frankl. Inst.
Vadim Azhmyakov, Rosalba Galván-Guerra, Alex Poznyak
2009 conf
ADHS
Vadim Azhmyakov, Magnus Egerstedt, Leonid M. Fridman, Alex Poznyak
2009 J jnl
J. Appl. Math.
Vadim Azhmyakov
2009 C conf
ACC
Vadim Azhmyakov, Rosalba Galván-Guerra, Magnus Egerstedt
2008 J jnl
IEEE Trans. Autom. Control.
Vadim Azhmyakov, Jörg Raisch
2008 C conf
ACC
Vadim Azhmyakov, Vladimir G. Boltyanski, Alexander S. Poznyak
2008 conf
HSCC
Vadim Azhmyakov, Sid Ahmed Attia, Jörg Raisch
2007 conf
HSCC
Vadim Azhmyakov, Sid Ahmed Attia, Dmitry Gromov, Jörg Raisch
2007 C conf
CCA
Sid Ahmed Attia, Vadim Azhmyakov, Jörg Raisch
2006 conf
ADHS
Vadim Azhmyakov, Jörg Raisch
2003 J jnl
Math. Methods Oper. Res.
Vadim Azhmyakov, Werner H. Schmidt
2002 J jnl
Informatica
Vadim Azhmyakov
redb/extractors/apk_extractors/apk_inconsistency_tests.py
← Index redb/extractors/apk_extractors/apk_inconsistency_tests.py python
import inspect
import re
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 APKInconsistencyTests

# Emulator detection indicator strings
EMULATOR_INDICATORS = {
    "generic", "sdk", "google_sdk", "Emulator",
    "goldfish", "ranchu", "Andy", "Genymotion",
    "BlueStacks", "nox", "ttVM_Hdragon",
}

# Root detection indicator strings
ROOT_INDICATORS = {
    "/system/app/Superuser.apk",
    "/system/xbin/su",
    "/system/bin/su",
    "com.noshufou.android.su",
    "com.thirdparty.superuser",
    "eu.chainfire.supersu",
    "com.koushikdutta.superuser",
    "com.topjohnwu.magisk",
}

# Standard DEX filename pattern
STANDARD_DEX_PATTERN = re.compile(r"^classes\d*\.dex$")


class APKInconsistencyTestsExtractor(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.test_results = None
        self.log.debug(inspect.currentframe().f_code.co_name)

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

    def _test_zip_bomb(self):
        """Check if any ZIP entry has compression ratio > 100:1."""
        try:
            zf = self._get_zip_file()
            if not zf:
                return None
            with zf:
                for info in zf.infolist():
                    if info.compress_size > 0:
                        ratio = info.file_size / info.compress_size
                        if ratio > 100:
                            return True
            return False
        except Exception as e:
            self.log.warning(f"Error in zip bomb test: {e}")
            return None

    def _test_zip_duplicate_entries(self):
        """Check for duplicate filenames in ZIP directory."""
        try:
            zf = self._get_zip_file()
            if not zf:
                return None
            with zf:
                names = [info.filename for info in zf.infolist()]
                return len(names) != len(set(names))
        except Exception as e:
            self.log.warning(f"Error in duplicate entries test: {e}")
            return None

    def _test_zip_path_traversal(self):
        """Check for path traversal (../) in ZIP entry names."""
        try:
            for f in self._list_files():
                if ".." in f or f.startswith("/"):
                    return True
            return False
        except Exception as e:
            self.log.warning(f"Error in path traversal test: {e}")
            return None

    def _test_zip_suspicious_timestamps(self):
        """Check for timestamps at epoch (1980) or in the future."""
        try:
            zf = self._get_zip_file()
            if not zf:
                return None
            now = datetime.now()
            with zf:
                for info in zf.infolist():
                    try:
                        dt = datetime(*info.date_time)
                        if dt.year <= 1980 or dt > now:
                            return True
                    except (ValueError, TypeError):
                        continue
            return False
        except Exception as e:
            self.log.warning(f"Error in suspicious timestamps test: {e}")
            return None

    def _test_hidden_dex_files(self):
        """Check for DEX files not matching classes*.dex pattern."""
        try:
            for f in self._list_files():
                if f.endswith(".dex"):
                    basename = f.split("/")[-1]
                    if not STANDARD_DEX_PATTERN.match(basename):
                        return True
            return False
        except Exception as e:
            self.log.warning(f"Error in hidden DEX files test: {e}")
            return None

    def _test_manifest_component_mismatch(self):
        """Check for declared components that don't exist in DEX."""
        try:
            if not self._is_valid_apk():
                return None

            # Get all class names from DEX
            dex_classes = set()
            try:
                from androguard.core.dex import DEX
                for dex_data in (self.apk.get_all_dex() or []):
                    try:
                        d = DEX(dex_data)
                        for cls in d.get_classes():
                            name = cls.get_name()
                            if name:
                                # Convert "Lcom/example/Foo;" to "com.example.Foo"
                                dex_classes.add(
                                    name[1:-1].replace("/", ".") if name.startswith("L") else name
                                )
                    except Exception:
                        continue
            except Exception:
                return None

            if not dex_classes:
                return None

            # Check manifest components against DEX classes
            components = []
            try:
                components.extend(self.apk.get_activities() or [])
                components.extend(self.apk.get_services() or [])
                components.extend(self.apk.get_receivers() or [])
                components.extend(self.apk.get_providers() or [])
            except Exception:
                return None

            for comp in components:
                if comp and comp not in dex_classes:
                    # Component might use a shorthand; check with package prefix
                    package = self.apk.get_package() or ""
                    full_name = package + comp if comp.startswith(".") else comp
                    if full_name not in dex_classes:
                        return True

            return False
        except Exception as e:
            self.log.warning(f"Error in manifest component mismatch test: {e}")
            return None

    def _test_debuggable_release(self):
        """Check android:debuggable=true combined with a release signature."""
        try:
            if not self._is_valid_apk():
                return None

            is_debuggable = self.apk.get_attribute_value(
                "application", "debuggable"
            ) == "true"

            if not is_debuggable:
                return False

            # Check if it has a signing certificate (release builds have certs)
            try:
                certs = self.apk.get_certificates()
                if certs and len(certs) > 0:
                    return True
            except Exception:
                pass

            return False
        except Exception as e:
            self.log.warning(f"Error in debuggable release test: {e}")
            return None

    def _get_dex_strings(self):
        """Get all string constants from DEX files."""
        all_strings = set()
        try:
            from androguard.core.dex import DEX
            for dex_data in (self.apk.get_all_dex() or []):
                try:
                    d = DEX(dex_data)
                    for s in d.get_strings():
                        if s:
                            all_strings.add(s)
                except Exception:
                    continue
        except Exception:
            pass
        return all_strings

    def _test_emulator_detection_strings(self):
        """Check for emulator detection patterns in DEX strings."""
        try:
            if not self._is_valid_apk():
                return None

            dex_strings = self._get_dex_strings()
            for indicator in EMULATOR_INDICATORS:
                for s in dex_strings:
                    if indicator in s:
                        return True
            return False
        except Exception as e:
            self.log.warning(f"Error in emulator detection test: {e}")
            return None

    def _test_debugger_detection(self):
        """Check for debugger detection API calls in DEX."""
        try:
            if not self._is_valid_apk():
                return None

            dex_strings = self._get_dex_strings()
            debugger_patterns = {
                "isDebuggerConnected",
                "waitingForDebugger",
                "Debug.isDebuggerConnected",
            }
            for pattern in debugger_patterns:
                for s in dex_strings:
                    if pattern in s:
                        return True
            return False
        except Exception as e:
            self.log.warning(f"Error in debugger detection test: {e}")
            return None

    def _test_root_detection(self):
        """Check for root detection patterns in DEX."""
        try:
            if not self._is_valid_apk():
                return None

            dex_strings = self._get_dex_strings()
            for indicator in ROOT_INDICATORS:
                for s in dex_strings:
                    if indicator in s:
                        return True
            return False
        except Exception as e:
            self.log.warning(f"Error in root detection test: {e}")
            return None

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

        self.test_results = APKInconsistencyTests(
            test_zip_bomb=self._test_zip_bomb(),
            test_zip_duplicate_entries=self._test_zip_duplicate_entries(),
            test_zip_path_traversal=self._test_zip_path_traversal(),
            test_zip_suspicious_timestamps=self._test_zip_suspicious_timestamps(),
            test_hidden_dex_files=self._test_hidden_dex_files(),
            test_manifest_component_mismatch=self._test_manifest_component_mismatch(),
            test_debuggable_release=self._test_debuggable_release(),
            test_emulator_detection_strings=self._test_emulator_detection_strings(),
            test_debugger_detection=self._test_debugger_detection(),
            test_root_detection=self._test_root_detection(),
        )
        return self.test_results

    def _bool_to_nullable(self, val):
        """Convert bool/None to ClickHouse Nullable(UInt8)."""
        if val is None:
            return None
        return int(val)

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

            current_time = datetime.now(timezone.utc)
            t = self.test_results

            data = [[
                self.sha256,
                self._bool_to_nullable(t.test_zip_bomb),
                self._bool_to_nullable(t.test_zip_duplicate_entries),
                self._bool_to_nullable(t.test_zip_path_traversal),
                self._bool_to_nullable(t.test_zip_suspicious_timestamps),
                self._bool_to_nullable(t.test_hidden_dex_files),
                self._bool_to_nullable(t.test_manifest_component_mismatch),
                self._bool_to_nullable(t.test_debuggable_release),
                self._bool_to_nullable(t.test_emulator_detection_strings),
                self._bool_to_nullable(t.test_debugger_detection),
                self._bool_to_nullable(t.test_root_detection),
                current_time,
            ]]

            column_names = [
                'sha256',
                'test_zip_bomb', 'test_zip_duplicate_entries',
                'test_zip_path_traversal', 'test_zip_suspicious_timestamps',
                'test_hidden_dex_files', 'test_manifest_component_mismatch',
                'test_debuggable_release', 'test_emulator_detection_strings',
                'test_debugger_detection', 'test_root_detection',
                'analysis_date',
            ]

            column_type_names = [
                'FixedString(64)',
                'Nullable(UInt8)', 'Nullable(UInt8)',
                'Nullable(UInt8)', 'Nullable(UInt8)',
                'Nullable(UInt8)', 'Nullable(UInt8)',
                'Nullable(UInt8)', 'Nullable(UInt8)',
                'Nullable(UInt8)', 'Nullable(UInt8)',
                "DateTime64(3, 'UTC')",
            ]

            return (data, column_names, column_type_names)

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