NOIR

VerlintasMIT活跃维护

用 adb 扫描 Android 应用的权限、上报端点和数据流向,生成隐私审计报告,并给出可回滚的处置方案。

手机隐私审计:用 adb 扫出 Android 应用的权限、上报端点与数据流向,并给出可回滚的处置。Desktop Android leak audit: permissions, endpoints, data flows, reversible fixes.

v0.4.2发布于 2026-11-07 14:20 UTC3,226star +324 / 7 天295fork同步于 2026-11-10 17:43 UTC

怎么上手

由 README 提炼,执行前请确认
brew install --cask android-platform-tools jadx
noir
硬件要求按 README 说明

README 未说明显存或 GPU 要求;工具运行在 macOS(Intel/Apple Silicon)、Windows 10/11、Debian/Ubuntu 桌面端,需 JDK 17+、Android platform-tools(adb),deep 命令另需 jadx。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

用 adb 审计 Android 应用的权限、上报端点与数据流向,并给出可回滚的处置

用 adb 扫描 Android 应用的权限、上报端点和数据流向,生成隐私审计报告,并给出可回滚的处置方案。

核心能力

  • 在设备端用 unzip+strings 从 APK dex 抽取 URL,只回传几 KB
  • 按包名和域名识别厂商与类别,结合权限和端点计算风险分
  • 把权限翻译成可获取的数据类型,再与上报域名配对成数据流向
  • 解析二进制 AXML,找出导出组件、明文流量、备份、debuggable
  • 为每条处置动作生成回滚命令,默认只读、不卸载

容易踩的坑

