├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── pull_request_template.md └── workflows │ ├── flutter-ci.yml │ └── issue_watcher.yaml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── app │ │ │ │ └── talsec │ │ │ │ └── free_malware_detection │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── lib ├── app.dart ├── home │ ├── providers │ │ ├── providers.dart │ │ ├── threat_notifier.dart │ │ └── threat_state.dart │ ├── views │ │ ├── home_page.dart │ │ ├── malware_bottom_sheet.dart │ │ └── views.dart │ └── widgets │ │ ├── app_icon.dart │ │ ├── dismiss_background.dart │ │ ├── malware_item.dart │ │ ├── spinning_icon.dart │ │ ├── status_tile.dart │ │ └── widgets.dart ├── main.dart └── services │ ├── services.dart │ └── talsec_service.dart ├── pubspec.lock └── pubspec.yaml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: talsec-app 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | If applicable, steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Please complete the following information:** 23 | - Device: [e.g. Samsung Galaxy A50] 24 | - OS version: [e.g. Android 12] 25 | - Version of freeRASP: [e.g. 6.0.0] 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: talsec-app 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # .freeMalwareDetection 2 | 3 | 4 | 5 | ## Pre-release checklist 6 | - [ ] 🔎 Malware detection works 7 | - [ ] 📝 Whitelisting works 8 | - [ ] 📝 Logging works 9 | - [ ] 📋 Changelog updated 10 | - [ ] ➡️ `pubspec.yaml` version updated 11 | 12 | 13 | ## Post-release checklist 14 | - [ ] 📝 GitHub release 15 | 16 | ## Type of Changes 17 | 18 | - [ ] ✨ New feature (non-breaking change which adds functionality) 19 | - [ ] 🛠️ Bug fix (non-breaking change which fixes an issue) 20 | - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change) 21 | - [ ] 🧹 Code refactor 22 | - [ ] ✅ Build configuration change 23 | - [ ] 📝 Documentation 24 | - [ ] 🗑️ Chore 25 | 26 | ## Description 27 | 28 | 37 | -------------------------------------------------------------------------------- /.github/workflows/flutter-ci.yml: -------------------------------------------------------------------------------- 1 | name: Flutter CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths-ignore: 8 | - '**/*.md' 9 | - '.github/**' 10 | pull_request: 11 | branches: 12 | - main 13 | paths-ignore: 14 | - '**/*.md' 15 | - '.github/**' 16 | 17 | workflow_dispatch: 18 | 19 | env: 20 | FLUTTER_VERSION: 3.24.0 21 | 22 | jobs: 23 | lint: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: 📚 Git Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: 🐦 Setup Flutter 30 | uses: subosito/flutter-action@v2.16.0 31 | with: 32 | channel: stable 33 | flutter-version: ${{ env.FLUTTER_VERSION }} 34 | cache: true 35 | 36 | - name: ✂ Format Code 37 | run: dart format --set-exit-if-changed . 38 | 39 | - name: 📊 Analyze Code 40 | run: flutter analyze --fatal-infos --fatal-warnings . 41 | 42 | build-android: 43 | runs-on: ubuntu-latest 44 | 45 | steps: 46 | - name: 📚 Git Checkout 47 | uses: actions/checkout@v4 48 | 49 | - name: 🐦 Setup Flutter 50 | uses: subosito/flutter-action@v2.16.0 51 | with: 52 | channel: stable 53 | flutter-version: ${{ env.FLUTTER_VERSION }} 54 | cache: true 55 | 56 | - name: 🤖 Build Android app 57 | run: flutter build apk --release 58 | -------------------------------------------------------------------------------- /.github/workflows/issue_watcher.yaml: -------------------------------------------------------------------------------- 1 | name: Issue watcher 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | # Date follows the cron syntax: https://en.wikipedia.org/wiki/Cron 6 | # Every Monday at 6:30 AM 7 | - cron: '30 6 * * 1' 8 | 9 | jobs: 10 | check_issues: 11 | uses: talsec/github-workflows/.github/workflows/issue_watcher.yml@master 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 17 | base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 18 | - platform: android 19 | create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 20 | base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.0.0] - 2024-11-08 9 | - Initial release -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Talsec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![freeMalwareDetection](https://raw.githubusercontent.com/talsec/freeMalwareDetection/main/visuals/freeMalwareDetection.png) 2 | 3 | # freeMalwareDetection for Flutter 4 | 5 | Enhance the security of your Android application with Free Malware Detection, a powerful feature designed to scan for malicious or suspicious apps. Leveraging various blacklists and security policies, this tool ensures your application remains protected from known threats, providing a secure environment for your users. 6 | 7 | ## Overview 8 | 9 | freeMalwareDetection is an easy-to-integrate SDK that operates asynchronously to safeguard your application without compromising performance. It runs scans in the background, ensuring that your app's performance remains unaffected while delivering comprehensive security checks. This SDK is freely available and designed for seamless integration with the freeRASP SDK, delivering a comprehensive security solution. 10 | 11 | Learn more about freemium freeMalwareDetection features at [GitHub main repository](https://github.com/talsec/freeMalwareDetection). 12 | 13 | ## :key: Key Advantages 14 | 15 | - **Asynchronous Scanning**: Perform malware scans in the background without impacting app performance. 16 | - **Threat Analysis**: Receive information about detected threats to better inform and protect your users. 17 | - **Simple Integration**: Easy-to-follow integration process with extensive documentation and support. 18 | - **Versatile Blacklisting**: Supports hash-based, package name-based, and permission-based blacklists for comprehensive threat detection. 19 | - **Seamless Operation**: Integrates smoothly with freeRASP SDK to provide an all-in-one security solution. 20 | 21 | ## 🎯 Features 22 | 23 | Free Malware Detection provides protection against potentially dangerous applications and behaviors, including: 24 | 25 | ✔️ Detection of apps with suspicious package names or hashes. 26 | 27 | ✔️ Blocking of apps with disallowed permissions. 28 | 29 | ✔️ Whitelisting of trusted installation sources to prevent unauthorized app installations. 30 | 31 | Visit our wiki to learn more about the specific checks performed and their impact on app security. 32 | 33 | ## 📖 Discover Official Documentation 34 | 35 | Explore our [GitBook page](https://docs.talsec.app/freemalwaredetection) for detailed guides, tutorials, and technical documentation. 36 | 37 | ## 🔗 Integration Guide 38 | 39 | To integrate Free Malware Detection, follow our step-by-step [Integration Guide](https://docs.talsec.app/freemalwaredetection/integration-guide/requirements). This guide provides all the details you need for a smooth setup process on any platform. 40 | 41 | ## ✨ Enhancements 42 | 43 | If you have any suggestions for improvement or notice anything that could be clarified in the new documentation, please open an issue. Your feedback helps us maintain high-quality resources for all users. 44 | 45 | You can check out the [project board](https://github.com/orgs/talsec/projects/3) here. 46 | 47 | ## :wave: Come and Be Part of the Community! 48 | 49 | Explore the **freeMalware Discussion section** for: 50 | 51 | - Support and Q&A :books: 52 | - Announcements :mega: 53 | - Community collaboration 🛠️ 54 | 55 | :point_right: [Join the Discussion](https://github.com/talsec/freeMalwareDetection/discussions) :point_left: 56 | 57 | ## :page_facing_up: License 58 | This project is provided as freemium software, i.e. there is a fair usage policy that imposes some limitations on the free usage. The SDK software consists of open-source and binary parts, which is the property of Talsec. The open-source part is licensed under the MIT License - see the LICENSE file for details. 59 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file("local.properties") 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader("UTF-8") { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty("flutter.versionCode") 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = "1" 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty("flutter.versionName") 21 | if (flutterVersionName == null) { 22 | flutterVersionName = "1.0" 23 | } 24 | 25 | android { 26 | namespace = "app.talsec.free_malware_detection" 27 | compileSdk = flutter.compileSdkVersion 28 | ndkVersion = flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility = JavaVersion.VERSION_1_8 32 | targetCompatibility = JavaVersion.VERSION_1_8 33 | } 34 | 35 | defaultConfig { 36 | applicationId = "app.talsec.free_malware_detection" 37 | // You can update the following values to match your application needs. 38 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 39 | minSdk = 23 40 | targetSdk = flutter.targetSdkVersion 41 | versionCode = flutterVersionCode.toInteger() 42 | versionName = flutterVersionName 43 | } 44 | 45 | buildTypes { 46 | release { 47 | // TODO: Add your own signing config for the release build. 48 | // Signing with the debug keys for now, so `flutter run --release` works. 49 | signingConfig = signingConfigs.debug 50 | } 51 | } 52 | } 53 | 54 | flutter { 55 | source = "../.." 56 | } 57 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/talsec/free_malware_detection/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package app.talsec.free_malware_detection 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talsec/freeMalwareDetection-Flutter/1f424b056baff2669c92a21fb503c7e15587b254/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talsec/freeMalwareDetection-Flutter/1f424b056baff2669c92a21fb503c7e15587b254/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talsec/freeMalwareDetection-Flutter/1f424b056baff2669c92a21fb503c7e15587b254/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talsec/freeMalwareDetection-Flutter/1f424b056baff2669c92a21fb503c7e15587b254/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talsec/freeMalwareDetection-Flutter/1f424b056baff2669c92a21fb503c7e15587b254/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "7.3.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /lib/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:free_malware_detection/home/views/views.dart'; 3 | 4 | /// The root widget of the application 5 | class App extends StatelessWidget { 6 | const App({super.key}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | title: 'Flutter Demo', 12 | theme: ThemeData(primarySwatch: Colors.blue), 13 | home: const HomePage(), 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/home/providers/providers.dart: -------------------------------------------------------------------------------- 1 | export 'threat_notifier.dart'; 2 | export 'threat_state.dart'; 3 | -------------------------------------------------------------------------------- /lib/home/providers/threat_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:free_malware_detection/home/providers/threat_state.dart'; 3 | import 'package:freerasp/freerasp.dart'; 4 | 5 | /// Class responsible for setting up listeners to detected threats 6 | class ThreatNotifier extends AutoDisposeNotifier { 7 | @override 8 | ThreatState build() { 9 | _init(); 10 | return ThreatState(detectedMalware: {}, isDetected: false); 11 | } 12 | 13 | void _init() { 14 | final threatCallback = ThreatCallback(onMalware: _updateMalware); 15 | Talsec.instance.attachListener(threatCallback); 16 | } 17 | 18 | void _updateMalware(List malware) { 19 | state = state.copyWith( 20 | detectedMalware: malware.nonNulls.toSet(), 21 | hasDetectedMalware: true, 22 | ); 23 | } 24 | 25 | void removeMalware(SuspiciousAppInfo malware) { 26 | final malwareSet = state.detectedMalware..remove(malware); 27 | state = state.copyWith(detectedMalware: malwareSet); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/home/providers/threat_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:freerasp/freerasp.dart'; 2 | 3 | class ThreatState { 4 | ThreatState({ 5 | required this.detectedMalware, 6 | required this.isDetected, 7 | }); 8 | 9 | final Set detectedMalware; 10 | final bool isDetected; 11 | 12 | ThreatState copyWith({ 13 | Set? detectedMalware, 14 | bool? hasDetectedMalware, 15 | }) { 16 | return ThreatState( 17 | detectedMalware: detectedMalware ?? this.detectedMalware, 18 | isDetected: hasDetectedMalware ?? isDetected, 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/home/views/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:free_malware_detection/home/views/views.dart'; 4 | import 'package:free_malware_detection/home/widgets/widgets.dart'; 5 | 6 | import 'package:free_malware_detection/main.dart'; 7 | import 'package:freerasp/freerasp.dart'; 8 | 9 | /// The home page that displays the threats and results 10 | class HomePage extends ConsumerWidget { 11 | const HomePage({super.key}); 12 | 13 | @override 14 | Widget build(BuildContext context, WidgetRef ref) { 15 | final threatState = ref.watch(threatProvider); 16 | 17 | return Scaffold( 18 | appBar: AppBar(title: const Text('freeMalwareDetection Demo')), 19 | body: SafeArea( 20 | child: Center( 21 | child: Column( 22 | mainAxisAlignment: MainAxisAlignment.center, 23 | children: [ 24 | const StatusTile( 25 | title: '.freeRASP', 26 | subtitle: 'Up and running', 27 | icon: Icons.check_circle_outline_rounded, 28 | iconColor: Colors.green, 29 | ), 30 | StatusTile( 31 | title: '.freeMalwareDetection', 32 | subtitle: threatState.isDetected ? 'Scan done' : 'Scan running', 33 | icon: threatState.isDetected 34 | ? Icons.check_circle_outline_rounded 35 | : Icons.sync_outlined, 36 | iconColor: 37 | threatState.isDetected ? Colors.green : Colors.orange, 38 | isSpinning: !threatState.isDetected, // Spins if scan is running 39 | ), 40 | Visibility( 41 | visible: threatState.isDetected, 42 | child: OutlinedButton( 43 | onPressed: () => _showMalwareBottomSheet( 44 | context, 45 | threatState.detectedMalware.toList(), 46 | ref, 47 | ), 48 | child: Text( 49 | 'Show Results'.toUpperCase(), 50 | style: Theme.of(context).textTheme.labelLarge, 51 | ), 52 | ), 53 | ), 54 | ], 55 | ), 56 | ), 57 | ), 58 | ); 59 | } 60 | } 61 | 62 | void _showMalwareBottomSheet( 63 | BuildContext context, 64 | List suspiciousApps, 65 | WidgetRef ref, 66 | ) { 67 | WidgetsBinding.instance.addPostFrameCallback((_) { 68 | showModalBottomSheet( 69 | context: context, 70 | isDismissible: false, 71 | enableDrag: false, 72 | isScrollControlled: true, 73 | builder: (BuildContext context) => MalwareBottomSheet( 74 | suspiciousApps: suspiciousApps, 75 | onDismiss: () => Navigator.pop(context), 76 | ), 77 | ); 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /lib/home/views/malware_bottom_sheet.dart: -------------------------------------------------------------------------------- 1 | import 'package:android_intent_plus/android_intent.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:free_malware_detection/home/widgets/widgets.dart'; 5 | import 'package:free_malware_detection/main.dart'; 6 | import 'package:free_malware_detection/services/talsec_service.dart'; 7 | import 'package:freerasp/freerasp.dart'; 8 | 9 | /// Bottom sheet widget that displays malware information 10 | class MalwareBottomSheet extends ConsumerWidget { 11 | /// Represents malware information in the example app 12 | const MalwareBottomSheet({ 13 | required this.suspiciousApps, 14 | required this.onDismiss, 15 | super.key, 16 | }); 17 | 18 | /// List of suspicious apps 19 | final List suspiciousApps; 20 | final void Function()? onDismiss; 21 | 22 | @override 23 | Widget build(BuildContext context, WidgetRef ref) { 24 | final textTheme = Theme.of(context).textTheme; 25 | final suspiciousApps = ref.watch(threatProvider).detectedMalware.toList(); 26 | 27 | return Container( 28 | height: double.infinity, 29 | padding: const EdgeInsets.all(8), 30 | child: Column( 31 | children: [ 32 | Text('Suspicious Apps', style: textTheme.titleMedium), 33 | const SizedBox(height: 8), 34 | Expanded( 35 | child: ListView.builder( 36 | itemCount: suspiciousApps.length, 37 | itemBuilder: (_, index) { 38 | final item = suspiciousApps[index]; 39 | return MalwareItem( 40 | packageInfo: item.packageInfo, 41 | reason: item.reason, 42 | onWhitelist: () { 43 | _removeItem(ref, item); 44 | TalsecService.whitelistApp(item); 45 | }, 46 | onUninstall: () => _launchUninstall(item), 47 | onDismiss: () { 48 | _whitelistApp(item); 49 | _removeItem(ref, item); 50 | }, 51 | ); 52 | }, 53 | ), 54 | ), 55 | const SizedBox(height: 16), 56 | SizedBox( 57 | width: double.infinity, 58 | child: FilledButton( 59 | onPressed: onDismiss, 60 | child: const Text('Dismiss'), 61 | ), 62 | ), 63 | ], 64 | ), 65 | ); 66 | } 67 | 68 | void _removeItem(WidgetRef ref, SuspiciousAppInfo item) { 69 | ref.read(threatProvider.notifier).removeMalware(item); 70 | } 71 | 72 | Future _whitelistApp(SuspiciousAppInfo malware) async { 73 | await TalsecService.whitelistApp(malware); 74 | } 75 | 76 | Future _launchUninstall(SuspiciousAppInfo item) async { 77 | // Launch uninstall intent 78 | final packageName = item.packageInfo.packageName; 79 | await AndroidIntent( 80 | action: 'action_application_details_settings', 81 | data: 'package:$packageName', 82 | ).launch(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/home/views/views.dart: -------------------------------------------------------------------------------- 1 | export 'home_page.dart'; 2 | export 'malware_bottom_sheet.dart'; 3 | -------------------------------------------------------------------------------- /lib/home/widgets/app_icon.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | /// Displays the app icon or a default warning icon if unavailable 6 | class AppIcon extends StatelessWidget { 7 | const AppIcon({super.key, this.base64Icon}); 8 | 9 | final String? base64Icon; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | if (base64Icon == null) { 14 | return const Icon(Icons.warning, color: Colors.red); 15 | } 16 | 17 | return Padding( 18 | padding: const EdgeInsets.all(4), 19 | child: Image.memory(base64.decode(base64Icon!)), 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/home/widgets/dismiss_background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Dismiss background widget with a customizable message 4 | class DismissBackground extends StatelessWidget { 5 | const DismissBackground({required this.message, super.key}); 6 | 7 | final String message; 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final textTheme = Theme.of(context).textTheme; 12 | return Container( 13 | color: Colors.amber, 14 | alignment: Alignment.centerLeft, 15 | padding: const EdgeInsets.only(left: 16), 16 | child: Row( 17 | children: [ 18 | const Icon(Icons.close, color: Colors.white), 19 | const SizedBox(width: 8), 20 | Text( 21 | message.toUpperCase(), 22 | style: textTheme.labelLarge?.copyWith(color: Colors.white), 23 | ), 24 | ], 25 | ), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/home/widgets/malware_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:free_malware_detection/home/widgets/widgets.dart'; 3 | import 'package:freerasp/freerasp.dart'; 4 | 5 | extension on PackageInfo { 6 | String get validAppName => appName ?? packageName; 7 | } 8 | 9 | /// List tile widget that displays malware information 10 | class MalwareItem extends StatelessWidget { 11 | /// Represents malware information in the example app 12 | const MalwareItem({ 13 | required this.packageInfo, 14 | required this.reason, 15 | this.onWhitelist, 16 | this.onUninstall, 17 | this.onDismiss, 18 | super.key, 19 | }); 20 | 21 | final PackageInfo packageInfo; 22 | final String reason; 23 | final void Function()? onWhitelist; 24 | final void Function()? onUninstall; 25 | final void Function()? onDismiss; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Dismissible( 30 | key: ValueKey(packageInfo.packageName), 31 | onDismissed: (_) => onDismiss?.call(), 32 | direction: DismissDirection.startToEnd, 33 | background: const DismissBackground(message: 'Dismiss'), 34 | child: ExpansionTile( 35 | tilePadding: const EdgeInsets.all(8), 36 | title: Text(packageInfo.validAppName), 37 | leading: AppIcon(base64Icon: packageInfo.appIcon), 38 | children: [ 39 | ListTile( 40 | title: const Text('Package Name'), 41 | subtitle: Text(packageInfo.packageName), 42 | ), 43 | ListTile( 44 | title: const Text('Installation Source'), 45 | subtitle: Text(packageInfo.installationSource ?? 'Unknown'), 46 | ), 47 | ListTile( 48 | title: const Text('Version'), 49 | subtitle: Text(packageInfo.version ?? 'Unknown'), 50 | ), 51 | ListTile( 52 | title: const Text('Detection Reason'), 53 | subtitle: Text(reason), 54 | ), 55 | OverflowBar( 56 | alignment: MainAxisAlignment.end, 57 | children: [ 58 | TextButton( 59 | onPressed: () => onWhitelist?.call(), 60 | child: const Text('Whitelist'), 61 | ), 62 | TextButton( 63 | onPressed: () => onUninstall?.call(), 64 | child: const Text('Uninstall'), 65 | ), 66 | ], 67 | ), 68 | ], 69 | ), 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/home/widgets/spinning_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SpinningIcon extends StatefulWidget { 4 | const SpinningIcon({ 5 | required this.icon, 6 | required this.iconColor, 7 | super.key, 8 | }); 9 | 10 | final IconData icon; 11 | final Color iconColor; 12 | 13 | @override 14 | State createState() => _SpinningIconState(); 15 | } 16 | 17 | class _SpinningIconState extends State 18 | with SingleTickerProviderStateMixin { 19 | late final AnimationController _controller = AnimationController( 20 | duration: const Duration(milliseconds: 1000), 21 | vsync: this, 22 | )..repeat(); 23 | 24 | late final Animation _curvedAnimation = CurvedAnimation( 25 | parent: _controller, 26 | curve: Curves.decelerate, 27 | ); 28 | 29 | @override 30 | void dispose() { 31 | _controller.dispose(); // Dispose of the controller to free resources 32 | super.dispose(); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return RotationTransition( 38 | turns: _curvedAnimation, 39 | child: Icon(widget.icon, color: widget.iconColor), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/home/widgets/status_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:free_malware_detection/home/widgets/widgets.dart'; 3 | 4 | class StatusTile extends StatelessWidget { 5 | const StatusTile({ 6 | required this.title, 7 | required this.subtitle, 8 | required this.icon, 9 | required this.iconColor, 10 | super.key, 11 | this.isSpinning = false, 12 | }); 13 | 14 | final String title; 15 | final String subtitle; 16 | final IconData icon; 17 | final Color iconColor; 18 | final bool isSpinning; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return ListTile( 23 | trailing: isSpinning 24 | ? SpinningIcon(icon: icon, iconColor: iconColor) 25 | : Icon(icon, color: iconColor), 26 | title: Text(title), 27 | subtitle: Text(subtitle), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/home/widgets/widgets.dart: -------------------------------------------------------------------------------- 1 | export 'app_icon.dart'; 2 | export 'dismiss_background.dart'; 3 | export 'malware_item.dart'; 4 | export 'spinning_icon.dart'; 5 | export 'status_tile.dart'; 6 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: public_member_api_docs, avoid_redundant_argument_values 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:free_malware_detection/app.dart'; 6 | import 'package:free_malware_detection/home/providers/providers.dart'; 7 | import 'package:free_malware_detection/services/talsec_service.dart'; 8 | 9 | /// Represents current state of the threats detectable by freeRASP 10 | final threatProvider = 11 | NotifierProvider.autoDispose( 12 | ThreatNotifier.new, 13 | ); 14 | 15 | Future main() async { 16 | WidgetsFlutterBinding.ensureInitialized(); 17 | await TalsecService.initialize(); 18 | runApp(const ProviderScope(child: App())); 19 | } 20 | -------------------------------------------------------------------------------- /lib/services/services.dart: -------------------------------------------------------------------------------- 1 | export 'talsec_service.dart'; 2 | -------------------------------------------------------------------------------- /lib/services/talsec_service.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_redundant_argument_values 2 | 3 | import 'package:freerasp/freerasp.dart'; 4 | 5 | class TalsecService { 6 | static Future initialize() async { 7 | final config = TalsecConfig( 8 | androidConfig: AndroidConfig( 9 | // ❗️ Do not retrieve any package information dynamically using 10 | // ❗️ package_info_plus or similar packages. These can return false 11 | // ❗️ information when the app is spoofed. 12 | packageName: 'app.talsec.free_malware_detection', 13 | signingCertHashes: ['AKoRuyLMM91E7lX/Zqp3u4jMmd0A7hH/Iqozu0TMVd0='], 14 | supportedStores: ['com.sec.android.app.samsungapps'], 15 | malwareConfig: MalwareConfig( 16 | // Let app detect itself as malware 17 | blacklistedPackageNames: ['app.talsec.free_malware_detection'], 18 | // Apps CANNOT have these (groups) of permissions 19 | suspiciousPermissions: [ 20 | [ 21 | 'android.permission.CAMERA', 22 | ], 23 | /* OR */ 24 | [ 25 | 'android.permission.READ_SMS', 26 | /* AND */ 27 | 'android.permission.READ_CONTACTS', 28 | ], 29 | ], 30 | ), 31 | ), 32 | watcherMail: 'your_mail@example.com', 33 | isProd: true, 34 | ); 35 | 36 | await Talsec.instance.start(config); 37 | } 38 | 39 | static Future whitelistApp(SuspiciousAppInfo malware) async { 40 | await Talsec.instance.addToWhitelist(malware.packageInfo.packageName); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | android_intent_plus: 5 | dependency: "direct main" 6 | description: 7 | name: android_intent_plus 8 | sha256: e1c62bb41c90e15083b7fb84dc327fe90396cc9c1445b55ff1082144fabfb4d9 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "4.0.3" 12 | async: 13 | dependency: transitive 14 | description: 15 | name: async 16 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.11.0" 20 | boolean_selector: 21 | dependency: transitive 22 | description: 23 | name: boolean_selector 24 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.1.1" 28 | characters: 29 | dependency: transitive 30 | description: 31 | name: characters 32 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.3.0" 36 | clock: 37 | dependency: transitive 38 | description: 39 | name: clock 40 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.1" 44 | collection: 45 | dependency: transitive 46 | description: 47 | name: collection 48 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.18.0" 52 | convert: 53 | dependency: transitive 54 | description: 55 | name: convert 56 | sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "3.1.2" 60 | fake_async: 61 | dependency: transitive 62 | description: 63 | name: fake_async 64 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.3.1" 68 | flutter: 69 | dependency: "direct main" 70 | description: flutter 71 | source: sdk 72 | version: "0.0.0" 73 | flutter_plugin_android_lifecycle: 74 | dependency: transitive 75 | description: 76 | name: flutter_plugin_android_lifecycle 77 | sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" 78 | url: "https://pub.dev" 79 | source: hosted 80 | version: "2.0.22" 81 | flutter_riverpod: 82 | dependency: "direct main" 83 | description: 84 | name: flutter_riverpod 85 | sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" 86 | url: "https://pub.dev" 87 | source: hosted 88 | version: "2.6.1" 89 | flutter_test: 90 | dependency: "direct dev" 91 | description: flutter 92 | source: sdk 93 | version: "0.0.0" 94 | freerasp: 95 | dependency: "direct main" 96 | description: 97 | name: freerasp 98 | sha256: f18b728a54b27d1dfc4666df27a12d04da4943072c65f3ad06a648f877979ba7 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "6.8.0" 102 | json_annotation: 103 | dependency: transitive 104 | description: 105 | name: json_annotation 106 | sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "4.9.0" 110 | leak_tracker: 111 | dependency: transitive 112 | description: 113 | name: leak_tracker 114 | sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "10.0.5" 118 | leak_tracker_flutter_testing: 119 | dependency: transitive 120 | description: 121 | name: leak_tracker_flutter_testing 122 | sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "3.0.5" 126 | leak_tracker_testing: 127 | dependency: transitive 128 | description: 129 | name: leak_tracker_testing 130 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "3.0.1" 134 | matcher: 135 | dependency: transitive 136 | description: 137 | name: matcher 138 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "0.12.16+1" 142 | material_color_utilities: 143 | dependency: transitive 144 | description: 145 | name: material_color_utilities 146 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 147 | url: "https://pub.dev" 148 | source: hosted 149 | version: "0.11.1" 150 | meta: 151 | dependency: transitive 152 | description: 153 | name: meta 154 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 155 | url: "https://pub.dev" 156 | source: hosted 157 | version: "1.15.0" 158 | path: 159 | dependency: transitive 160 | description: 161 | name: path 162 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 163 | url: "https://pub.dev" 164 | source: hosted 165 | version: "1.9.0" 166 | platform: 167 | dependency: transitive 168 | description: 169 | name: platform 170 | sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" 171 | url: "https://pub.dev" 172 | source: hosted 173 | version: "3.1.6" 174 | riverpod: 175 | dependency: transitive 176 | description: 177 | name: riverpod 178 | sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" 179 | url: "https://pub.dev" 180 | source: hosted 181 | version: "2.6.1" 182 | sky_engine: 183 | dependency: transitive 184 | description: flutter 185 | source: sdk 186 | version: "0.0.99" 187 | source_span: 188 | dependency: transitive 189 | description: 190 | name: source_span 191 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "1.10.0" 195 | stack_trace: 196 | dependency: transitive 197 | description: 198 | name: stack_trace 199 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "1.11.1" 203 | state_notifier: 204 | dependency: transitive 205 | description: 206 | name: state_notifier 207 | sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "1.0.0" 211 | stream_channel: 212 | dependency: transitive 213 | description: 214 | name: stream_channel 215 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "2.1.2" 219 | string_scanner: 220 | dependency: transitive 221 | description: 222 | name: string_scanner 223 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "1.2.0" 227 | term_glyph: 228 | dependency: transitive 229 | description: 230 | name: term_glyph 231 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 232 | url: "https://pub.dev" 233 | source: hosted 234 | version: "1.2.1" 235 | test_api: 236 | dependency: transitive 237 | description: 238 | name: test_api 239 | sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "0.7.2" 243 | typed_data: 244 | dependency: transitive 245 | description: 246 | name: typed_data 247 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "1.3.2" 251 | vector_math: 252 | dependency: transitive 253 | description: 254 | name: vector_math 255 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 256 | url: "https://pub.dev" 257 | source: hosted 258 | version: "2.1.4" 259 | very_good_analysis: 260 | dependency: "direct dev" 261 | description: 262 | name: very_good_analysis 263 | sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629" 264 | url: "https://pub.dev" 265 | source: hosted 266 | version: "6.0.0" 267 | vm_service: 268 | dependency: transitive 269 | description: 270 | name: vm_service 271 | sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" 272 | url: "https://pub.dev" 273 | source: hosted 274 | version: "14.2.5" 275 | sdks: 276 | dart: ">=3.4.1 <4.0.0" 277 | flutter: ">=3.22.0" 278 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: free_malware_detection 2 | description: "Flutter malware detection library for Android. Protect your app against potential threats with Talsec." 3 | publish_to: 'none' 4 | version: 1.0.0 5 | 6 | environment: 7 | sdk: '>=3.4.1 <4.0.0' 8 | 9 | dependencies: 10 | android_intent_plus: 4.0.3 11 | flutter: 12 | sdk: flutter 13 | flutter_riverpod: ^2.6.1 14 | freerasp: 6.8.0 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | very_good_analysis: ^6.0.0 20 | 21 | flutter: 22 | uses-material-design: true 23 | --------------------------------------------------------------------------------