Flutter应用列表检测插件applist_detector_flutter的使用

Flutter应用列表检测插件applist_detector_flutter的使用

A Flutter端口库用于检测可疑应用,如Magisk管理器、Xposed框架、异常环境、运行模拟器等。该库用Kotlin和Dart编写。

这并不是一个由Google官方支持的产品

截图

security tester app logo displaying syscall file detection displaying pm Conventional apis displaying emulator detection

| app logo | 您可以使用我们的应用 Security Tester,它是一个直接UI实现/示例库。 |

平台支持

Android iOS MacOS Web Linux Windows

特性

  • 检查系统文件中的可疑文件。

  • 检查可疑设置属性,如调试属性、VPN使用情况等。

  • 检查运行可疑应用的异常环境,如Magisk、Riru或Zygisk。

  • 检查应用是否在模拟器上运行,例如Genymotion、Bluestacks、Windows子系统等。

    注意: 这个功能不是100%准确的。但比其他库如 device_info_plussafe_device 更准确。

  • 检查Xposed框架是否已安装。

  • 使用Play Integrity API检查,帮助保护您的应用和游戏免受潜在的风险和欺诈性交互,如作弊和未经授权的访问,并允许您采取适当的措施来防止攻击和减少滥用。

贡献

欢迎通过创建问题或拉取请求来贡献此项目。任何帮助都将被感激❤️。更多信息请查看 CONTRIBUTING.md 文件。

TODO

这些是我们计划在未来添加的功能。

  • 完成 CONTRIBUTING.md 指南。
  • 添加更多针对Xposed框架的检查。
  • 添加对iOS的支持。
  • 添加100%文档覆盖率。
  • 添加100%测试覆盖率。

信用

免责声明

该工具旨在帮助用户轻松保护其应用,并且 不是100%无懈可击的。如果您正在寻找100%安全的解决方案,那么这不是正确的工具。该工具不应用于任何非法或恶意活动。仅将其用于良好用途。对于因使用此工具而造成的任何损害,我概不负责。

许可证

该库根据Apache 2.0许可证分发。更多详情请参阅 LICENSE DETAILS

示例代码

import 'dart:async';
import 'dart:developer';

import 'package:flutter/material.dart';

