RASP Feature Overview

RASP (runtime application self-protection) features protect the app against several attack vectors at runtime. Here is a list of available features:

Configuration

RASP features can be initially configured by building a RaspConfig instance and passing it to the raspConfig method in the general AppProtectionConfig:

val config = AppProtectionConfig.Builder(appContext)
        .raspConfig(
            RaspConfig.Builder()
                // RASP feature configuration
                .build()
        )
        // other Malwarelytics configuration
        .build()

When no RaspConfig instance is provided, all RASP features are turned off. When a RaspConfig instance is provided, all RASP configurations are enabled by default. However, the repackaging detection feature requires a signatureHash to be set.

A minimum RASP configuration with all features enabled requires only signatureHash to be set:

val config = AppProtectionConfig.Builder(appContext)
        .raspConfig(
            RaspConfig.Builder()
            .signatureHash(SIGNATURE_HASH)
            .build()
        )
        // …
        .build()

Available Configuration Items

val raspConfig = RaspConfig.Builder()
    .checkEmulator(Boolean)
    .exitOnEmulator(Boolean)
    .checkRoot(Boolean)
    .exitOnRoot(Boolean)
    .exitOnRootMinConfidence(Float) // value from 0.0 to 1.0
    .checkDebugger(Boolean)
    .exitOnDebugger(Boolean)
    .checkRepackaging(Boolean)
    .exitOnRepackaging(Boolean)
    .signatureHash(String)          // SHA-1 of signing certificate(s)
    .checkScreenSharing(Boolean)
    .exitOnScreenSharing(Boolean)
    .blockScreenshots(Boolean)
    .blockScreenReaders(Boolean)
    .allowedScreenReaders(Collection<RaspConfig.ApkAllowlist>)
    .customProcessName(String)      // when set, turns off useStealthyProcessName
    .useStealthyProcessName(Boolean)
    .blockTapjacking(Boolean)
    .ignoreTapjackingSystemApps(Boolean)
    .blockTapjackingSensitivity(ThreatIndex)
    .checkHttpProxy(Boolean)
    .exitOnHttpProxy(Boolean)
    .exitOnAdbEnabled(Boolean)
    .build()
Method Description
checkEmulator(Boolean) indicates whether emulators should be detected automatically. Defaults to true.
exitOnEmulator(Boolean) indicates whether the app should be terminated when an emulator is automatically detected. Defaults to false.
checkRoot(Boolean) indicates whether rooted device should be detected automatically. Defaults to true.
exitOnRoot(Boolean) indicates whether the app should be terminated when a rooted device is automatically detected. Defaults to false.
exitOnRootMinConfidence(Float) gives the minimum confidence value of a heuristic root detection that triggers app termination. Works only if exitOnRoot is true. Possible values are between 0.0 (inclusive) and 1.0 (inclusive). The default value is 1.0.
checkDebugger(Boolean) indicates whether debuggers should be detected automatically. Defaults to true.
exitOnDebugger(Boolean) indicates whether the app should be terminated when a debugger is automatically detected. Defaults to false.
signatureHash(String) SHA-1 of signing certificate(s). One or more values can be set. A lowercase hex value without any byte separators is expected. No default value is set.
checkRepackaging(Boolean) indicates whether repackaging should be detected automatically. Defaults to true but works only if signatureHash is set.
exitOnRepackaging(Boolean) indicates whether the app should be terminated when repackaging is automatically detected. Defaults to true but works only if signatureHash is set.
checkScreenSharing(Boolean) indicates whether screen sharing should be detected automatically. Defaults to true.
exitOnScreenSharing(Boolean) indicates whether the app should be terminated when screen sharing is automatically detected. Defaults to false.
blockScreenshots(Boolean) indicates whether taking screenshots and screen recordings should be blocked. Defaults to true.
allowedScreenReaders(
Collection<RaspConfig.ApkAllowlist>)
defines a collection of allowed screen readers. It is empty by default.
blockScreenReaders(Boolean) indicates whether screen readers should be blocked. Defaults to true. However, screen readers are only blocked if Malwarelytics detects an enabled screen reader that is not whitelisted in allowedScreenReaders.
customProcessName(String) sets a custom name which will be used for the app process. When the name is set, the useStealthyProcessName option is automatically turned off.
useStealthyProcessName(Boolean) indicates whether a stealthy name should be used for the app process. Defaults to true.
blockTapjacking(Boolean) indicates whether tapjacking should be blocked. Defaults to true. However, tapjacking is not blocked unless a “problematic” app is installed on the device. An app is deemed “problematic” when it meets sensitivity criteria defined by blockTapjackingSensitivity.
ignoreTapjackingSystemApps(Boolean) indicates whether tapjacking protection should ignore system apps in the checks. Defaults to false.
blockTapjackingSensitivity(ThreatIndex) defines tapjacking protection sensitivity. Defaults to ThreatIndex.HIGHLY_DANGEROUS.
checkHttpProxy(Boolean) indicates whether HTTP proxy use should be detected automatically. Defaults to true.
exitOnHttpProxy(Boolean) indicates whether the app should be terminated when the use of an HTTP proxy is detected. Defaults to false.
exitOnAdbEnabled(Boolean) indicates whether the app should be terminated when ADB (Android Debug Bridge) is enabled on the device. Defaults to false.

