Raid Ayoub

52 papers A* 3A 6C 5Misc 2Journal 22Unranked 13
YearRankTypeTitle / Venue / Authors
2024 A conf
ICCAD
Chien-Yi Yang, Minxuan Zhou, Flavio Ponzina, Suraj Sathya Prakash, Raid Ayoub, Pietro Mercati, Mahesh Subedar, Tajana Rosing
2023 A conf
DATE
Shruti Yadav Narayana, Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2023 J jnl
ACM Trans. Design Autom. Electr. Syst.
Gaurav Narang, Aryan Deshwal, Raid Ayoub, Michael Kishinevsky, Janardhan Rao Doppa, Partha Pratim Pande
2023 J jnl
IEEE Internet Things J.
Kazim Ergun, Raid Ayoub, Pietro Mercati, Tajana Simunic Rosing
2023 J jnl
IEEE Des. Test
Shruti Yadav Narayana, Sumit K. Mandal, Raid Ayoub, Mohammad M. Islam, Michael Kishinevsky, Ümit Y. Ogras
2023 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Sumit K. Mandal, Shruti Yadav Narayana, Raid Ayoub, Michael Kishinevsky, Ahmed Abousamra, Ümit Y. Ogras
2023 J jnl
CoRR
Shruti Yadav Narayana, Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2023 C conf
ACC
Jiajun Shen, Kananart Kuwaranancharoen, Raid Ayoub, Pietro Mercati, Shreyas Sundaram
2023 J jnl
CoRR
Jiajun Shen, Kananart Kuwaranancharoen, Raid Ayoub, Pietro Mercati, Shreyas Sundaram
2023 A conf
ISLPED
Gaurav Narang, Raid Ayoub, Michael Kishinevsky, Janardhan Rao Doppa, Partha Pratim Pande
2022 J jnl
Ad Hoc Networks
Kazim Ergun, Raid Ayoub, Pietro Mercati, Tajana Rosing
2021 J jnl
IEEE Embed. Syst. Lett.
Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Mohammad M. Islam, Ümit Y. Ogras
2021 conf
ASP-DAC
Kazim Ergun, Raid Ayoub, Pietro Mercati, Dancheng Liu, Tajana Rosing
2021 conf
MECO
Kazim Ergun, Raid Ayoub, Pietro Mercati, Tajana Rosing
2021 A conf
ICCAD
Sumit K. Mandal, Jie Tong, Raid Ayoub, Michael Kishinevsky, Ahmed Abousamra, Ümit Y. Ogras
2021 J jnl
CoRR
Sumit K. Mandal, Jie Tong, Raid Ayoub, Michael Kishinevsky, Ahmed Abousamra, Ümit Y. Ogras
2020 J jnl
IEEE Des. Test
Sudeep Pasricha, Raid Ayoub, Michael Kishinevsky, Sumit K. Mandal, Ümit Y. Ogras
2020 J jnl
CoRR
Ujjwal Gupta, Manoj Babu, Raid Ayoub, Michael Kishinevsky, Francesco Paterna, Suat Gumussoy, Ümit Y. Ogras
2020 J jnl
CoRR
Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Mohammad M. Islam, Ümit Y. Ogras
2020 conf
SLIP
Raid Ayoub, Michael Kishinevsky, Sumit K. Mandal, Ümit Y. Ogras
2020 J jnl
IEEE Des. Test
Ümit Y. Ogras, Sudeep Pasricha, Michael Kishinevsky, Raid Ayoub
2020 A conf
ICCAD
Sumit K. Mandal, Anish Krishnakumar, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2020 J jnl
CoRR
Sumit K. Mandal, Anish Krishnakumar, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2020 conf
ICIOT
Kazim Ergun, Xiaofan Yu, Nitish Nagesh, Ludmila Cherkasova, Pietro Mercati, Raid Ayoub, Tajana Rosing
2020 conf
DSN (Supplements)
Kazim Ergun, Xiaofan Yu, Nitish Nagesh, Ludmila Cherkasova, Pietro Mercati, Raid Ayoub, Tajana Rosing
2019 J jnl
CoRR
Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2019 J jnl
ACM Trans. Embed. Comput. Syst.
Sumit K. Mandal, Raid Ayoub, Michael Kishinevsky, Ümit Y. Ogras
2019 C conf
ICCD
Kazim Ergun, Raid Ayoub, Pietro Mercati, Tajana Rosing
2018 J jnl
IEEE Trans. Computers
Ujjwal Gupta, Manoj Babu, Raid Ayoub, Michael Kishinevsky, Francesco Paterna, Suat Gumussoy, Ümit Y. Ogras
2018 J jnl
IEEE Trans. Multi Scale Comput. Syst.
Ujjwal Gupta, Raid Ayoub, Michael Kishinevsky, David Kadjo, Niranjan Soundararajan, Ugurkan Tursun, Ümit Y. Ogras
2018 A* conf
DAC
Ujjwal Gupta, Manoj Babu, Raid Ayoub, Michael Kishinevsky, Francesco Paterna, Ümit Y. Ogras
2017 conf
ANDARE@PACT
Francesco Paterna, Ujjwal Gupta, Raid Ayoub, Ümit Y. Ogras, Michael Kishinevsky
2017 J jnl
Syst. Control. Lett.
Ankush Chakrabarty, Raid Ayoub, Stanislaw H. Zak, Shreyas Sundaram
2017 A* conf
DAC
Pietro Mercati, Raid Ayoub, Michael Kishinevsky, Eric Samson, Marc Beuchat, Francesco Paterna, Tajana Simunic Rosing
2017 J jnl
Autom.
Haotian Zhang, Raid Ayoub, Shreyas Sundaram
2017 J jnl
ACM Trans. Embed. Comput. Syst.
Begum Egilmez, Matthew Schuchhardt, Gokhan Memik, Raid Ayoub, Niranjan Soundararajan, Michael Kishinevsky
2016 A conf
ICCAD
Ujjwal Gupta, Joseph Campbell, Ümit Y. Ogras, Raid Ayoub, Michael Kishinevsky, Francesco Paterna, Suat Gumussoy
2016 conf
CDC
Haotian Zhang, Ankush Chakrabarty, Raid Ayoub, Gregery T. Buzzard, Shreyas Sundaram
2015 A* conf
DAC
David Kadjo, Raid Ayoub, Michael Kishinevsky, Paul V. Gratz
2015 Misc conf
CASES
Matthew Schuchhardt, Susmit Jha, Raid Ayoub, Michael Kishinevsky, Gokhan Memik
2015 conf
CDC
Haotian Zhang, Raid Ayoub, Shreyas Sundaram
2015 C conf
ACC
Haotian Zhang, Raid Ayoub, Shreyas Sundaram
2014 Misc conf
CASES
Matthew Schuchhardt, Susmit Jha, Raid Ayoub, Michael Kishinevsky, Gokhan Memik
2014 conf
SoCC
David Kadjo, Ümit Y. Ogras, Raid Ayoub, Michael Kishinevsky, Paul Gratz
2013 J jnl
ACM Trans. Design Autom. Electr. Syst.
Raid Ayoub, Rajib Nath, Tajana Simunic Rosing
2013 C conf
ICCD
David Kadjo, Hyungjun Kim, Paul Gratz, Jiang Hu, Raid Ayoub
2011
Raid Ayoub
2010 conf
ACM Great Lakes Symposium on VLSI
Raid Ayoub, Alex Orailoglu
2009 conf
ASAP
Raid Ayoub, Alex Orailoglu
2007 C conf
ICCD
Raid Ayoub, Alex Orailoglu
2005 conf
ASP-DAC
Raid Ayoub, Alex Orailoglu
2004 conf
SoCC
Raid Ayoub, Peter Petrov, Alex Orailoglu
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"