import 'package:applist_detector_flutter/applist_detector_flutter.dart';
import './utils.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Applist Detector Flutter',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: lightColorScheme,
      ),
      darkTheme: ThemeData.dark(useMaterial3: true).copyWith(
        colorScheme: darkColorScheme,
      ),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  [@override](/user/override)
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final _plugin = ApplistDetectorFlutter();
  bool isLoading = false;

  List<ResultWrapper> results = [];
  Set<ResultWrapper> selected = {};

  [@override](/user/override)
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _startTests();
    });
  }

  void _startTests() async {
    try {
      final tests = [
        buildWrapper("Abnormal Environment", process: () {
          return _plugin.abnormalEnvironment();
        }),
        buildWrapper("Libc File Detection", process: () {
          return _plugin.fileDetection();
        }),
        buildWrapper("Syscall File Detection", process: () {
          return _plugin.fileDetection(useSysCall: true);
        }),
        buildWrapper("Xposed Framework", process: () {
          return _plugin.xposedFramework();
        }),
        buildWrapper("Xposed Modules", process: () {
          return _plugin.xposedModules();
        }),
        buildWrapper("LS Patch Xposed Modules", process: () {
          return _plugin.xposedModules(lspatch: true);
        }),
        buildWrapper("Magisk App", process: () {
          return _plugin.magiskApp();
        }),
        buildWrapper("PM Command", process: () {
          return _plugin.pmCommand();
        }),
        buildWrapper("PM Conventional APIs", process: () {
          return _plugin.pmConventionalAPIs();
        }),
        buildWrapper("PM Sundry APIs", process: () {
          return _plugin.pmSundryAPIs();
        }),
        buildWrapper("PM QueryIntentActivities", process: () {
          return _plugin.pmQueryIntentActivities();
        }),
        buildWrapper("Settings Props", process: () {
          return _plugin.settingsProps();
        }),
        buildWrapper("Running Emulator", process: () {
          return _plugin.emulatorCheck();
        }),
        buildWrapper("RootBear Checks", process: () {
          return _plugin.checkRootBeer();
        }),
      ];
      results = await Future.wait(tests);
    } catch (e, t) {
      log("ERROR Init", error: e, stackTrace: t);
    } finally {
      if (mounted) {
        setState(() {
          isLoading = false;
        });
      }
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Applist Detector Flutter'),
        elevation: 0,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() => isLoading = true);
          _startTests();
        },
        child: const Icon(Icons.refresh),
      ),
      body: SafeArea(
        child: Builder(
          builder: (context) {
            if (isLoading) {
              return const SizedBox(
                width: double.infinity,
                height: 50,
                child: Center(
                  child: CircularProgressIndicator(),
                ),
              );
            }
            return ListView(
              children: [
                Wrap(
                  runSpacing: 10,
                  spacing: 5,
                  children: DetectorResultType.values.map((type) {
                    return Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        const SizedBox(width: 10),
                        icons[type] ?? const SizedBox.shrink(),
                        const SizedBox(width: 5),
                        Text(labels[type] ?? "-"),
                      ],
                    );
                  }).toList(),
                ),
                const SizedBox(height: 10),
                if (results.isEmpty) ...[
                  const SizedBox.square(
                    dimension: 50,
                    child: Center(
                      child: CircularProgressIndicator(),
                    ),
                  )
                ],
                ExpansionPanelList(
                  dividerColor: Colors.transparent,
                  expansionCallback: (index, isExpanded) {
                    final item = results[index];
                    if (isExpanded) {
                      selected.remove(item);
                    } else {
                      selected.add(item);
                    }
                    if (mounted) {
                      setState(() {});
                    }
                  },
                  children: results.map((e) {
                    final isExpanded = selected.contains(e);
                    return buildExpPanel(
                      e,
                      testName: e.testName,
                      isExpanded: isExpanded,
                    );
                  }).toList(),
                ),
                const SizedBox(height: 80)
              ],
            );
          },
        ),
      ),
    );
  }

  static const Map<DetectorResultType, Widget> icons = {
    DetectorResultType.notFound: Icon(Icons.done),
    DetectorResultType.found: Icon(Icons.coronavirus, color: Colors.red),
    DetectorResultType.suspicious: Icon(Icons.visibility),
    DetectorResultType.methodUnavailable: Icon(Icons.code_off),
  };

  static const Map<DetectorResultType, String> labels = {
    DetectorResultType.notFound: "Not Found",
    DetectorResultType.found: "Found",
    DetectorResultType.suspicious: "Suspicious",
    DetectorResultType.methodUnavailable: "Method Unavailable",
  };

  ExpansionPanel buildExpPanel(
    ResultWrapper wrapper, {
    required String testName,
    bool isExpanded = false,
  }) {
    final details = wrapper.result.details;
    final type = wrapper.result.type;
    final error = wrapper.error;
    return ExpansionPanel(
      isExpanded: isExpanded,
      headerBuilder: (context, isExpanded) {
        return ListTile(
          leading: error != null
              ? const Icon(Icons.error, color: Colors.red)
              : icons[type],
          title: Text(testName),
          trailing: Text(error != null ? "ERROR" : ""),
          subtitle: Text(labels[type] ?? "Unknown"),
        );
      },
      body: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: 10,
        ).add(const EdgeInsets.only(bottom: 15)),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: details.entries.map((e) {
                return Row(
                  children: [
                    icons[e.value]!,
                    const SizedBox(width: 10),
                    Expanded(child: Text(e.key)),
                  ],
                );
              }).toList(),
            ),
            if (error != null) ...[
              const SizedBox(height: 10),
              Text(error.toString()),
            ],
          ],
        ),
      ),
    );
  }
}

更多关于Flutter应用列表检测插件applist_detector_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用列表检测插件applist_detector_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


applist_detector_flutter 是一个用于检测设备上已安装应用程序列表的 Flutter 插件。它可以帮助开发者获取设备上安装的应用程序信息,并根据需要进行处理。以下是如何使用 applist_detector_flutter 插件的基本步骤:

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 applist_detector_flutter 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  applist_detector_flutter: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入插件:

import 'package:applist_detector_flutter/applist_detector_flutter.dart';

3. 获取已安装应用程序列表

使用 AppListDetectorFlutter 类来获取设备上已安装的应用程序列表。以下是一个简单的示例:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('AppList Detector Example'),
        ),
        body: Center(
          child: FutureBuilder<List<AppInfo>>(
            future: AppListDetectorFlutter.getInstalledApps(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              } else if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
                return Text('No apps found');
              } else {
                List<AppInfo> apps = snapshot.data!;
                return ListView.builder(
                  itemCount: apps.length,
                  itemBuilder: (context, index) {
                    AppInfo app = apps[index];
                    return ListTile(
                      title: Text(app.appName),
                      subtitle: Text(app.packageName),
                      leading: Icon(Icons.apps),
                    );
                  },
                );
              }
            },
          ),
        ),
      ),
    );
  }
}

4. 处理权限

在某些设备上,获取已安装应用程序列表可能需要特定的权限。请确保在 Android 的 AndroidManifest.xml 文件中添加以下权限:

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
回到顶部