The check- methods turn certain features on or off. The exit- methods cause the app to exit when the corresponding detection is triggered. The block- methods block certain system features to shield the app against the related vulnerability.

Detailed information about these configuration items can be found on the documentation pages of individual features.

Obtaining Detection Results

After Malwarelytics for Android has been initialized with certain configurations, RASP features can be accessed with RaspManager. You can obtain an instance from AppProtection by calling:

val raspManager = appProtection.getRaspManager()

When RaspConfig is not provided, all RASP features are turned off and the RaspManager instance cannot be used to access RASP features.

You can use the RaspManager instance to register and unregister a RASP observer or to trigger RASP checks manually.

Observing RASP Detections

An observer can be registered in RaspManager to notify the app about any RASP detections. This is an example of registering an observer in which all available detections are handled:

val raspObserver = object : RaspObserver {
    override fun onEmulatorDetected(emulatorDetection: EmulatorDetection) {
        // handle emulator detection
    }

    override fun onRootDetected(rootDetection: RootDetection) {
        // handle root detection
    }

    override fun onDebuggerDetected(debuggerDetected: Boolean) {
        // handle debugger detection
    }

    override fun onRepackagingDetected(repackagingResult: RepackagingResult) {
        // handle repackaging detection
    }

    override fun onScreenSharingDetected(screenSharingDetected: Boolean) {
        // handle screen sharing detection
    }

    override fun onTapjackingDetected(tapjackingDetection: TapjackingDetection) {
        // handle tapjacking detection
    }

    override fun onHttpProxyDetected(httpProxyDetected: Boolean) {
        // handle http proxy detection
    }

    override fun onAdbStatusDetected(adbStatus: Boolean) {
        // handle ADB status detection
    }
}
raspManager.registerRaspObserver(raspObserver)

The observer can be unregistered when it is no longer necessary:

raspManager.unregisterRaspObserver(raspObserver)

The observer callbacks are always called on a background thread before the app exits. It’s recommended to perform only a quick lightweight processing in the callback as any heavy processing or threading is not guaranteed to be completed.

Any detections that are manually triggered via RaspManager (see section below) are not propagated into the observer.

Triggering RASP Checks Manually

All RASP checks can be triggered manually with RaspManager. There are two types of manual checks: the is- methods give a simple boolean answer whereas the get- methods provide more detailed information.

// root detection
val rootDetection = raspManager.getRootDetection()
val isRooted = raspManager.isDeviceRooted()

// emulator detection
val emulatorDetection = raspManager.getEmulatorDetection()
val isDeviceEmulator = raspManager.isDeviceEmulator()

// debugger
val debuggerDetection = raspManager.getDebuggerDetection()
val isDebuggerAttached = raspManager.isDebuggerAttached()

// repackaging
val repackagingResult = raspManager.isAppRepackaged()

// screen sharing
val screenSharingDetection = raspManager.getScreenSharingDetection()
val isScreenShared = raspManager.isScreenShared()

// screen lock usage
val isDeviceUsingScreenLock = raspManager.isDeviceUsingScreenLock()

// Play Protect status
val isPlayProtectEnabled = raspManager.isPlayProtectEnabled()

// tapjacking
val isBadTapjackingCapableAppPresent = raspManager.isBadTapjackingCapableAppPresent()
val tapjackingDetection = raspManager.getTapjackingDetection()

// http proxy detection
val isHttpProxyEnabled = raspManager.isHttpProxyEnabled()

// ADB status
val isAdbEnabled = raspManager.isAdbEnabled()

// developer options status
val isDeveloperOptionsEnabled = raspManager.isDeveloperOptionsEnabled()
Last updated on Jun 07, 2022 (22:56) View product
Search

0.19.x

Malwarelytics for Android