Jacob van der Woude

30 papers Journal 26Unranked 4
YearRankTypeTitle / Venue / Authors
2024 J jnl
IEEE Trans. Control. Netw. Syst.
Christian Commault, Jacob van der Woude
2024 J jnl
Eur. J. Control
Jacob van der Woude, Christian Commault, Taha Boukhobza
2022 J jnl
Autom.
Taha Boukhobza, Jacob van der Woude, Christian Commault, Gilles Millérioux
2022 J jnl
IEEE Trans. Autom. Control.
Mahya Adibi, Jacob van der Woude
2020 conf
ISIE
Mahya Adibi, Jacob van der Woude
2020 J jnl
CoRR
Abhimanyu Gupta, Ton J. J. van den Boom, Jacob van der Woude, Bart De Schutter
2020 J jnl
IEEE Trans. Netw. Sci. Eng.
Christian Commault, Jacob van der Woude, Paolo Frasca
2019 J jnl
IEEE Trans. Autom. Control.
Christian Commault, Jacob van der Woude
2019 J jnl
Syst. Control. Lett.
Jacob van der Woude, Christian Commault, Taha Boukhobza
2019 J jnl
CoRR
Christian Commault, Jacob van der Woude, Paolo Frasca
2018 J jnl
Syst. Control. Lett.
Jacob van der Woude, Taha Boukhobza, Christian Commault
2018 conf
ECC
Jacob van der Woude
2017 J jnl
Discret. Event Dyn. Syst.
Kistosil Fahim, Subiono, Jacob van der Woude
2017 J jnl
Syst. Control. Lett.
Christian Commault, Jacob van der Woude, Taha Boukhobza
2014 conf
ECC
Dimitri Jeltsema, Jacob van der Woude
2011 J jnl
IMA J. Math. Control. Inf.
Shah Muhammad, Jacob van der Woude
2009 J jnl
IMA J. Math. Control. Inf.
Shah Muhammad, Jacob van der Woude
2005 conf
CDC/ECC
Jacob van der Woude, Geert Jan Olsder
2004 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Yusuf Fuad, Willem L. De Koning, Jacob van der Woude
2003 J jnl
Theor. Comput. Sci.
Jacob van der Woude, Subiono
2003 J jnl
Autom.
Jean-Michel Dion, Christian Commault, Jacob van der Woude
2003 J jnl
Math. Control. Signals Syst.
Jacob van der Woude, Christian Commault, Jean-Michel Dion
2002 J jnl
Kybernetika
Christian Commault, Jean-Michel Dion, Jacob van der Woude
2001 J jnl
Discret. Event Dyn. Syst.
Jacob van der Woude
2000 J jnl
Discret. Event Dyn. Syst.
Subiono, Jacob van der Woude
1999 J jnl
SIAM J. Control. Optim.
Jacob van der Woude
1996 J jnl
Autom.
Jacob van der Woude
1995 J jnl
SIAM J. Matrix Anal. Appl.
Jacob van der Woude, Kazuo Murota
1995 J jnl
Math. Control. Signals Syst.
Jacob van der Woude
1991 J jnl
Math. Control. Signals Syst.
Jacob van der Woude
redb/extractors/apk_extractors/apk_permissions.py
← Index redb/extractors/apk_extractors/apk_permissions.py python
import inspect
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 APKPermissions, APKPermission

