跳至正文
发布与分发安全 发布机构:西安守界御盾信息安全技术有限公司 18 views

Android APK 权限清单怎么做差异检测?用 apkanalyzer 比较原包与加固包|御盾

从阅读进入评估 内测人员已满,请耐心等待新一轮内测开放;当前不接受在线申请、邀请码登记或候补提交。
查看内测状态(名额已满)

核心判断:若要确认加固前后 APK 请求的权限是否不同,先用 Android 官方 apkanalyzer manifest permissions 分别读取两个 APK,再比较提取出的权限集合;不要只看源码 Manifest,也不要仅凭文本相同就推断 Play 合规或运行期行为一致。御盾提供的本地权限清单比较器只比较用户粘贴的命令输出,不接收 APK,也不替代真实产物核查。本轮没有提供或测试御盾 APK,产品候选状态为 NOT_TESTED。

摘要

用同一构建变体的两份 APK 权限输出做集合比较,再对差异回溯到 Manifest 合并或产物链;本文的在线工具只比较粘贴文本,不解析 APK。

读者对象与问题边界

本文面向需要检查 Android APK Manifest 权限的开发、测试、安全和发布团队。目标是回答一个窄问题:两份已提取的 APK 权限清单有哪些新增、移除或保持不变的项目,以及发现差异后如何找到它首次进入交付链的位置。它不提供 APK 二进制解析,不检查运行时是否实际调用联系人、定位、相机等数据,也不判断 Google Play 是否批准权限用途。

核心结论

  • Android 官方 apkanalyzer 可读取 APK Manifest 权限和 target SDK;两份输出可形成静态清单差异。
  • 源码 Manifest 不等于最终 APK Manifest,构建变体和库声明可能参与合并。
  • 差异集合只能说明输入清单的不同,不能自动确定权限来源、运行时行为或政策结果。
  • 本地比较器不接收 APK;御盾自有或客户产物均未测试,状态为 NOT_TESTED。

如果实际交付物是 AAB,应遵循团队的应用包验证流程,检查 Bundle 内容及面向目标设备生成的 APK 产物。此处给出的 apkanalyzer manifest permissions 命令以 APK 文件为输入;不能把某一份通用 APK 的结果外推到 AAB 生成的所有设备配置。权限静态列表有助于发布核对,但它只覆盖清单声明这一面。

快速流程:先固定两个被比较的对象

比较开始前,为原包和候选包分别记下版本、构建变体、产物类型、文件摘要与来源。应确保两者属于同一业务版本,或明确记录版本差异;若一个是 Debug、另一个是 Release,观察到的权限差异可能来自变体配置,而不是保护步骤。不同候选的产物身份若不清楚,就先停止比较,不能从文件名猜测它们的关系。

Android Developers 文档说明,apkanalyzer 可查看 APK Manifest,并提供 manifest permissions 和 manifest target-sdk 子命令。可以在受控的本地 Android SDK 环境中分别运行:

apkanalyzer manifest permissions /path/to/original.apk
apkanalyzer manifest permissions /path/to/candidate.apk
apkanalyzer manifest target-sdk /path/to/original.apk
apkanalyzer manifest target-sdk /path/to/candidate.apk

上面是工具用法示例,不表示御盾已对某个 APK 执行这些命令。请将路径替换为你有权检查的文件;不要把私有 APK 上传到不受控网站,也不要在公开报告中粘贴包名、证书、签名信息或客户产物的未脱敏标识。两份命令输出应分别保存并与被检查文件关联,之后再进入差异比较。

技术拆解:本地权限比较器能做什么

比较器面向 apkanalyzer manifest permissions 的文本输出。将原始 APK 输出贴入左侧,候选 APK 输出贴入右侧,页面会在浏览器当前会话内提取权限名称,分别列出候选新增、候选移除和两边共同存在的权限。结果可导出为 JSON,便于手动附在发布审查记录中。页面不上传两个文本框的内容,不调用服务端 API,也不读取或保存 APK 文件。