portable 包不含 adb 和 jadx,首次运行会询问是否自动下载到 ~/.noir/tools;deep 命令需要单独安装 jadx;DNS 拦截只导出清单不执行,domains-functional.txt 拦了会掉功能。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.4.2
  1. v0.4.2NOIR 0.4.2 — security & safety release最新正式版2026-11-07 · 2026-11-07 14:20 UTC

    NOIR v0.4.2 — security & safety release

    Everyone running 0.4.1 or earlier should update.

    This release fixes issues that could cause unexpected AppOps changes, unintended uninstalls, lost rollback records, and false-negative scans. If you use --apply, noir block, or noir deepscan --purge, update before your next run.

    Critical fixes

    • --apply=false, --yes=false, and --purge=false are now treated as false. Previously they were treated as enabled, which could change device state or skip confirmation when you explicitly asked not to.
    • rollback.txt is now written only after a successful apply, includes the device serial, and is no longer erased by a later scan or dry run. This is the safety net for AppOps changes.
    • noir block no longer emits the obsolete PROJECT_MEDIA no-op or runs AppOps after uninstalling a package. It performs a per-user uninstall and writes a concrete block-rollback.txt.
    • noir deepscan --purge now uses the current Android user, writes purge-rollback.txt, and states clearly that reinstalling restores the APK but not app data.
    • Failed AppOps commands and non-interactive --apply without --yes now exit nonzero instead of silently claiming success.
    • User-supplied package names are validated, and adb/jadx commands have real timeouts.
    • Tool downloads reject non-HTTPS redirects and zip-slip paths.

    Scan accuracy

    • Split APKs and classes16.dex+ are scanned.
    • Failed pulls/parses are no longer cached as “no endpoints”; the cache is scoped to the device/build.
    • DeepScan no longer reuses a stale APK or stale decompiled sources.
    • Runtime.getRuntime().exec is detected again.
    • Upload detection now covers /stats, /logs, /tracking, /analytics, /metrics, and /crash.
    • Coarse location and legacy storage permissions are included.
    • Domain classification no longer treats static, biometrics, or soundtrack as trackers.
    • Manifest/AXML/Dumpsys parsing handles application permissions, provider read/write permissions, enabled=false, default allowBackup, malformed AXML, legacy userId=, and shared UIDs.

    Reports and CLI

    • Reports add stable leaksByType keys; HTML/Markdown escaping and upload-host counting are fixed.
    • noir diff rejects empty/malformed reports and records scan filters.
    • Global flags work before commands; noir scan --help no longer runs a scan.
    • --ascii, 40/50-column layouts, CJK table alignment, and Chinese TUI labels are fixed.

    Packaging

    • Intel (x86_64) and Apple Silicon (arm64) macOS builds are both published.
    • Tagged releases run the test suite before packaging.
    • Portable archives include the MIT LICENSE and SHA256SUMS.txt.

    Upgrade notes

    1. Download the asset for your platform and replace the old portable directory.
    2. Keep --apply / block / purge review habits: this release makes destructive intent explicit, but it still changes device state only when you ask.
    3. The endpoint cache moved to endpoints-v3.tsv; the first scan after upgrading will rebuild it.
    4. Verify SHA256SUMS.txt before running any downloaded build.

    Full changelog: https://github.com/Verlintas/NOIR/blob/main/CHANGELOG.md Source: https://github.com/Verlintas/NOIR

    If you are unsure whether to update: yes, update. The previous version could act on --flag=false and could lose the rollback record.

  2. v0.4.1NOIR 0.4.12026-11-06 · 2026-11-06 12:40 UTC
    查看更新说明

    NOIR v0.4.1 — English interface + smarter AppOps.

    Added

    • Automatic English interface — NOIR follows the Android device locale, then the host locale, and renders the CLI, dashboard, guidance and reports in English for non-Chinese devices.
    • --lang auto|zh|en and the NOIR_LANG environment variable can pin the language.
    • Reports now include stable categoryKey / actionKey / dataTypeKeys fields, so a Chinese report can still be diffed against an English one without false category changes.

    Fixed

    • Removed the misleading PROJECT_MEDIA ignore recommendation. Declaring screen-capture capability is not an action; that app-op only controls a persistent grant.
    • AppOp plans now query the device's current effective mode and omit actions that would be no-ops, so plan.txt and --apply only contain real changes.

    Portable builds for macOS, Windows and Linux. Bundled runtime, no JDK, no account, no telemetry. MIT.

    Full changelog: https://github.com/Verlintas/NOIR/blob/main/CHANGELOG.md Source: https://github.com/Verlintas/NOIR

  3. v0.4.02026-11-06 · 2026-11-06 06:32 UTC
    查看更新说明
  4. v0.3.02026-11-06 · 2026-11-06 06:22 UTC
    查看更新说明
  5. v0.2.72026-11-06 · 2026-11-06 05:21 UTC
    查看更新说明

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译
      ███╗   ██╗ ██████╗ ██╗██████╗
      ████╗  ██║██╔═══██╗██║██╔══██╗
      ██╔██╗ ██║██║   ██║██║██████╔╝
      ██║╚██╗██║██║   ██║██║██╔══██╗
      ██║ ╚████║╚██████╔╝██║██║  ██║
      ╚═╝  ╚═══╝ ╚═════╝ ╚═╝╚═╝  ╚═╝
    

    NOIR

    build release license platforms

    AtomGit G-Star

    把「这台手机到底能泄露什么」变成一份可复现的报告。

    NOIR 是一个跑在电脑上的审计工具,通过 adb 读取已连接 Android 设备的应用清单、权限和 APK 里的网络端点,给出分类、风险评分和可执行的处置建议。它也可以在需要时调用 jadx 对单个应用做反编译和关键字检索。

    定位:审计与自我防护。面向自己的设备、自己的应用、已授权的安全研究。

    官网 / Website: https://verlintas.dev/noir/ · 中文

    AtomGit G-Star 项目 / Mirror: https://atomgit.com/Verlintas/NOIR


    它做什么

    1. 盘点:列出所有「有网络权限 + 敏感权限」的应用,以及它们各自拿到了什么。
    2. 抽取端点:在设备端用 unzip + strings 从每个 APK 的 dex 里提取 URL,只回传几 KB,不把整包拉回电脑。
    3. 分类与打分:按包名和域名识别厂商(Xiaomi / Google / 腾讯 / 高德 …)与类别(遥测、广告、定位、输入法 …),结合权限和上报端点计算风险分。
    4. 数据关联:把权限翻译成"能拿到什么数据"(位置/通讯录/短信/通话/麦克风/相机/屏幕/应用列表/设备标识/文件/日历/账号),再和上报域名配对,得出"哪类数据可能流向哪里"。
    5. 共享 UID:识别 android.uid.system 这类共享用户,列出哪些包实际上共享同一套权限并集。
    6. 清单层:解析 AndroidManifest.xml 二进制 AXML,找出没有权限保护的导出组件、明文流量、备份、debuggable、targetSdk。
    7. 给建议:区分「可安全自动执行」「需人工确认」「不建议动」,并为每条动作生成回滚命令。
    8. 必要时深挖:deep 会把一个应用的基础 APK 和 split APK 拉到本地,用 jadx 反编译后检索 Runtime.getRuntime().exec、setApplicationEnabledSetting、DexClassLoader、MediaProjection 等高风险调用。

    它不做什么

    • 不联网、不上传任何数据、不需要账号。
    • 不修改系统分区,不需要 root。
    • 默认不会卸载任何东西;只有 noir deepscan --purge 会逐个确认卸载高风险用户应用。

    第一次运行

    noir
    

    不带参数会进入向导:

    1. 检查 adb,没有就问你要不要自动下载(~/.noir/tools)
    2. 检查设备,没有就打印开发者模式 / USB 调试的开通步骤,然后等你插线(最多 180 秒)
    3. 问一句「开始扫描?」,扫完直接出仪表盘
    4. 问一句「执行安全处置?」,y 就执行,并写好回滚文件

    全程只会问两三个 y/n,其余都是自动的。

    环境自检

    noir doctor
    
    NOIR doctor
      platform  Mac OS X aarch64
      java      17.0.19
      adb       /opt/homebrew/.../platform-tools/adb
                Version 37.0.1-15733141
      device    178b0d2f  device  2509FPN0BC
      jadx      /opt/homebrew/bin/jadx
    
    noir setup          # 缺什么下什么
    noir setup --yes    # 不询问,适合脚本
    

    出现问题时

    所有错误都会带「怎么办」,而不是抛异常栈:

    ╭─ ERROR ──────────────────────────────────────────────────────────╮
    │ 指定的 adb 不存在:/nonexistent/adb                              │
    ├──────────────────────────────────────────────────────────────────┤
    │ 检查路径,或运行 noir setup 自动安装。                           │
    ╰──────────────────────────────────────────────────────────────────╯
    

    没有设备时给出的是可执行步骤:

    ╭─ 没有检测到设备 ──────────────────────────────────────────────╮
    │  1. 打开开发者模式                                           │
    │     小米 / HyperOS:设置 → 我的设备 → 全部参数 → 连点「MIUI 版本」7 次
    │  2. 开启 USB 调试:设置 → 系统 → 开发者选项 → USB 调试        │
    │  3. 插线后手机弹「允许 USB 调试吗?」→ 勾选「一律允许」        │
    │  4. 还不行就换一根数据线(很多线只能充电)                    │
    ╰──────────────────────────────────────────────────────────────╯
    

    已连接但没授权时,会单独提示「撤销 USB 调试授权后重插」。

    支持平台

    系统状态
    macOS (Intel / Apple Silicon)✅
    Windows 10 / 11✅
    Debian / Ubuntu✅

    依赖:

    • JDK 17+
    • Android platform-tools(adb)
    • jadx(仅 deep 命令需要)

    程序会自动在常见安装位置查找 adb 和 jadx;找不到时可以用 --adb / --jadx 指定。

    # macOS
    brew install --cask android-platform-tools jadx
    
    # Debian / Ubuntu
    sudo apt install adb
    # jadx: https://github.com/skylot/jadx/releases
    
    # Windows (scoop)
    scoop install adb jadx
    

    安装

    方式一:下载即用(推荐)

    到 Releases 下载对应平台的 portable 包:

    noir-vX.Y.Z-macOS-arm64-portable.zip
    noir-vX.Y.Z-macOS-x86_64-portable.zip
    noir-vX.Y.Z-Windows-portable.zip
    noir-vX.Y.Z-Linux-portable.zip
    SHA256SUMS.txt
    

    解压后双击启动器即可,包内自带运行时,不需要安装 Java:

    系统双击这个如果被拦
    macOSStart NOIR.command右键 → 打开;或 xattr -dr com.apple.quarantine "Start NOIR.command" NOIR.app
    WindowsStart NOIR.batSmartScreen → 更多信息 → 仍要运行(批处理会切到 UTF-8 并调用包内 JRE)
    LinuxStart-NOIR.sh先 chmod +x Start-NOIR.sh,或在终端执行

    启动器会打开一个终端窗口跑完向导,并在结束时停住(不会一闪而过)。

    adb 和 jadx 不在包里——首次运行会询问是否自动下载到 ~/.noir/tools。

    方式二:从源码构建

    git clone https://github.com/Verlintas/NOIR
    cd NOIR
    ./gradlew :cli:installDist
    ./cli/build/install/noir/bin/noir --about
    

    构建

    git clone <repo> && cd NOIR
    ./gradlew :cli:installDist
    

    产物:

    cli/build/install/noir/bin/noir        # macOS / Linux
    cli/build/install/noir/bin/noir.bat    # Windows
    

    也可以直接:

    ./gradlew :cli:run --args="devices"
    

    界面

    NOIR dashboard on a Xiaomi 17 Pro Max

    真机输出(macOS Terminal):渐变 logo、CJK 对齐的表格、按风险着色的分数、 每处理完一个 APK 就刷新一次的进度条。

    noir ui 会把结果渲染成一块等宽仪表盘;颜色和边框都会按终端能力自动降级:

    • --ascii:纯 ASCII 边框,给旧版 Windows 控制台
    • --no-color / --color:关闭或强制 ANSI 颜色(默认按是否为 TTY 自动判断)
    • --quiet:只留仪表盘,不打印扫描过程
    • --no-clear:不清屏(方便把输出重定向到文件)
    • --lang <auto|zh|en>:界面语言。默认按手机系统语言切换;没有设备时按电脑系统语言;NOIR_LANG 环境变量也可以指定

    用法

    noir --about              # 它是什么、会写什么、许可
    noir --version
    noir devices
    noir scan                 # 全量扫描,输出 JSON / Markdown / 域名清单
    noir diff old/report.json new/report.json   # 对比两次扫描
    noir ui                   # 扫描并渲染仪表盘
    noir auto                 # 扫描 + 分类 + 生成处置计划(dry-run)
    noir auto --apply         # 执行安全的 appops 动作(可回滚)
    noir deepscan --apply --purge    # 额外卸载高风险用户应用(逐个确认)
    noir deep com.example.app # 拉包 + jadx + 关键字检索
    noir block com.example.app        # 打印处置命令
    noir block com.example.app --apply
    

    常用参数:

    参数说明
    --lang <auto|zh|en>界面语言(默认跟随设备语言)
    --serial <id>指定设备
    --out <dir>输出目录(默认 noir-out)
    --min <score>只保留分数 ≥ N 的应用
    --limit <n>最多输出 N 条
    --only <regex>只扫描匹配的包名,例如 --only 'com\.miui\.'
    --adb <path> / --jadx <path>手动指定工具路径
    --yes自动化场景下跳过确认

    对比两次扫描

    noir diff 读取两份 report.json,比较应用、分数、权限和端点:

    noir diff noir-out-before noir-out-after
    noir diff old/report.json new/report.json --json
    noir diff old/report.json new/report.json --fail-on-regression
    

    输出会分成 added / removed / changed,并标出新增权限和新增端点。 --fail-on-regression 会在出现新应用、分数上升、新增权限或新增端点时返回退出码 1, 适合放进 CI 或定期审计脚本。

    DeepScan:一条命令反编译 + 处置

    noir deepscan                  # 反编译风险最高的 15 个应用
    noir deepscan --top 30         # 更多
    noir deepscan --all            # 全部被标记应用(慢,占磁盘)
    noir deepscan --jobs 4         # 并行 jadx 数量
    

    流程是:扫描 → 按风险排序 → 逐个 adb pull + jadx → 统计代码级信号 (Runtime.getRuntime().exec、DexClassLoader、setApplicationEnabledSetting、 enabled_accessibility_services、MediaProjection、SystemProperties.set、 短信/设备标识、WebView 桥、无障碍/通知监听/设备管理员 …)→ 解析清单 (导出组件、明文流量、备份、debuggable)→ 识别 SDK(Umeng/Firebase/AppsFlyer…) → 输出 deepscan.md / deepscan.tsv → 询问是否清理。

    noir deepscan --apply          # 分析后执行安全 appops
    noir deepscan --apply --purge  # 再逐个确认卸载高风险用户应用
    

    反编译结果按 包名 + APK 路径 缓存,第二次跑同一个应用会直接复用。

    输出

    noir-out/
    ├── report.json               # 结构化结果(应用、权限、端点、建议)
    ├── report.md                 # 人类可读报告
    ├── report.html               # 离线单文件报告,可直接用浏览器打开
    ├── domains-trackers.txt      # 统计/广告/崩溃上报,可整份导入
    ├── domains-other.txt         # 用途不明,导入前逐条判断
    ├── domains-functional.txt    # 推送/登录/更新/支付/商店/云同步,禁止拦截
    ├── domains.txt               # 等于 trackers(兼容旧脚本)
    ├── plan.txt                  # 本次可执行的 appops
    ├── applied.txt               # 实际执行的命令、退出码、完整 stdout/stderr
    └── rollback.txt              # 回滚命令(成功后写入修改前的 AppOps 模式)
    

    隐私

    • 工具本身不联网:没有遥测、没有版本检查、没有崩溃上报
    • 扫描结果只写在你指定的 --out 目录
    • 唯一的外部请求发生在 noir setup(下载 adb/jadx)和 noir deep(jadx 是本地进程)
    • 报告里可能包含你设备上的包名和端点,分享前自行检查

    缓存

    扫描结果按 设备/构建指纹 + 包名 + APK 路径 缓存在 ~/.noir/endpoints-v3.tsv。应用更新后路径变化会自动重新分析,失败/半截扫描不会写入缓存。


    架构

    adb ──▶ pm / dumpsys ──▶ Dumpsys parser ──┐
                                              ├─▶ cache (pkg + apk path)
    adb ──▶ unzip/strings ──▶ endpoints ──────┘        │
                                                       ▼
                                              Classifier ─▶ score ─▶ Advisor
                                                       │              │
                                                       ▼              ▼
                                                  report.json    plan.txt
                                                  report.md      rollback.txt
                                                       │
                                                       ▼
                                                     Tui / CLI
    

    deep 走另一条支线:adb pull → jadx → 源码 grep。

    设计取舍

    • 端点抽取在设备端完成:adb shell 内跑 unzip | strings | grep,避免把几百个 APK 拉回电脑。设备缺少 unzip/strings 时自动退化为本地解析。
    • 共享 UID 特殊处理:Android 上 android.uid.system 下的应用(常见 50+ 个)权限记录在 dumpsys package 尾部的 Shared users 段。解析器会把这些权限合并回每个包,否则最该被看见的应用反而会消失。
    • 建议分级:只有 appops 级别的动作标记为可自动执行;卸载必须显式开启。
    • 无遥测:程序不包含任何上报逻辑。

    常见问题

    需要 root 吗? 不需要。全部通过 adb 的 shell 权限完成;卸载只是 --user 0 级别,APK 仍在系统分区。

    会改坏手机吗? 默认完全只读。--apply 只改 app-ops;执行前会查询原模式,成功执行的动作会写入 rollback.txt,按记录恢复。完整 stdout/stderr 和退出码写入 applied.txt。 noir block 的卸载也会先打印 pm install-existing 的恢复命令。

    为什么有些应用只给"人工复核"? 系统应用不能真正卸载(--user 0 卸载也会被 OTA 或恢复出厂装回来),所以只建议 app-ops 或 DNS 层拦截。

    DNS 拦截为什么只导出不执行? 跨平台改 DNS 很容易把设备网断掉(我们在开发中踩过),所以只导出清单:

    • domains-trackers.txt —— 统计/广告/崩溃上报,可以整份导入
    • domains-other.txt —— 用途不明,导入前逐条判断
    • domains-functional.txt —— 推送、登录、更新、支付、应用商店、云同步,拦了会掉功能
    • domains.txt —— 现在只包含 trackers,兼容旧脚本

    IP、localhost 和带 test/staging 的域名会被自动剔除。

    支持 iOS 吗? 不支持。core 是按 Kotlin Multiplatform 组织的,但审计逻辑依赖 Android 的 dumpsys 和 APK 格式。

    参与

    • CONTRIBUTING.md — 构建、测试、规则放在哪
    • SECURITY.md — 漏洞报告方式(请不要开公开 issue)
    • Issues — bug 请附上 noir doctor 输出

    路线图

    • 等宽仪表盘(noir ui)
    • DeepScan(批量反编译 + 代码级信号)
    • 自带运行时的双击即用包(jpackage)
    • 图形界面(Compose Multiplatform)
    • 规则文件可配置(YAML),支持社区规则包
    • 与 apktool / jadx 的批量流水线
    • 设备端 DNS/VPN 拦截方案导出
    • 扫描结果版本对比(noir diff)
    • 扫描结果签名

    免责声明

    NOIR 只应用于你自己的设备,或你获得明确授权的设备。它给出的是静态证据 ("这个应用具备这个能力,并且代码里有这个端点"),不能证明某次具体传输发生过。 请结合网络层证据自行判断。

    许可

    MIT © 2026 Verlintas