# Known dangerous permissions (Android runtime permissions)
DANGEROUS_PERMISSIONS = {
    "android.permission.READ_CALENDAR",
    "android.permission.WRITE_CALENDAR",
    "android.permission.CAMERA",
    "android.permission.READ_CONTACTS",
    "android.permission.WRITE_CONTACTS",
    "android.permission.GET_ACCOUNTS",
    "android.permission.ACCESS_FINE_LOCATION",
    "android.permission.ACCESS_COARSE_LOCATION",
    "android.permission.ACCESS_BACKGROUND_LOCATION",
    "android.permission.RECORD_AUDIO",
    "android.permission.READ_PHONE_STATE",
    "android.permission.READ_PHONE_NUMBERS",
    "android.permission.CALL_PHONE",
    "android.permission.ANSWER_PHONE_CALLS",
    "android.permission.ADD_VOICEMAIL",
    "android.permission.USE_SIP",
    "android.permission.BODY_SENSORS",
    "android.permission.SEND_SMS",
    "android.permission.RECEIVE_SMS",
    "android.permission.READ_SMS",
    "android.permission.RECEIVE_WAP_PUSH",
    "android.permission.RECEIVE_MMS",
    "android.permission.READ_EXTERNAL_STORAGE",
    "android.permission.WRITE_EXTERNAL_STORAGE",
    "android.permission.READ_MEDIA_IMAGES",
    "android.permission.READ_MEDIA_VIDEO",
    "android.permission.READ_MEDIA_AUDIO",
    "android.permission.POST_NOTIFICATIONS",
    "android.permission.NEARBY_WIFI_DEVICES",
    "android.permission.ACTIVITY_RECOGNITION",
    "android.permission.BLUETOOTH_SCAN",
    "android.permission.BLUETOOTH_ADVERTISE",
    "android.permission.BLUETOOTH_CONNECT",
}


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

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

    def _get_protection_level(self, perm_name):
        """Determine the protection level of a permission.

        Uses androguard's permission mappings first, falls back to the
        known dangerous list.
        """
        try:
            from androguard.core.api_specific_resources import load_permission_mappings
            target_sdk = self.apk.get_target_sdk_version()
            sdk = int(target_sdk) if target_sdk else 30
            permission_map = load_permission_mappings(sdk)
            if perm_name in permission_map:
                info = permission_map[perm_name]
                if isinstance(info, dict):
                    return info.get("protectionLevel", "unknown")
                return "unknown"
        except Exception:
            pass

        # Fallback to known dangerous set
        if perm_name in DANGEROUS_PERMISSIONS:
            return "dangerous"
        if perm_name.startswith("android.permission."):
            return "normal"
        return "unknown"

    def _compute_permhash(self):
        """Compute permhash using the permhash library."""
        try:
            from permhash.functions import permhash_apk
            return permhash_apk(self.filepath)
        except Exception as e:
            self.log.warning(f"Failed to compute permhash: {e}")
            return None

    def _safe_extract(self, field_name, func, default=None):
        """Extract a single field, logging and returning default on failure."""
        try:
            return func()
        except Exception as e:
            self.log.warning(
                f"Error extracting APK permissions field '{field_name}' for "
                f"{self.hash.sha256}: {e}"
            )
            return default

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

        requested_perms = self._safe_extract(
            "requested_permissions",
            lambda: list(self.apk.get_permissions() or []), []
        )
        custom_perms = self._safe_extract(
            "custom_permissions",
            lambda: list(self.apk.get_declared_permissions() or []), []
        )
        custom_perm_set = set(custom_perms)

        permission_details = []
        dangerous_permissions = []

        for perm in requested_perms:
            try:
                protection_level = self._get_protection_level(perm)
                is_custom = perm in custom_perm_set

                permission_details.append(APKPermission(
                    permission_name=perm,
                    protection_level=protection_level,
                    is_custom=is_custom,
                ))

                if protection_level == "dangerous":
                    dangerous_permissions.append(perm)
            except Exception as e:
                self.log.warning(
                    f"Error processing permission '{perm}' for "
                    f"{self.hash.sha256}: {e}"
                )
                permission_details.append(APKPermission(
                    permission_name=perm,
                    protection_level="unknown",
                    is_custom=perm in custom_perm_set,
                ))

        permhash_value = self._compute_permhash()

        self.permissions_data = APKPermissions(
            total_permission_count=len(requested_perms),
            dangerous_permission_count=len(dangerous_permissions),
            permissions=requested_perms,
            dangerous_permissions=dangerous_permissions,
            custom_permissions=custom_perms,
            permission_details=permission_details,
            permhash=permhash_value,
        )
        return self.permissions_data

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

            current_time = datetime.now(timezone.utc)

            # One row per permission
            data = []
            for detail in self.permissions_data.permission_details:
                data.append([
                    self.sha256,
                    detail.permission_name,
                    detail.protection_level,
                    int(detail.is_custom),
                    current_time,
                ])

            if not data:
                return None

            column_names = [
                'sha256', 'permission_name', 'protection_level',
                'is_custom', 'analysis_date',
            ]

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

            return (data, column_names, column_type_names)

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