该工具刻意不尝试在浏览器里重新实现 Android 二进制 XML 解码,也不把 AAB 当成 APK。若输入为空、命令输出格式无法解析或至少一侧没有识别出权限名称,页面会提示无法比较,而不会输出“无差异”。用户应检查命令是否成功、文件路径是否正确、输出是否完整,然后重新读取。对不属于标准 Android 权限命名空间的自定义权限,或工具版本输出格式不同的行,也应人工复核解析结果。

工具返回的 JSON 记录包括输入中识别出的权限列表、差异集合、比较时间以及“仅比较粘贴文本”的边界。它不包含 APK 文件摘要,也不能证明文本确实来自所声明的文件。发布负责人应在自己的构建系统中另行记录 SHA-256、构建变体和候选身份,避免导出的列表脱离产物上下文。

Manifest Merge 为什么会改变最终权限

Android 项目可能同时包含主 Manifest、Product Flavor、Build Type、具体构建变体以及导入库的 Manifest。构建时,Manifest Merger 会按优先级合并这些声明,并把结果放入 APK 或 Android App Bundle。某个权限没有写在主 src/main/AndroidManifest.xml 中,并不能证明它不会出现在打包清单里;依赖库或某个专用变体可能引入它。

排查时应使用 Android Studio 的 Merged Manifest 视图或 Manifest Merger 报告,确认每一项声明来自哪个输入文件。主应用的 variant manifest、build type、flavor、主 Manifest 和库 Manifest 的优先级不同;实际结果还受到 tools:node 等 merge rule marker 和构建配置影响。不要看到某个权限与某个 SDK 同时出现就直接认定 SDK 是来源,必须查看合并报告或逐项构建差异。

变体比较也要保持一致。若 Original 来自 demoRelease,候选来自 fullDebug,即使它们对应同一个 Git commit,权限列表仍可能不同。要回答“加固是否改变权限”,最有说服力的比较是同一应用版本、相同构建变体、同一依赖锁定状态下,保护链前后的实际产物;如无法做到,应把差异归为“待定位”,而不是把责任归给某个环节。

从差异集合定位首次出现阶段

用五个阶段记录清单状态:源码 Manifest、合并后的 Manifest、原始 APK、受保护候选 APK、客户最终签名 APK。每一阶段都记录产物来源和检查方式。对相邻阶段进行比较,第一次出现权限新增或移除的位置,才是后续调查的起点;它不是未经复核的责任判定。

阶段 输入对象 主要问题 发现差异后的首要复核
Source 主 Manifest 与各源文件 开发者直接声明了什么 是否检查了正确模块和变体
Merged 目标 Variant 的合并结果 SDK、Flavor 或规则是否带入声明 Merged Manifest 与 merger report
Original APK 保护前打包产物 实际构建文件包含什么 文件摘要、target SDK、产物来源
Protected Candidate 保护工具输出 保护阶段前后列表是否不同 相同输入、参数、工具版本和产物身份
Final Signed APK 客户签名后的交付物 最终准备分发的文件是什么 签名、版本、渠道和前一候选是否匹配

如果权限在 Source 没有、Merged 中出现,应先检查依赖或变体。如果 Merged Manifest 没有、Original APK 中出现,应核查实际构建任务和 APK 来源。如果 Original 无该项、Protected Candidate 出现,才有理由把保护阶段列为调查范围;还要用同一输入重跑并排除配置变化。如果 Protected Candidate 没有、Final Signed APK 出现,优先调查后续打包或渠道处理。只有证据链完整之后,才可以写明首次差异阶段。

新增、移除和一致分别能说明什么

“新增”说明候选清单比原包多出权限声明,需要进一步确认功能是否需要、声明由哪个阶段引入,以及是否涉及平台政策。它不证明应用已经滥用权限,也不自动意味着加固过程有缺陷。“移除”表示候选列表里没有原包的某项声明,但不证明相关功能仍然可用;运行时 API 调用、SDK 行为和业务路径需要另行检查。

“一致”表示两份被比较的权限集合相同。如果文本取错、输入不完整、工具输出解析失败或候选身份错误,这个结论没有意义。因此记录应包含文件身份和命令执行结果。即使权限集合一致,也不能推导 APK 字节相同、签名相同、target SDK 相同、隐私实践合规或应用商店审批通过。比较结论的表述应限于“指定两个产物的已读取权限列表相同”。

