NoobDigital/react-native-shieldscan
GitHub: NoobDigital/react-native-shieldscan
为 React Native 应用提供一站式运行时安全检测与屏幕安全功能的原生模块,覆盖越狱/Root、Frida、调试器、模拟器及 Hook 框架检测,并支持防截屏与后台模糊。
Stars: 5 | Forks: 0
# @noobdigital/react-native-shieldscan
[](https://www.npmjs.com/package/@noobdigital/react-native-shieldscan)
[](https://www.npmjs.com/package/@noobdigital/react-native-shieldscan)
[](LICENSE)
[](https://www.npmjs.com/package/@noobdigital/react-native-shieldscan)
[](https://reactnative.dev/docs/the-new-architecture/landing-page)
为 React Native 应用提供**运行时安全检测**与**屏幕安全**功能。它可以在单个原生模块中检测越狱、root、Frida 注入、调试器附加、模拟器环境、运行时 hook 框架以及开发者模式——此外还提供后台模糊、防截屏/录屏以及屏幕录制检测功能。
支持**旧架构**(Bridge)和**新架构**(Turbo Modules / JSI)。支持 React Native 0.70+ 版本。
## 功能
### 运行时安全检测
| 检测项 | iOS | Android |
|---|---|---|
| 越狱 / Root | ✅ 文件路径 + 沙盒写入测试 + 符号链接检查 | ✅ RootBeer `0.1.2` |
| 基于文件的 root | ✅ Cydia, MobileSubstrate, bash, sshd | ✅ Magisk, SuperSU, Xposed, Zygisk 路径 |
| Frida 检测 | ✅ dylib 注入 + 27042 端口 + 环境变量 | ✅ 文件路径 + 27042 端口 + `/proc/self/maps` |
| 调试器附加 | ✅ 通过 `sysctl` 获取 `kinfo_proc` / `P_TRACED` | ✅ `Debug.isDebuggerConnected()` + `waitingForDebugger()` + `TracerPid` |
| 模拟器 / 仿真器 | ✅ `targetEnvironment(simulator)` | ✅ 构建指纹 + 传感器数量启发式检测(涵盖 Bluestacks, Nox, LDPlayer, Genymotion, MEmu) |
| Hook 框架 | ✅ dyld 镜像扫描(Substrate, Substitute, LibHooker) | ✅ 包扫描 + 堆栈跟踪探测 + `/proc/self/maps`(Xposed, LSPosed, Frida gadget, SandHook) |
| 开者模式 | ✅ 始终为 `false`(无公开的 iOS API) | ✅ `Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED` |
### 屏幕安全(v1.1.0+)
| 功能 | iOS | Android |
|---|---|---|
| 后台模糊 | ✅ 在 `willResignActive` 时显示遮罩,在 `didBecomeActive` 时移除 | ✅ 在失去窗口焦点时(应用切换器 / Home 键)显示遮罩,重新获得焦点时移除 |
| 防截屏 / 防录屏 | ✅ Secure `UITextField` 图层技巧——截图中为空白,设备上正常可见 | ✅ `WindowManager.LayoutParams.FLAG_SECURE`——在截图**和**最近任务卡片中均为空白 |
| 录屏检测 | ✅ `UIScreen.main.isCaptured`,适用于任何 iOS 版本 | ⚠️ 仅限 Android 15 (API 35)+,通过 `WindowManager.addScreenRecordingCallback` 实现。在较旧的 OS 版本上返回 `false`——因为在 15 之前没有公开 API |
## 截图
在 Android 模拟器和 iOS Simulator 上运行的示例应用。`Running on Emulator: TRUE` 证实了双平台上的模拟器检测均工作正常。
`
在单次调用中以原生方式运行所有安全检查。返回一个解析为 `SecurityScanResult` 对象的 Promise。所有检查均在原生端并行运行。
### `isDeviceCompromised(): Promise`
便捷封装。如果风险评分 ≥ 30,则返回 `true`——即 `rooted`、`fileBasedRoot`、`fridaDetected`、`debugger` 或 `hooksDetected` 中任何一个为 `true`。
### `getDeviceRiskAssessment(): Promise`
企业级加权风险评估。返回一个 `CompromisedResult` 对象,包含威胁等级、评分、活跃信号以及建议的操作。
信号权重:
| 信号 | 权重 | 理由 |
|---|---|---|
| `fridaDetected` | 40 分 | 活跃的运行时注入 |
| `hooksDetected` | 40 分 | 活跃的运行时注入 |
| `rooted` | 30 分 | 操作系统完整性破坏 |
| `fileBasedRoot` | 20 分 | 存在痕迹,但未确认处于活跃状态 |
| `debugger` | 10 分 | 在生产环境中非常可疑 |
| `developerMode` | 5 分 | 扩大了攻击面 |
| `emulator` | 0 分 | 仅供参考 |
### `setBlurEnabled(enabled: boolean): Promise`
启用或禁用后台模糊遮罩。返回传入的布尔值。请参阅上方的[用法示例](#screen-security--background-blur-v110)。
### `setScreenshotPreventionEnabled(enabled: boolean): Promise`
为当前屏幕启用或禁用防截屏/录屏拦截。返回传入的布尔值。请参阅上方的[用法示例](#screen-security--screenshot--recording-prevention-v110)。
### `isScreenBeingRecorded(): Promise<{ isRecording: boolean }>`
返回在调用瞬间,屏幕是否正在被录制/投射会话捕获。请参阅上方的[用法示例](#screen-security--detecting-an-active-screen-recording-v110)。
### `SecurityScanResult`
```
interface SecurityScanResult {
/**
* True if RootBeer (Android) or jailbreak file paths (iOS) detect
* a compromised OS environment. Primary root/jailbreak signal.
*/
rooted: boolean;
/**
* True if known root, jailbreak, or Frida file paths exist on disk.
* Android: /sbin/su, /magisk, XposedBridge.jar, Zygisk modules
* iOS: /Applications/Cydia.app, /bin/bash, /usr/sbin/sshd
*/
fileBasedRoot: boolean;
/**
* True if Frida instrumentation framework is detected.
* Checks: known file paths + TCP port 27042 + environment variables
* + dylib injection (iOS) + /proc/self/maps scan (Android).
*/
fridaDetected: boolean;
/**
* True if a debugger is currently attached to the process.
* iOS: sysctl kinfo_proc P_TRACED flag.
* Android: Debug.isDebuggerConnected() + waitingForDebugger() + TracerPid.
*/
debugger: boolean;
/**
* True if running on an Android emulator or iOS Simulator.
* iOS: compile-time targetEnvironment(simulator).
* Android: Build fingerprint heuristics + sensor count (< 5 sensors).
* Covers: AOSP, Genymotion, Bluestacks, Nox, LDPlayer, MEmu, Andy, Droid4X.
*/
emulator: boolean;
/**
* True if a runtime hooking framework is detected.
* iOS: dyld image scan for Substrate, Substitute, LibHooker, TweakInject.
* Android: package scan (Xposed/LSPosed managers) + stack trace probe
* + /proc/self/maps scan for XposedBridge, frida-gadget, SandHook.
*/
hooksDetected: boolean;
/**
* True if developer options/mode is enabled on the device.
* Android: Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED.
* iOS: Always false — no public API exposes developer mode on iOS.
*/
developerMode: boolean;
}
```
### `CompromisedResult`
```
interface CompromisedResult {
/** True if risk score >= 30 */
compromised: boolean;
/** CLEAN | LOW | MEDIUM | HIGH | CRITICAL */
threatLevel: ThreatLevel;
/** Weighted risk score 0–100 */
score: number;
/** Which signals fired */
signals: string[];
/** Recommended action for the consuming app */
recommendation: string;
}
```
## 示例应用
该仓库的 `example/SampleApp/` 目录下包含一个可运行的示例应用。
它展示了全部七项安全检测,并提供实时的结果界面,包括风险评分卡、威胁等级指示器以及各项检测的严重性徽章——此外还有一个屏幕安全面板,可用于实时切换后台模糊和防截屏功能,以及屏幕录制状态指示器。
```
example/
SampleApp/
src/
SampleAppScreen.tsx ← main demo screen
assets/
noobdigital-logo.png
```
### 运行示例
```
# Clone 该 repo
git clone https://github.com/NoobDigital/react-native-shieldscan.git
cd react-native-shieldscan
# 安装依赖
yarn install
# iOS
cd example/SampleApp && yarn install
cd ios && pod install && cd ..
yarn ios
# Android
cd example/SampleApp && yarn install
yarn android
```
## 架构
### 旧架构 (`newArchEnabled=false`)
模块通过标准的 React Native bridge,经由 `NativeModules.ShieldScan` 解析。
### 新架构 (`newArchEnabled=true`, React Native 0.71+)
模块通过 JSI 经由 `TurboModuleRegistry.get('ShieldScan')` 解析。`src/NativeShieldScanSpec.ts` 中的 TypeScript 规范驱动 codegen,生成类型安全的原生绑定,且没有桥接序列化的开销。
该包会在运行时检测当前处于哪种架构下,并自动选择合适的解析路径。
## 安全说明
**误报保证**
在 BrowserStack、LambdaTest、Firebase Test Lab、AWS Device Farm 真机,以及任何开启了 ADB、开启了开发者选项或安装了企业/MDM 证书的设备上,`hooksDetected` 都会返回 `false`。只有真正的 hook 框架特征才会触发此信号。
**生产环境中的 `developerMode`**
仅凭 `developerMode: true` 不会将设备标记为已受损——它只为风险评分贡献 5 分,远低于 30 分的阈值。这是一个信息信号。建议使用 `!__DEV__` 守卫来拦截硬阻断,以免阻塞您自己的开发工作流。
**模拟器 / 仿真器**
`emulator: true` 永远不会计入风险评分。它被排除在 `isDeviceCompromised()` 之外。许多团队在模拟器上进行 QA 测试——除非您明确要求拦截,否则此信号仅供参考。
**开发环境下的调试器标志**
在进行 Xcode 和 Android Studio 调试时,出现 `debugger: true` 是正常的。请使用 `!__DEV__` 进行硬阻断守卫。
**Frida 端口检测延迟**
向 `127.0.0.1:27042` 发起的 TCP socket 探测在干净的设备上会增加大约 50–300ms 的耗时(在显式超时后被拒绝连接)。对于一次性的启动检测来说,这是可以接受的。避免在渲染循环或高频执行的热路径中调用 `runSecurityChecks()`。
**RootBeer 版本**
Android 的 root 检测使用 RootBeer `0.1.2`,该版本包含了符合 Android 15+ / Google Play 要求的 16 KB ELF 页面大小对齐(自 2025 年 11 月起强制要求)。
**iOS 上的模拟器守卫**
越狱和 hook 检测在 iOS Simulator 上通过 `#if targetEnvironment(simulator)` 在编译时被禁用。这可以防止由于 macOS 文件系统路径(例如 `/bin/bash`)导致的误报,这些路径存在于模拟器宿主机上,但并不是越狱标志。
**Android:防截屏功能会导致最近任务中的后台模糊变白**
`FLAG_SECURE` 在 OS 合成器级别运行——它指示 Android 绝对不要将窗口内容渲染到*任何*快照(最近任务卡片、截图、屏幕录制、投射)中,无论视图层级中包含什么视图。如果 `setBlurEnabled(true)` 和 `setScreenshotPreventionEnabled(true)` 同时处于激活状态,最近任务卡片将显示为空白/白色卡片,而不是您的模糊消息——在任何快照使用者看到它之前,OS 就已经丢弃了整个帧。这是预期的、设计好的 Android 行为,而不是错误,并且在应用级别没有任何解决方法。如果您的消息和硬性内容拦截都很重要,请考虑对 UI 进行控制,让用户明白在 Android 上同一时间只能有一种视觉结果;iOS 没有类似的冲突,因为它的两项功能使用的是相互独立的机制。
**Android:屏幕录制检测需要 API 35+**
`isScreenBeingRecorded()` 采用了 Android 15 (API 35) 引入的 `WindowManager.addScreenRecordingCallback`,并且需要 `DETECT_SCREEN_RECORDING` manifest 权限(由本库自动声明)。在低于 API 35 的设备上,它会返回 `false`——因为在早期的 Android 版本上没有公开、可靠的屏幕录制检测 API。它也只能检测基于 `MediaProjection` 的录制工具(Android 内置的录制器和大多数第三方应用);像 `scrcpy` 或底层 `screenrecord` 二进制文件这样的工具,并不会被这个 Android API 识别为录制会话。
**Android:manifest 权限是库级别的声明**
`DETECT_SCREEN_RECORDING` 是一个普通的安装时权限——它不会触发 Google Play 的敏感权限声明表单、延长审核,也不会出现运行时用户提示。它通过 Gradle 的 manifest 合并器自动合并到使用的应用中;您的应用 manifest 或 Play Console 详情页无需进行任何操作。
## VAPT 合规性
基于 OWASP Mobile Top 10 进行开发与验证:
| VAPT 检测结果 | OWASP 参考 | ShieldScan 信号 |
|---|---|---|
| 应用未检测已越狱/root 设备 | M8, M9 | `rooted`, `fileBasedRoot` |
| Frida 可在运行时附加并注入应用 | M10 | `fridaDetected`, `hooksDetected` |
| 无调试器检测机制 | M8 | `debugger` |
未检测到 hook 框架(Xposed, Substrate) | M10 | `hooksDetected` |
| 应用在模拟器上无限制运行 | M8 | `emulator` |
| 未检测开发者选项 | M8 | `developerMode` |
| 应用切换器 / 最近任务中暴露了敏感内容 | M9 | `setBlurEnabled` |
| 敏感内容被截屏或录屏捕获 | M9 | `setScreenshotPreventionEnabled`, `isScreenBeingRecorded` |
## 贡献
欢迎提交 Pull requests。
提交前请执行:
```
yarn lint # must pass
yarn typecheck # must pass
yarn test # must pass
```
新的检测项必须包含:
- 同时适用于 iOS (Swift) 和 Android (Kotlin) 的原生实现
- `SecurityScanResult` TypeScript 接口中对应的字段
- `__tests__/` 中的单元测试
- 更新本 README 中的文档
## 许可证
MIT © [noobdigital](https://noobdigital.com)
Android (left) · iOS (right)
## 安装说明 ``` npm install @noobdigital/react-native-shieldscan # 或 yarn add @noobdigital/react-native-shieldscan ``` ### iOS ``` cd ios && pod install ``` 通过 React Native 0.60+ 的自动链接机制进行链接。无需手动操作。 ### Android 通过 React Native 0.60+ 的自动链接机制进行链接。无需手动操作。 对于较旧的配置,请在 `MainApplication.kt` 中手动注册: ``` import com.shieldscan.ShieldScanPackage // inside getPackages(): packages.add(ShieldScanPackage()) ``` **权限:**该库自身的 manifest 声明了 `android.permission.DETECT_SCREEN_RECORDING`(这是一个普通的安装时权限——没有运行时提示,也不在 Google Play 的敏感权限列表中)。Gradle 的 manifest 合并器会自动将其合并到您的应用中;您的 `AndroidManifest.xml` 无需任何操作。此权限仅在 Android 15+ 上启用 `isScreenBeingRecorded()`,对应用分发、审核或面向用户的提示没有任何影响。 ## 用法 ### 完整结果对象 ``` import { runSecurityChecks } from '@noobdigital/react-native-shieldscan'; const result = await runSecurityChecks(); console.log(result); // { // rooted: false, // fileBasedRoot: false, // fridaDetected: false, // debugger: false, // emulator: false, // hooksDetected: false, // developerMode: false, // } ``` ### 单一布尔值拦截 ``` import { isDeviceCompromised } from '@noobdigital/react-native-shieldscan'; const compromised = await isDeviceCompromised(); if (compromised) { Alert.alert('Security Error', 'This app cannot run on a compromised device.'); } ``` ### 企业版——风险评分引擎(v1.0.2+) ``` import { getDeviceRiskAssessment } from '@noobdigital/react-native-shieldscan'; const assessment = await getDeviceRiskAssessment(); console.log(assessment); // { // compromised: false, // threatLevel: 'CLEAN', // CLEAN | LOW | MEDIUM | HIGH | CRITICAL // score: 0, // 0–100 weighted risk score // signals: [], // which signals fired // recommendation: 'Device is clean. No action required.' // } ``` 根据威胁等级进行分层响应: ``` switch (assessment.threatLevel) { case 'CLEAN': // proceed normally break; case 'LOW': // log only — e.g. developer mode on, expected in dev/QA break; case 'MEDIUM': // restrict sensitive features (payments, PII) break; case 'HIGH': // block sensitive flows, require re-authentication break; case 'CRITICAL': // Frida/hooks detected — terminate session immediately await revokeSessionToken(); BackHandler.exitApp(); break; } ``` ### 推荐——启动时强制执行并收集遥测数据 ``` import { getDeviceRiskAssessment } from '@noobdigital/react-native-shieldscan'; async function enforceDeviceSecurity() { const assessment = await getDeviceRiskAssessment(); // Always log everything to your security backend analytics.track('device_security_assessment', { score: assessment.score, threatLevel: assessment.threatLevel, signals: assessment.signals, platform: Platform.OS, }); if (assessment.threatLevel === 'CRITICAL') { throw new Error('COMPROMISED_DEVICE'); } } ``` ### 屏幕安全——后台模糊(v1.1.0+) 当应用置于后台或打开应用切换器时,显示带有保护性消息的遮罩,从而在最近任务的缩略图中隐藏敏感内容。 ``` import { setBlurEnabled } from '@noobdigital/react-native-shieldscan'; // Enable on a sensitive screen await setBlurEnabled(true); // Disable when leaving that screen await setBlurEnabled(false); ``` ### 屏幕安全——防截屏与防录屏(v1.1.0+) 阻止当前屏幕的内容出现在屏幕截图和屏幕录制中。 ``` import { setScreenshotPreventionEnabled } from '@noobdigital/react-native-shieldscan'; // Enable on a payment / card details screen await setScreenshotPreventionEnabled(true); // Disable when leaving that screen await setScreenshotPreventionEnabled(false); ``` ### 屏幕安全——检测正在进行的屏幕录制(v1.1.0+) ``` import { isScreenBeingRecorded } from '@noobdigital/react-native-shieldscan'; const { isRecording } = await isScreenBeingRecorded(); if (isRecording) { // e.g. warn the user, or hide a sensitive value in JS as an extra layer } ``` ## API 参考 ### `runSecurityChecks(): Promise标签:CVE监控, React Native, 环境检测, 移动端安全, 自动化攻击, 越狱检测, 防截屏, 防调试