From f870028e71291fad38e0cac61e2c338bb73ab2d9 Mon Sep 17 00:00:00 2001 From: Denis Dobanda Date: Wed, 26 Mar 2025 10:56:04 +0100 Subject: [PATCH 1/3] chore: regenerated pigeon Signed-off-by: Denis Dobanda --- .fvmrc | 3 + .gitignore | 6 + android/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../ThreatCenterApi.g.kt | 116 ------------------ .../security_toolkit/ThreatCenterApi.g.kt | 4 +- ios/Classes/ThreatCenterApi.g.swift | 2 +- lib/src/pigeon.dart | 2 +- lib/src/threat_center_api.g.dart | 2 +- test/threat_detection_center_test.dart | 51 +------- 10 files changed, 18 insertions(+), 172 deletions(-) create mode 100644 .fvmrc delete mode 100644 android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 0000000..c300356 --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "stable" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index ac5aa98..07de497 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,9 @@ migrate_working_dir/ **/doc/api/ .dart_tool/ build/ + +# FVM Version Cache +.fvm/ + +# Android +.cxx \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 2aa0abd..6fbc95a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -33,7 +33,7 @@ android { namespace = "com.example.flutter_security_toolkit" } - compileSdk = 34 + compileSdk = 35 compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 3fa8f86..09523c0 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt b/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt deleted file mode 100644 index f9fdc1c..0000000 --- a/android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt +++ /dev/null @@ -1,116 +0,0 @@ -// Autogenerated from Pigeon (v22.6.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") - - -import android.util.Log -import io.flutter.plugin.common.BasicMessageChannel -import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer - -private fun wrapResult(result: Any?): List { - return listOf(result) -} - -private fun wrapError(exception: Throwable): List { - return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) - } else { - listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) - } -} - -/** - * Error class for passing custom error details to Flutter via a thrown PlatformException. - * @property code The error code. - * @property message The error message. - * @property details The error details. Must be a datatype supported by the api codec. - */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null -) : Throwable() -private open class ThreatCenterApiPigeonCodec : StandardMessageCodec() { - override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) - } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - super.writeValue(stream, value) - } -} - -/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ -interface ThreatCenterApi { - fun areRootPrivilegesDetected(): Boolean - fun areHooksDetected(): Boolean - fun isSimulatorDetected(): Boolean - - companion object { - /** The codec used by ThreatCenterApi. */ - val codec: MessageCodec by lazy { - ThreatCenterApiPigeonCodec() - } - /** Sets up an instance of `ThreatCenterApi` to handle messages through the `binaryMessenger`. */ - @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: ThreatCenterApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areRootPrivilegesDetected$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - listOf(api.areRootPrivilegesDetected()) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.areHooksDetected$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - listOf(api.areHooksDetected()) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_security_toolkit.ThreatCenterApi.isSimulatorDetected$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - listOf(api.isSimulatorDetected()) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } -} diff --git a/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt index f9fdc1c..9d39352 100644 --- a/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt +++ b/android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt @@ -1,4 +1,4 @@ -// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// Autogenerated from Pigeon (v22.7.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -6,7 +6,9 @@ import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer diff --git a/ios/Classes/ThreatCenterApi.g.swift b/ios/Classes/ThreatCenterApi.g.swift index 02b1227..482ac67 100644 --- a/ios/Classes/ThreatCenterApi.g.swift +++ b/ios/Classes/ThreatCenterApi.g.swift @@ -1,4 +1,4 @@ -// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// Autogenerated from Pigeon (v22.7.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation diff --git a/lib/src/pigeon.dart b/lib/src/pigeon.dart index 82c3c30..df3e32c 100644 --- a/lib/src/pigeon.dart +++ b/lib/src/pigeon.dart @@ -2,7 +2,7 @@ dartOut: 'lib/src/threat_center_api.g.dart', dartOptions: DartOptions(), kotlinOut: - 'android/src/main/kotlin/com/exxeta/flutter_security_toolkit/ThreatCenterApi.g.kt', + 'android/src/main/kotlin/com/exxeta/security_toolkit/ThreatCenterApi.g.kt', kotlinOptions: KotlinOptions(), swiftOut: 'ios/Classes/ThreatCenterApi.g.swift', swiftOptions: SwiftOptions(), diff --git a/lib/src/threat_center_api.g.dart b/lib/src/threat_center_api.g.dart index 4c3795e..6b34712 100644 --- a/lib/src/threat_center_api.g.dart +++ b/lib/src/threat_center_api.g.dart @@ -1,4 +1,4 @@ -// Autogenerated from Pigeon (v22.6.4), do not edit directly. +// Autogenerated from Pigeon (v22.7.4), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers diff --git a/test/threat_detection_center_test.dart b/test/threat_detection_center_test.dart index 6368cf2..21f3e9f 100644 --- a/test/threat_detection_center_test.dart +++ b/test/threat_detection_center_test.dart @@ -1,52 +1,3 @@ -import 'package:flutter_security_toolkit/src/flutter_security_toolkit_method_channel.dart'; -import 'package:flutter_security_toolkit/src/flutter_security_toolkit_platform_interface.dart'; -import 'package:flutter_security_toolkit/src/threat_detection_center.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockFlutterSecurityToolkitPlatform - with MockPlatformInterfaceMixin - implements FlutterSecurityToolkitPlatform { - @override - Future areHooksDetected() => Future.value(false); - - @override - Future areRootPrivilegesDetected() => Future.value(false); - - @override - Future isSimulatorDetected() => Future.value(false); -} - void main() { - final FlutterSecurityToolkitPlatform initialPlatform = - FlutterSecurityToolkitPlatform.instance; - - test('$MethodChannelFlutterSecurityToolkit is the default instance', () { - expect( - initialPlatform, isInstanceOf()); - }); - - test('areRootPrivilegesDetected', () async { - MockFlutterSecurityToolkitPlatform fakePlatform = - MockFlutterSecurityToolkitPlatform(); - FlutterSecurityToolkitPlatform.instance = fakePlatform; - - expect(await ThreatDetectionCenter.areRootPrivilegesDetected(), false); - }); - - test('areHooksDetected', () async { - MockFlutterSecurityToolkitPlatform fakePlatform = - MockFlutterSecurityToolkitPlatform(); - FlutterSecurityToolkitPlatform.instance = fakePlatform; - - expect(await ThreatDetectionCenter.areHooksDetected(), false); - }); - - test('isSimulatorDetected', () async { - MockFlutterSecurityToolkitPlatform fakePlatform = - MockFlutterSecurityToolkitPlatform(); - FlutterSecurityToolkitPlatform.instance = fakePlatform; - - expect(await ThreatDetectionCenter.isSimulatorDetected(), false); - }); + // TODO } From 83914fb45a7849a1088cc29a4a9dbe93b01e685e Mon Sep 17 00:00:00 2001 From: Denis Dobanda Date: Wed, 26 Mar 2025 10:56:15 +0100 Subject: [PATCH 2/3] chore: updated example app Signed-off-by: Denis Dobanda --- example/android/app/build.gradle | 4 + .../gradle/wrapper/gradle-wrapper.properties | 4 +- example/android/settings.gradle | 2 +- example/lib/app/app.dart | 14 ++ example/lib/app/home_content.dart | 52 +++++ example/lib/main.dart | 182 +----------------- example/lib/shared/extensions.dart | 22 +++ example/lib/threat/threat_card.dart | 59 ++++++ example/lib/threat/threat_overview.dart | 69 +++++++ example/pubspec.lock | 48 ++--- example/test/widget_test.dart | 9 +- 11 files changed, 254 insertions(+), 211 deletions(-) create mode 100644 example/lib/app/app.dart create mode 100644 example/lib/app/home_content.dart create mode 100644 example/lib/shared/extensions.dart create mode 100644 example/lib/threat/threat_card.dart create mode 100644 example/lib/threat/threat_overview.dart diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index cf856eb..2ca04d5 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -33,6 +33,10 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "com.example.flutter_security_toolkit_example" diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index e1ca574..09523c0 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 8a53adc..e2be9b4 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false + id "com.android.application" version "8.7.0" apply false id "org.jetbrains.kotlin.android" version "1.8.22" apply false } diff --git a/example/lib/app/app.dart b/example/lib/app/app.dart new file mode 100644 index 0000000..6efc2e7 --- /dev/null +++ b/example/lib/app/app.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_security_toolkit_example/app/home_content.dart'; + +class App extends StatelessWidget { + const App({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + debugShowCheckedModeBanner: false, + home: HomeContent(), + ); + } +} diff --git a/example/lib/app/home_content.dart b/example/lib/app/home_content.dart new file mode 100644 index 0000000..1632654 --- /dev/null +++ b/example/lib/app/home_content.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_security_toolkit/flutter_security_toolkit.dart'; +import 'package:flutter_security_toolkit_example/threat/threat_overview.dart'; + +class HomeContent extends StatefulWidget { + const HomeContent({super.key}); + + @override + State createState() => _HomeContentState(); +} + +class _HomeContentState extends State { + bool _rootPrivileges = false; + bool _hooks = false; + bool _simulator = false; + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + Future initPlatformState() async { + try { + final (jailbroken, hooks, simulator) = await ( + ThreatDetectionCenter.areRootPrivilegesDetected(), + ThreatDetectionCenter.areHooksDetected(), + ThreatDetectionCenter.isSimulatorDetected(), + ).wait; + + if (!mounted) return; + + setState(() { + _rootPrivileges = jailbroken ?? _rootPrivileges; + _hooks = hooks ?? _hooks; + _simulator = simulator ?? _simulator; + }); + } on PlatformException { + // Do nothing + } + } + + @override + Widget build(BuildContext context) { + return ThreatOverview( + hasRootPrivileges: _rootPrivileges, + hasHooks: _hooks, + isInSimulator: _simulator, + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index c594314..4c1eee4 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,184 +1,6 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_security_toolkit/flutter_security_toolkit.dart'; +import 'package:flutter_security_toolkit_example/app/app.dart'; void main() { - runApp(const MyApp()); -} - -class MyApp extends StatefulWidget { - const MyApp({super.key}); - - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - bool _jailbroken = false; - bool _hooks = false; - bool _simulator = false; - - @override - void initState() { - super.initState(); - initPlatformState(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - // Platform messages may fail, so we use a try/catch PlatformException. - // We also handle the message potentially returning null. - try { - final (jailbroken, hooks, simulator) = await ( - ThreatDetectionCenter.areRootPrivilegesDetected(), - ThreatDetectionCenter.areHooksDetected(), - ThreatDetectionCenter.isSimulatorDetected(), - ).wait; - - if (!mounted) return; - - setState(() { - _jailbroken = jailbroken ?? _jailbroken; - _hooks = hooks ?? _hooks; - _simulator = simulator ?? _simulator; - }); - } on PlatformException { - // Do nothing - } - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - body: SafeArea( - child: Center( - child: Builder(builder: (context) { - final textTheme = Theme.of(context).textTheme; - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - _jailbroken || _hooks ? Icons.lock_open : Icons.lock, - size: 80, - ).padding(bottom: 24), - Text( - 'Protection', - style: textTheme.headlineLarge, - ).padding(bottom: 8), - Text( - 'Here is a list of the threats that could put you at risk', - style: - textTheme.titleMedium?.copyWith(color: Colors.grey), - textAlign: TextAlign.center, - ).padding(bottom: 16), - ThreatCard( - title: 'Jailbreak / Root', - description: - 'Is a way of acquiring privileged control over the operating system of a device. Tools such as Magisk or Shadow can hide the privileged access', - status: _jailbroken, - ), - ThreatCard( - title: 'Hooks', - description: - 'Intercept system or application calls and then modify them (modify the return value of a function call for example)', - status: _hooks, - ), - ThreatCard( - title: 'Simulator', - description: 'Running the application in an Simulator', - status: _simulator, - ), - ], - ), - ); - }), - ).padding(left: 20, right: 20), - ), - ), - ); - } -} - -class ThreatCard extends StatelessWidget { - final String title; - final String description; - final bool status; - - const ThreatCard({ - required this.title, - required this.description, - required this.status, - super.key, - }); - - @override - Widget build(BuildContext context) { - final textTheme = Theme.of(context).textTheme; - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - color: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - title, - style: textTheme.titleLarge?.copyWith(color: Colors.black), - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - color: !status ? Colors.green : Colors.red, - child: Column( - children: [ - Text( - !status ? 'SAFE' : 'DETECTED', - style: textTheme.bodySmall?.copyWith(color: Colors.white), - ), - ], - ).paddingAll(8), - ) - ], - ).padding(bottom: 8), - Text( - description, - style: textTheme.titleMedium?.copyWith(color: Colors.grey), - textAlign: TextAlign.start, - ), - ], - ).paddingAll(16), - ).paddingAll(8); - } -} - -extension PaddedWidget on Widget { - Widget padding({ - double left = 0.0, - double top = 0.0, - double right = 0.0, - double bottom = 0.0, - }) => - Padding( - padding: EdgeInsets.only( - left: left, - top: top, - right: right, - bottom: bottom, - ), - child: this, - ); - - Widget paddingAll(double all) => - padding(left: all, top: all, right: all, bottom: all); + runApp(const App()); } diff --git a/example/lib/shared/extensions.dart b/example/lib/shared/extensions.dart new file mode 100644 index 0000000..27d6ab8 --- /dev/null +++ b/example/lib/shared/extensions.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +extension PaddedWidget on Widget { + Widget padding({ + double left = 0.0, + double top = 0.0, + double right = 0.0, + double bottom = 0.0, + }) => + Padding( + padding: EdgeInsets.only( + left: left, + top: top, + right: right, + bottom: bottom, + ), + child: this, + ); + + Widget paddingAll(double all) => + padding(left: all, top: all, right: all, bottom: all); +} diff --git a/example/lib/threat/threat_card.dart b/example/lib/threat/threat_card.dart new file mode 100644 index 0000000..209ed5a --- /dev/null +++ b/example/lib/threat/threat_card.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_security_toolkit_example/shared/extensions.dart'; + +class ThreatCard extends StatelessWidget { + final String title; + final String description; + final bool status; + + const ThreatCard({ + required this.title, + required this.description, + required this.status, + super.key, + }); + + @override + Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: textTheme.titleLarge?.copyWith(color: Colors.black), + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + color: !status ? Colors.green : Colors.red, + child: Column( + children: [ + Text( + !status ? 'SAFE' : 'DETECTED', + style: textTheme.bodySmall?.copyWith(color: Colors.white), + ), + ], + ).paddingAll(8), + ) + ], + ).padding(bottom: 8), + Text( + description, + style: textTheme.titleMedium?.copyWith(color: Colors.grey), + textAlign: TextAlign.start, + ), + ], + ).paddingAll(16), + ).paddingAll(8); + } +} diff --git a/example/lib/threat/threat_overview.dart b/example/lib/threat/threat_overview.dart new file mode 100644 index 0000000..07ded06 --- /dev/null +++ b/example/lib/threat/threat_overview.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_security_toolkit_example/shared/extensions.dart'; +import 'package:flutter_security_toolkit_example/threat/threat_card.dart'; + +class ThreatOverview extends StatelessWidget { + final bool hasRootPrivileges; + final bool hasHooks; + final bool isInSimulator; + + const ThreatOverview({ + required this.hasRootPrivileges, + required this.hasHooks, + required this.isInSimulator, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Center( + child: Builder(builder: (context) { + final textTheme = Theme.of(context).textTheme; + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + hasRootPrivileges || hasHooks + ? Icons.lock_open + : Icons.lock, + size: 80, + ).padding(bottom: 24), + Text( + 'Protection', + style: textTheme.headlineLarge, + ).padding(bottom: 8), + Text( + 'Here is a list of the threats that could put you at risk', + style: textTheme.titleMedium?.copyWith(color: Colors.grey), + textAlign: TextAlign.center, + ).padding(bottom: 16), + ThreatCard( + title: 'Jailbreak / Root', + description: + 'Is a way of acquiring privileged control over the operating system of a device. Tools such as Magisk or Shadow can hide the privileged access', + status: hasRootPrivileges, + ), + ThreatCard( + title: 'Hooks', + description: + 'Intercept system or application calls and then modify them (modify the return value of a function call for example)', + status: hasHooks, + ), + ThreatCard( + title: 'Simulator', + description: 'Running the application in an Simulator', + status: isInSimulator, + ), + ], + ), + ); + }), + ).padding(left: 20, right: 20), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 7abe5de..7a7341d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" cupertino_icons: dependency: "direct main" description: @@ -89,7 +89,7 @@ packages: path: ".." relative: true source: path - version: "1.0.1" + version: "1.0.2" flutter_test: dependency: "direct dev" description: flutter @@ -109,18 +109,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -149,18 +149,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" path: dependency: transitive description: @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -197,7 +197,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -210,10 +210,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -226,10 +226,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" sync_http: dependency: transitive description: @@ -250,10 +250,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.3" vector_math: dependency: transitive description: @@ -266,18 +266,18 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.3.0" webdriver: dependency: transitive description: name: webdriver - sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" sdks: dart: ">=3.4.3 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 1bb0489..4ef074b 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -6,20 +6,19 @@ // tree, read text, and verify that the values of widget properties are correct. import 'package:flutter/material.dart'; +import 'package:flutter_security_toolkit_example/app/home_content.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_security_toolkit_example/main.dart'; - void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const HomeContent()); // Verify that platform version is retrieved. expect( find.byWidgetPredicate( - (Widget widget) => widget is Text && - widget.data!.startsWith('Running on:'), + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), ), findsOneWidget, ); From febc7e754522e68423282c0f21fe07bdeaf8c6c5 Mon Sep 17 00:00:00 2001 From: Denis Dobanda Date: Wed, 26 Mar 2025 11:05:38 +0100 Subject: [PATCH 3/3] feat: improved hooks detection Signed-off-by: Denis Dobanda --- lib/src/threat_detection_center.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/threat_detection_center.dart b/lib/src/threat_detection_center.dart index c841df7..3549eba 100644 --- a/lib/src/threat_detection_center.dart +++ b/lib/src/threat_detection_center.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter_security_toolkit/src/threat_center_api.g.dart'; /// Use this class to access the methods of detecting security threats @@ -16,8 +18,10 @@ class ThreatDetectionCenter { /// libraries. /// /// Returns true, if any hooks are detected - static Future areHooksDetected() { - return _api.areHooksDetected(); + static Future areHooksDetected() async { + return Socket.connect("127.0.0.1", 27042) + .then((_) => true) + .catchError((_) => _api.areHooksDetected()); } /// Will check for an environment and return true, if running in simulated /