对于 READ_CONTACTS 等敏感权限,还需要将权限状态与功能用途、目标 SDK 和目标商店规则分开判断。Google Play 对面向 Android 17/API 37+ 且请求 READ_CONTACTS 的应用公布了联系人权限要求;能由用户主动选择少量联系人完成的场景,可评估 Contact Picker 等更小范围方案。Permission Diff 能指出候选清单中存在什么声明,但不能说明某个业务是否符合“核心功能必要性”,也不能提交或批准 Play Console 声明。具体政策事实和时间点请以御盾的 Android 17 联系人权限说明及 Google Play 当前规则为准。

动态时间线:把权限证据绑定到发布候选

权限比较的时间线从“选择对象”开始,而不是从粘贴清单开始。先确定业务版本和目标渠道,然后固定构建变体与依赖状态;随后保留 Original、Protected Candidate 和 Final Signed Artifact 的来源关系。每次生成的清单都应能追溯到对应文件,避免把上一轮的文本误贴到新候选。

下一步读取目标变体的 Merged Manifest,保存合并报告。完成构建后,用同一 Android SDK 工具读取 Original APK 和 Protected APK 的 Manifest 权限与 target SDK。若候选经客户正式签名或渠道侧重新处理,还应读取最后交付的 APK 并重新比较。出现差异时,沿相邻阶段回到首次出现的位置,再核查依赖版本、构建任务、保护参数或渠道处理记录。

最后,发布负责人复核列表是否完整、产物身份是否一致、差异项是否有业务依据,并把未完成项标为 UNKNOWN 或 NOT_TESTED。只有在风险和政策判断另有证据的情况下,才能决定放行。静态权限列表可以作为发布记录的一部分,但不是对用户数据访问行为的完整观测,也不替代 Play Console 的政策审核。

事实依据与脱敏证据

本节把本期用户提供的工作重点、官方公开资料、工程判断和结论边界逐项对照,帮助读者区分“为什么选择这个检查问题”与“官方资料实际证明了什么”。搜索需求方向仍是待验证的选题假设,不是已经确认的关键词流量或排名增长。

序号 公开事实或本期输入 工程判断 不能据此推出
1 Google Play 对 target API 37+ 且请求 READ_CONTACTS 的应用提出联系人权限要求 发布门禁应检查最终产物而不只看源码 某个具体御盾包触发或通过该政策
2 报告要求建设 APK 权限差异能力,并把实际测试结果与未测试状态分开 先提供本地、可复核的清单比较路径 御盾已有 APK 自动解析或合规认证能力
3 Android 官方 apkanalyzer 提供 Manifest 权限与 target SDK 查询命令 两份 APK 的静态清单可用相同工具读取后比较 该命令检查运行时数据访问行为
4 Gradle 构建会合并多个源集、变体和依赖库中的 Manifest 权限差异应沿合并阶段定位来源 发现新增权限就代表由某 SDK 或加固器单独引入
5 本期报告明确没有执行御盾 APK/AAB 权限差异测试 产品侧结论必须标记为 NOT_TESTED 任何权限“PASS”或“不变”的产品结论
6 apkanalyzer manifest permissions 文档命令以 APK 文件为输入 AAB 与设备交付 APK 要另按实际发布流核对 某个通用 APK 覆盖所有 AAB 配置
7 Android 官方文档还提供 manifest target-sdk 命令 可在清单对比时并列记录 target SDK target SDK 足以代表权限政策结论
report_scope: 2026-10-08
public_tool: local_comparison_of_pasted_apkanalyzer_permission_output
raw_apk_upload: false
yudun_apk_permission_diff: NOT_TESTED
play_policy_compliance: NOT_TESTED
search_demand_validation: NOT_VERIFIED

Source Report Mapping:本期问题与页面回应

下表把本期推进报告提出的问题转成可公开核对的处理范围;它记录的是选题依据和边界,不是御盾 APK 测试结果。

