Blocking Screen Readers

Screen readers are apps that use the Android accessibility API to read the contents of other apps. This API was designed to facilitate mobile device use for disabled people.

Unfortunately, this feature is frequently misused for other purposes. Some are helpful, such as automation tools, device cleaners, battery savers, or AVs. However, the Accessibility API is often abused by malware, especially by apps targeting banking software. Accessibility enables malware to grant itself excessive permissions and to read the screen contents of other apps.

Malwarelytics for Android provides a screen reader blocking feature.

The screen reader blocking feature is applied to the app’s activities. Details about behavior and APIs relevant to activity protection can be found in Activity protection.

Limitations

Blocking screen readers has certain limitations arising from the Accessibility API design.

An application can specify which data it sends to the accessibility API to be available for screen readers. However, it is impossible to choose to send data only to one specific screen reader. Screen readers have to be either allowed or blocked all at once.

Configuration

More information on general RASP feature configuration and usage can be found in this overview.

This feature bases its decision on whether screen readers should be universally allowed or blocked on two factors: on the action item of the SDK configuration and a provided list of allowed screen readers. Screen reading is only allowed if all screen readers enabled in the system appear on the list of allowed screen readers.

To simplify usage of the feature Malwarelytics for Android contains a built-in list of allowed screen readers. The list contains several frequently used apps that are designed to help disabled people. The list is used by default and can be found in the property ScreenReaderBlockConfig.DEFAULT_ALLOWED_SCREEN_READERS. If an app developer wishes to use a different list, it can be provided in the SDK configuration:

val allowList = listOf(
        // Specify an allowed app by its package name and signature hash (recommended approach)
        RaspConfig.ApkAllowlistItem("com.google.android.marvin.talkback", "9b424c2d27ad51a42a337e0bb6991c76eca44461"),
        // Specify an allowed app only by its package name (less secure)
        RaspConfig.ApkAllowlistItem("com.samsung.accessibility")
    )

val raspConfig = RaspConfig.Builder()
    .screenReader(
        ScreenReaderBlockConfig.Builder()
          .action(BlockConfig.Block)
          .allowedScreenReaders(allowList)
          .build()
    )
    .build()
Method Description
action(BlockConfig) specifies the automatic behavior of the screen reader blocking feature. Defaults to BlockConfig.Block.
allowedScreenReaders(
Collection<RaspConfig.ApkAllowlistItem>)
defines a collection of allowed screen readers. The default value is ScreenReaderBlockConfig.DEFAULT_ALLOWED_SCREEN_READERS.

Available values of BlockConfig:

Value Description
NoAction indicates that screen readers will not be automatically blocked and changes in the set of enabled screen readers will not be automatically detected. A manual check for not allowed screen readers is still possible.
Block indicates that screen readers will be automatically blocked, changes in the set of enabled screen readers will be automatically detected and observers will be notified.

Configuring Allowed Screen Readers

Allowed screen readers can be specified either by their package name and signature or by their package name only. However, the former is recommended to avoid allowing fake (and often malicious) apps.

Obtaining Package Name

Obtaining the app package name is simple – it is listed as a query param id in the URL of the app page on Google Play. For example, the package name of the Android Accessibility Suite is com.google.android.marvin.talkback as can be seen in this Google Play URL: https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback.

Obtaining App Signature

Obtaining the correct app signature is more complicated because a signed APK is necessary. Installing the app from Google Play is recommended. Next, the APK must be pulled from the device.

Find the APK location on the device:

adb shell pm list packages -f | grep "$PACKAGE$" | sed "s/package://" | sed "s/=$PACKAGE//"

Pull the APK from the device:

adb pull "$APK_LOCATION"

Obtain the signature hash in the right format:

apksigner verify --print-certs ${SOME_APK} | grep "SHA-1" | sed "s/.*: //"

The result is the app signature that can be used as the second argument for RaspConfig.ApkAllowlistItem(String, String).

Frequently Used Accessibility Apps

This is a list of some frequently used legitimate apps that make Android devices more accessible, though by no means exhaustive:

  • Android Accessibility Suite

    RaspConfig.ApkAllowlistItem("com.google.android.marvin.talkback", "9b424c2d27ad51a42a337e0bb6991c76eca44461")

  • Voice Access

    RaspConfig.ApkAllowlistItem("com.google.android.apps.accessibility.voiceaccess", "9dda347424376a377f78c4f2966f247270e16974")

  • Sound Amplifier

    RaspConfig.ApkAllowlistItem("com.google.android.accessibility.soundamplifier", "26710bdb08f6463b1f5842e2775169e31dd07301")

  • Live Transcribe & Sound Notifications

    RaspConfig.ApkAllowlistItem("com.google.audio.hearing.visualization.accessibility.scribe", "16e7d81dbd9baec338e32a5d7e13eec6af87b6d0")

Usage

After initialization, the screen reader blocking feature can be accessed via RaspManager. This can be used to trigger a manual check for active screen readers that were not allowed in the configuration.

Registering an Observer

The screen reader blocking feature also detects changes in the set of enabled screen readers and can trigger a certain action. To achieve that, an observer needs to be configured and registered.

Observer configuration:

val raspObserver = object : RaspObserver {
    override fun onScreenReaderDetected(screenReaderDetection: ScreenReaderDetection) {
        // handle screen reader detection
    }
    // handle detection of other RASP features
}

The observer can be registered in RaspManager. When it is no longer needed, it can be unregistered again.

raspManager.registerRaspObserver(raspObserver)
raspManager.unregisterRaspObserver(raspObserver)

Triggering a Manual Check

Check for not allowed screen readers can be triggered manually in RaspManager. Two methods are available. isNotAllowedScreenReaderEnabled() indicates whether there’s any active screen reader, that is not allowed in the configuration. Method getScreenReaderDetection() provides more details, it returns a list of all the active screen readers that are not allowed configuration.

val isNotAllowedScreenReaderEnabled = raspManager.isNotAllowedScreenReaderEnabled()
val screenReaderDetection = raspManager.getScreenReaderDetection()
Last updated on Feb 02, 2024 (13:35) View product
Search

develop

Malwarelytics for Android