Runtime Tampering Detection
Runtime tampering (also called dynamic instrumentation) refers to techniques that allow an attacker to inspect and modify the behavior of a running app without altering its binary. Various tools and hooking frameworks can attach to a live process and intercept or replace method calls, read memory, or alter application logic at runtime. Detecting these tools is a key RASP feature because their presence in a production environment is a strong indicator of a reverse engineering or active attack attempt.
Malwarelytics for Android is able to detect the presence of several runtime tampering technologies and can be configured to terminate the app when such a technology is detected.
Configuration
This feature can be configured during the Malwarelytics initialization phase:
val raspConfig = RaspConfig.Builder()
.runtimeTampering(DetectionConfig)
// configuration of other RASP features
.build()
Available values of DetectionConfig:
| Value | Description |
|---|---|
NoAction |
indicates that runtime tampering will not be automatically detected. A manual check is still possible. |
Notify |
indicates that runtime tampering will be automatically detected and observers will be notified. |
Exit(exitUrl:String?) |
indicates that runtime tampering will be automatically detected and the app will be terminated when a tampering tool is automatically detected. |
Runtime tampering detection defaults to DetectionConfig.Notify.
List of available parameters for some config values:
| Parameter | Description |
|---|---|
exitUrl:String? |
defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to null. |
Usage
After initialization, the runtime tampering detection feature can be accessed via RaspManager. This can be used to register an observer or to trigger a manual check.
Registering an Observer
Runtime tampering detection can trigger a certain action. To achieve that, an observer needs to be configured and registered.
Observer configuration:
val raspObserver = object : RaspObserver {
// The callback is delivered on a background thread
override fun onRuntimeTamperingDetected(runtimeTamperingDetection: RuntimeTamperingDetection) {
// Handle runtime tampering 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)
The RuntimeTamperingDetection data class contains the following properties:
| Property | Description |
|---|---|
isRuntimeTamperingPresent: Boolean |
indicates whether a runtime tampering technology is detected with non-zero confidence. |
detectionConfidence: Float |
indicates the confidence of the runtime tampering detection, the value is in the range [0.0, 1.0]. |
troubleshootingMessage: String |
contains troubleshooting information. The value is used for troubleshooting purposes only and may be changed at any version. |
Triggering a Manual Check
Runtime tampering detection can be triggered manually in RaspManager. Two methods are available – isRuntimeTamperingPresent() gives a simple boolean answer, whereas getRuntimeTamperingDetection() provides more details.
// Always run on a background thread
val runtimeTamperingDetection: RuntimeTamperingDetection = raspManager.getRuntimeTamperingDetection()
// Always run on a background thread
val isRuntimeTamperingPresent: Boolean = raspManager.isRuntimeTamperingPresent()
More information on general RASP feature configuration and usage can be found in this overview.