报告事实或需求 本页回应 公开边界
本期策略优先建设 APK 权限差异检测,减少重复政策解释 提供 apkanalyzer 输出比较流程和独立工具入口 工具不解析 APK 二进制
报告指出需要第一份可复核 Manifest 发布证据 明确列出需要记录的产物身份与状态字段 没有授权 APK,保持 NOT_TESTED
权限差异可涉及 Manifest Merge、依赖和构建变体 增加逐阶段定位方法 不预判任何单一 SDK 或加固流程为来源
READ_CONTACTS 政策是工具需求的上下文,而非唯一长期主题 链回 Contact Picker 政策页并说明目标 SDK/最终清单边界 权限清单比较不作 Play 合规结论
搜索需求方向尚未由平台数据验证 将搜索词作为待验证方向,不报告流量或排名增长 未导出 Search Console 数据
用户强调实测结果和未测试状态需区分 公开说明本轮只运行合成文本工具检查 没有御盾产品候选 PASS/FAIL

测试目标与非目标:本地比较器的范围

本轮主目标是实现并核对一项本地权限文本比较能力;非目标是声称完成御盾 APK 评估。页面脚本可以用合成的权限列表做工具逻辑自检,但这不是御盾 APK 实测,也不能证明对所有 apkanalyzer 版本、所有权限输出格式或 AAB 产物均有覆盖。任何格式兼容问题都应回报并先人工复核,不得将空解析结果解释为无差异。

目标 输入 本轮状态 不能推出
比较两份命令输出 用户粘贴的权限文本 工具逻辑自检 不能证明来源文件身份
列出新增/移除/共有权限 可解析的权限名 工具逻辑自检 不能判定权限用途是否合法
识别空输入或解析失败 两侧文本为空或无权限行 代码路径已实现 不能将解析失败当作零权限
检查御盾实际候选 授权的 Original/Protected APK NOT_TESTED 不报告 PASS/FAIL

非目标包括:读取客户 APK、验证签名或包名、扫描组件暴露、检查运行时权限调用、执行 Google Play 政策判定、测试 Contact Picker 功能或证明御盾加固兼容性。当前没有提供授权的自有 APK 样本、构建产物摘要和 Play Console 记录,因此产品测试结果均为 NOT_TESTED,并未生成第一方权限一致性证据。

权限差异记录建议

实际执行时至少记录:产物角色、文件摘要、应用版本、构建变体、APK/AAB 类型、Android SDK Build Tools/apkanalyzer 版本、权限集合、比较结果、检查时间、复核责任人和未覆盖项。对 AAB 应记录用于检查的具体 APK 集合或由发行流程生成的设备配置产物,不能只保留一个“通用 APK”结果。

Original Artifact: NOT_TESTED
Candidate Artifact: NOT_TESTED
Original Permission Set: NOT_TESTED
Candidate Permission Set: NOT_TESTED
Added / Removed / Unchanged: NOT_TESTED
Manifest Merge Source: NOT_TESTED
Play Policy Review: NOT_TESTED
Checked At: null

上面的记录是空白状态示例,不是御盾产品检查结论。得到真实产物后,应先在授权环境读取并保存结果,再把客户身份、包名、签名与内部路径脱敏后决定是否公开。即使第一次真实比较结果为“无差异”,也只能陈述被测的这两个候选和工具版本,不能宣传成御盾所有策略、版本和 APK 权限永远一致。

工程落地前的复核清单

比较前先确认两份 APK 都由可追溯的构建任务产生,并对文件计算本地摘要;摘要只用于固定对象,不需要公开给搜索页面。记录 SDK 工具版本和命令退出状态,确保输出不是截断的错误信息。若流水线采用自动保存或复制候选产物的方式,还应核对实际读取路径与发布目录的对应关系,避免拿到旧文件或 Debug 文件。以上检查应由拥有构建系统访问权限的团队完成。

差异出现后,先按权限名聚合并查阅官方平台文档,确认该项是 Android 系统权限、应用自定义权限还是工具输出中的其他标识。遇到目标 SDK 或平台版本相关规则时,记录采用的版本条件和复核日期。若某项权限来自依赖库,应查看 Manifest Merger 报告并与依赖版本对应;不能只凭库名称或源码中的单个片段做结论。需要移除依赖声明时,应评估库功能是否还可运行,并做构建与关键路径验证。

