diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c11ebd..8357f06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.2.0] - 2026-08-05 + +- Android SDK version: 19.2.1 +- iOS SDK version: 7.1.1 + +### Flutter + +#### Added + +- Added `onBootloader` callback for detecting an unlocked or compromised bootloader (Android only). + +### Android + +#### Added + +- Added bootloader detection (unlocked/compromised) with `onBootloader()` callback +- Added option to fetch JitPack dependencies from our own Talsec repository + +#### Changed + +- Improved KernelSU detection +- Improved hook detection +- Improved Frida detection +- Improved root detection capabilities + +#### Fixed + +- Fixed native crash caused by std::terminate() race condition +- Fixed periodic hook and root check overwriting +- Fixed crash inside AppZygotePreload during root detection +- Fixed root detection crash in obfuscated release builds +- Fixed hardware-backed keystore detection failing with `NoSuchMethodError` on some Android 12+ devices + ## [8.1.0] - 2026-07-23 - Android SDK version: 18.3.0 diff --git a/android/build.gradle b/android/build.gradle index 1193161..9bc6d58 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -3,7 +3,7 @@ version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '2.1.0' - ext.talsec_version = '18.3.0' + ext.talsec_version = '19.2.1' repositories { google() mavenCentral() diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/Extensions.kt b/android/src/main/kotlin/com/aheaditec/freerasp/Extensions.kt index 2f0a304..0529694 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/Extensions.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/Extensions.kt @@ -3,12 +3,12 @@ package com.aheaditec.freerasp import android.content.Context import android.content.pm.PackageInfo import android.os.Build -import com.aheaditec.talsec_security.security.api.ExternalIdResult -import com.aheaditec.talsec_security.security.api.MalwareScanScope -import com.aheaditec.talsec_security.security.api.ReasonMode -import com.aheaditec.talsec_security.security.api.ScopeType -import com.aheaditec.talsec_security.security.api.SuspiciousAppDetectionConfig -import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo +import app.talsec.rasp.security.api.ExternalIdResult +import app.talsec.rasp.security.api.MalwareScanScope +import app.talsec.rasp.security.api.ReasonMode +import app.talsec.rasp.security.api.ScopeType +import app.talsec.rasp.security.api.SuspiciousAppDetectionConfig +import app.talsec.rasp.security.api.SuspiciousAppInfo import io.flutter.plugin.common.MethodChannel import org.json.JSONArray import org.json.JSONObject diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/ScreenProtector.kt b/android/src/main/kotlin/com/aheaditec/freerasp/ScreenProtector.kt index 83ea7d0..d63ddb6 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/ScreenProtector.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/ScreenProtector.kt @@ -11,7 +11,7 @@ import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner -import com.aheaditec.talsec_security.security.api.Talsec +import app.talsec.rasp.security.api.Talsec import io.flutter.Log import java.util.function.Consumer diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/Threat.kt b/android/src/main/kotlin/com/aheaditec/freerasp/Threat.kt index aaf478f..6e733a4 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/Threat.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/Threat.kt @@ -47,4 +47,6 @@ internal sealed class Threat(val value: Int) { object LocationSpoofing : Threat(653273273) object Automation : Threat(298453120) + + object Bootloader : Threat(1651076936) } \ No newline at end of file diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/Utils.kt b/android/src/main/kotlin/com/aheaditec/freerasp/Utils.kt index 1a805a3..bf0ebba 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/Utils.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/Utils.kt @@ -7,7 +7,7 @@ import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.os.Build import android.util.Base64 -import com.aheaditec.talsec_security.security.api.TalsecConfig +import app.talsec.rasp.security.api.TalsecConfig import org.json.JSONArray import org.json.JSONException import org.json.JSONObject diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt b/android/src/main/kotlin/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt index f49ba51..9afd875 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt @@ -2,7 +2,7 @@ package com.aheaditec.freerasp.dispatchers import com.aheaditec.freerasp.Threat import com.aheaditec.freerasp.handlers.MethodCallHandler -import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo +import app.talsec.rasp.security.api.SuspiciousAppInfo import io.flutter.plugin.common.EventChannel.EventSink internal object ThreatDispatcher { diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/MethodCallHandler.kt b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/MethodCallHandler.kt index 7771e01..9c98c11 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/MethodCallHandler.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/MethodCallHandler.kt @@ -13,8 +13,8 @@ import com.aheaditec.freerasp.generated.TalsecPigeonApi import com.aheaditec.freerasp.resolve import com.aheaditec.freerasp.runResultCatching import com.aheaditec.freerasp.toPigeon -import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo -import com.aheaditec.talsec_security.security.api.Talsec +import app.talsec.rasp.security.api.SuspiciousAppInfo +import app.talsec.rasp.security.api.Talsec import io.flutter.Log import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/PluginThreatHandler.kt b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/PluginThreatHandler.kt index c9b9197..8b00478 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/PluginThreatHandler.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/PluginThreatHandler.kt @@ -5,11 +5,11 @@ import com.aheaditec.freerasp.RaspExecutionStateEvent import com.aheaditec.freerasp.Threat import com.aheaditec.freerasp.dispatchers.ExecutionStateDispatcher import com.aheaditec.freerasp.dispatchers.ThreatDispatcher -import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo -import com.aheaditec.talsec_security.security.api.ThreatListener -import com.aheaditec.talsec_security.security.api.ThreatListener.DeviceState -import com.aheaditec.talsec_security.security.api.ThreatListener.RaspExecutionState -import com.aheaditec.talsec_security.security.api.ThreatListener.ThreatDetected +import app.talsec.rasp.security.api.SuspiciousAppInfo +import app.talsec.rasp.security.api.ThreatListener +import app.talsec.rasp.security.api.ThreatListener.DeviceState +import app.talsec.rasp.security.api.ThreatListener.RaspExecutionState +import app.talsec.rasp.security.api.ThreatListener.ThreatDetected /** * A Singleton object that manages the [ThreatListener] to handle detected security threats in the application. @@ -19,89 +19,93 @@ import com.aheaditec.talsec_security.security.api.ThreatListener.ThreatDetected internal object PluginThreatHandler { private val threatDetected = object : ThreatDetected() { - override fun onRootDetected() { + override fun onPrivilegedAccess() { ThreatDispatcher.dispatchThreat(Threat.PrivilegedAccess) } - override fun onDebuggerDetected() { + override fun onDebug() { ThreatDispatcher.dispatchThreat(Threat.Debug) } - override fun onEmulatorDetected() { + override fun onSimulator() { ThreatDispatcher.dispatchThreat(Threat.Simulator) } - override fun onTamperDetected() { + override fun onAppIntegrity() { ThreatDispatcher.dispatchThreat(Threat.AppIntegrity) } - override fun onUntrustedInstallationSourceDetected() { + override fun onUnofficialStore() { ThreatDispatcher.dispatchThreat(Threat.UnofficialStore) } - override fun onHookDetected() { + override fun onHooks() { ThreatDispatcher.dispatchThreat(Threat.Hooks) } - override fun onDeviceBindingDetected() { + override fun onDeviceBinding() { ThreatDispatcher.dispatchThreat(Threat.DeviceBinding) } - override fun onObfuscationIssuesDetected() { + override fun onObfuscationIssues() { ThreatDispatcher.dispatchThreat(Threat.ObfuscationIssues) } - override fun onMalwareDetected(suspiciousApps: List) { + override fun onMalware(suspiciousApps: List) { ThreatDispatcher.dispatchMalware(suspiciousApps) } - override fun onScreenshotDetected() { + override fun onScreenshot() { ThreatDispatcher.dispatchThreat(Threat.Screenshot) } - override fun onScreenRecordingDetected() { + override fun onScreenRecording() { ThreatDispatcher.dispatchThreat(Threat.ScreenRecording) } - override fun onMultiInstanceDetected() { + override fun onMultiInstance() { ThreatDispatcher.dispatchThreat(Threat.MultiInstance) } - override fun onUnsecureWifiDetected() { + override fun onUnsecureWifi() { ThreatDispatcher.dispatchThreat(Threat.UnsecureWiFi) } - override fun onTimeSpoofingDetected() { + override fun onTimeSpoofing() { ThreatDispatcher.dispatchThreat(Threat.TimeSpoofing) } - override fun onLocationSpoofingDetected() { + override fun onLocationSpoofing() { ThreatDispatcher.dispatchThreat(Threat.LocationSpoofing) } - override fun onAutomationDetected() { + override fun onAutomation() { ThreatDispatcher.dispatchThreat(Threat.Automation) } + + override fun onBootloader() { + ThreatDispatcher.dispatchThreat(Threat.Bootloader) + } } private val deviceState = object : DeviceState() { - override fun onUnlockedDeviceDetected() { + override fun onPasscode() { ThreatDispatcher.dispatchThreat(Threat.Passcode) } - override fun onHardwareBackedKeystoreNotAvailableDetected() { + override fun onSecureHardwareNotAvailable() { ThreatDispatcher.dispatchThreat(Threat.SecureHardwareNotAvailable) } - override fun onSystemVPNDetected() { + override fun onSystemVpn() { ThreatDispatcher.dispatchThreat(Threat.SystemVPN) } - override fun onDeveloperModeDetected() { + override fun onDevMode() { ThreatDispatcher.dispatchThreat(Threat.DevMode) } - override fun onADBEnabledDetected() { + override fun onAdbEnabled() { ThreatDispatcher.dispatchThreat(Threat.ADBEnabled) } } @@ -121,4 +125,4 @@ internal object PluginThreatHandler { internal fun unregisterListener(context: Context) { internalListener.unregisterListener(context) } -} \ No newline at end of file +} diff --git a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/TalsecThreatHandler.kt b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/TalsecThreatHandler.kt index 5274d93..93a3958 100644 --- a/android/src/main/kotlin/com/aheaditec/freerasp/handlers/TalsecThreatHandler.kt +++ b/android/src/main/kotlin/com/aheaditec/freerasp/handlers/TalsecThreatHandler.kt @@ -6,8 +6,8 @@ import com.aheaditec.freerasp.RaspExecutionStateEvent import com.aheaditec.freerasp.ScreenProtector import com.aheaditec.freerasp.dispatchers.ExecutionStateDispatcher import com.aheaditec.freerasp.dispatchers.ThreatDispatcher -import com.aheaditec.talsec_security.security.api.Talsec -import com.aheaditec.talsec_security.security.api.TalsecConfig +import app.talsec.rasp.security.api.Talsec +import app.talsec.rasp.security.api.TalsecConfig import io.flutter.plugin.common.EventChannel.EventSink /** diff --git a/example/lib/threat_notifier.dart b/example/lib/threat_notifier.dart index e61e6d7..5cebb66 100644 --- a/example/lib/threat_notifier.dart +++ b/example/lib/threat_notifier.dart @@ -35,6 +35,7 @@ class ThreatNotifier extends AutoDisposeNotifier { onTimeSpoofing: () => _updateThreat(Threat.timeSpoofing), onLocationSpoofing: () => _updateThreat(Threat.locationSpoofing), onAutomation: () => _updateThreat(Threat.automation), + onBootloader: () => _updateThreat(Threat.bootloader), ); final raspExecutionStateCallback = diff --git a/lib/src/callbacks/threat_callback.dart b/lib/src/callbacks/threat_callback.dart index 8d7e935..9e48f91 100644 --- a/lib/src/callbacks/threat_callback.dart +++ b/lib/src/callbacks/threat_callback.dart @@ -43,6 +43,7 @@ class ThreatCallback extends TalsecPigeonApi { this.onTimeSpoofing, this.onLocationSpoofing, this.onAutomation, + this.onBootloader, }); /// This method is called when a threat related dynamic hooking (e.g. Frida) @@ -115,6 +116,12 @@ class ThreatCallback extends TalsecPigeonApi { /// This method is called when automation is detected final VoidCallback? onAutomation; + /// This method is called when an unlocked or compromised bootloader is + /// detected. + /// + /// Android only + final VoidCallback? onBootloader; + @override void onMalwareDetected(List packageInfo) { onMalware?.call(packageInfo); diff --git a/lib/src/enums/threat.dart b/lib/src/enums/threat.dart index 9c984cb..316a199 100644 --- a/lib/src/enums/threat.dart +++ b/lib/src/enums/threat.dart @@ -91,6 +91,11 @@ enum Threat { /// /// Android only automation, + + /// The device bootloader is unlocked or otherwise compromised. + /// + /// Android only + bootloader, } /// An extension on the [Threat] enum to provide additional functionality. @@ -126,6 +131,7 @@ extension ThreatX on Threat { /// * 64690214 - screenRecording /// * 859307284 - multiInstance /// * 298453120 - automation + /// * 1651076936 - bootloader static Threat fromInt(int code) { switch (code) { case 1268968002: @@ -170,6 +176,8 @@ extension ThreatX on Threat { return Threat.locationSpoofing; case 298453120: return Threat.automation; + case 1651076936: + return Threat.bootloader; default: // Unknown data came from native code. This shouldn't normally happen. exit(127); diff --git a/lib/src/talsec.dart b/lib/src/talsec.dart index a851250..532e705 100644 --- a/lib/src/talsec.dart +++ b/lib/src/talsec.dart @@ -311,6 +311,8 @@ class Talsec { callback.onLocationSpoofing?.call(); case Threat.automation: callback.onAutomation?.call(); + case Threat.bootloader: + callback.onBootloader?.call(); } }); } diff --git a/pubspec.yaml b/pubspec.yaml index 0ed4e24..3111571 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: freerasp description: Flutter library for improving app security and threat monitoring on Android and iOS mobile devices. Learn more about provided features on the freeRASP's homepage first. -version: 8.1.0 +version: 8.2.0 homepage: https://www.talsec.app/freerasp-in-app-protection-security-talsec repository: https://github.com/talsec/Free-RASP-Flutter