权限清单比较适合成为一个小型发布检查,而不是独立的“合规认证”。它能够帮助团队缩短差异定位时间,但产品决策还需要把功能必要性、用户体验、数据保留、隐私披露、商店规则和运行时行为放入评估。静态权限结果最好附在同一 Release Record 中,以便后续候选、依赖或目标 SDK 变化时可以重做比较。

工程落地:不要把静态差异合并成一个 PASS

适合的门禁至少拆成三个独立问题:第一,最终 APK 实际声明了什么权限;第二,目标商店政策和开发者声明是否已按当前规则复核;第三,受保护候选在目标设备和业务路径上的兼容情况是否已经测试。三种结论可以共同关联到版本号和候选摘要,但不应互相替代。

若新增权限无法解释、输入身份不匹配、命令输出为空、产物差异尚未定位或政策状态未知,门禁应输出 REVIEW_REQUIRED、UNKNOWN 或 NOT_TESTED,而不是默认通过。高风险权限的移除也要检查业务功能,不能为了让列表变短而破坏用户流程。策略判断和加固产品判断应分别由相应责任方完成。

御盾的产品职责是保护 App 候选并支持发布验收;Android SDK 工具提供静态 APK 检查;Google Play 对其分发政策作审核;客户发布团队负责确定业务用途、产物身份与放行。将这几项分开记录,才有可能在出现差异时定位问题并复核责任边界。

攻防视角:权限声明只是一个静态观察面

权限列表是交付物 Manifest 的声明面,既不能独立证明应用实际读取了哪些数据,也不能覆盖运行时 SDK、用户授权状态、服务端同步和业务用途。反过来,某项权限出现在清单里也不足以单独说明应用正在滥用它。防守方应先用构建产物和合并来源确定“声明了什么”,再结合代码路径、运行期验证和平台政策判断“为什么需要、何时使用、是否允许”。工具输出只支持第一步,不能被扩展成完整安全或隐私结论。

常见误区

  • 误区:主 Manifest 没有声明,就说明 APK 没有该权限。应读取最终产物。
  • 误区:两份权限集合相同,就说明 APK 或签名完全相同。比较器只比较清单文本。
  • 误区:发现新权限就能归因某个 SDK 或加固流程。应先定位首次出现阶段。
  • 误区:空白结果代表“没有权限”。解析失败和空清单不是同一结论。
  • 误区:权限集合符合预期就代表 Google Play 已批准。商店审核与静态清单核对相互独立。

风险边界

本页说明的是清单差异检查方法,不是法律意见、隐私审计、应用商店审批承诺或御盾产品测试报告。工具处理用户主动粘贴的命令输出,解析范围可能受格式影响;比较结果必须结合原始产物、构建记录和合并报告人工复核。政策和 Android 工具文档可能更新,实际发布时应重新检查官方来源。

常见问题

这个网页会上传 APK 或权限清单吗?

不会。它不提供 APK 上传控件,比较逻辑在浏览器内运行;粘贴的文本用于当前页面会话内计算。请仍然避免把客户标识、私有包名或敏感日志粘贴到公共设备,并以自己的网络与浏览器安全要求为准。

比较结果一致,就能说明加固没有改变 APK 吗?

不能。结果只说明两个输入文本中识别到的权限集合相同,不比较 APK 字节、签名、组件、资源、代码或运行时行为,也不说明 Google Play 合规。产物摘要、target SDK 和签名应另行记录。

为什么源码没有权限,最终 APK 却出现了?

主 Manifest、构建变体和导入库可能在构建时合并。先查看目标 Variant 的 Merged Manifest 和 Manifest Merger 报告,再核对生成 APK 是否来自同一配置。不要根据源码单文件或 SDK 名称直接判断来源。

可以直接比较 AAB 和 APK 吗?

不可以。本页按两份 APK 的 apkanalyzer manifest permissions 文本设计。AAB 需要在实际发布流程中检查 Bundle 和由其生成的设备交付 APK;要比较权限,必须确定对比的具体产物和设备配置。

御盾是否已经证明加固前后权限集合一致?

没有。本次没有获取授权的自有 APK/AAB 和御盾候选,页面也不自动解析 APK。御盾权限差异测试状态为 NOT_TESTED;需要有明确样本、产物身份和测试记录后才能给出限定范围内的实测结论。

事实依据与延伸阅读

相关阅读