Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/release-notes/versions/1.8.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### PVM2 方法级兼容修复

- 修复 UI、数据、资源、设备和媒体类因命名被整类排除的问题。对独立的基本类型计算逐方法检查,让符合条件的私有、静态和普通实例方法继续进入 PVM2 转换及产物验证。
- 统一实际转换、覆盖报告与精确必保清单的兼容判断;框架回调、对象状态、生成桥接等不满足条件的方法继续保留原执行方式,不能用必保清单绕过兼容检查。
- 保持严格模式转换成功率门槛,完整覆盖报告仍包含初始化器和兼容排除项。零转换或必保方法未覆盖时明确失败,不会静默关闭保护。
- 补充通用命名、继承与接口、桥接方法、对象状态及统计口径回归;在已授权的 Android 15 真机上完成独立样例加固前后结果对照。

### 使用说明

- 升级后重新加固,才能使用新的方法判断规则;已有加固产物不会自动改变。
- 本次扩大的是经过检查的独立计算范围,不保证任意类或全部方法均可转换。没有客户 APK 的场景,不能仅凭错误统计认定其具体方法已兼容。
- 逐方法失败报告可能包含业务标识,分享前请手动脱敏。
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/shield-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "shield-cli"
version = "1.8.1"
version = "1.8.2"
edition = "2021"
authors = ["MocikaDev"]
license = "MIT OR Apache-2.0"
Expand Down
4 changes: 2 additions & 2 deletions apps/shield-gui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/shield-gui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mocika-shield-gui",
"version": "1.8.1",
"version": "1.8.2",
"license": "MIT OR Apache-2.0",
"private": true,
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion apps/shield-gui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mocika-shield"
version = "1.8.1"
version = "1.8.2"
edition = "2021"
license = "MIT OR Apache-2.0"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion apps/shield-gui/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Shellsmith",
"version": "1.8.1",
"version": "1.8.2",
"identifier": "dev.mocika.shield-gui",
"build": {
"beforeDevCommand": "npm run dev -- --host 127.0.0.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/shield-gui/src/hooks/use-about-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type AppInfo = {
};

const defaultAppInfo: AppInfo = {
version: "1.8.1",
version: "1.8.2",
git_hash: "dev",
build_date: "unknown",
};
Expand Down
2 changes: 1 addition & 1 deletion apps/shield-gui/src/lib/protect-diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function buildPvm2FailureDiagnostic(summary: Pvm2FailureSummary, locale:
initializer: ["构造器/静态初始化器", "Initializer"],
ui_runtime_glue: ["界面/生命周期兼容规则", "UI/lifecycle compatibility"],
data_resource_runtime_glue: ["数据/资源框架兼容规则", "Data/resource compatibility"],
compiler_generated_bridge: ["编译器生成桥接类", "Compiler-generated bridge"],
compiler_generated_bridge: ["编译器生成桥接/合成方法", "Compiler-generated bridge/synthetic method"],
playback_compatibility: ["媒体/辅助类兼容规则", "Media/helper compatibility"],
nullable_receiver: ["接收者非空语义无法证明", "Nullable receiver"],
unsupported_opcode: ["不支持的指令", "Unsupported opcode"],
Expand Down
2 changes: 1 addition & 1 deletion crates/shield-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "shield-core"
version = "1.8.1"
version = "1.8.2"
edition = "2021"
authors = ["MocikaDev"]
license = "MIT OR Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion crates/shield-core/src/protection_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl Pvm2SkipReason {
Self::Initializer => "构造器/静态初始化器",
Self::UiRuntimeGlue => "界面/生命周期兼容规则",
Self::DataResourceRuntimeGlue => "数据/资源框架兼容规则",
Self::CompilerGeneratedBridge => "编译器生成桥接类",
Self::CompilerGeneratedBridge => "编译器生成桥接/合成方法",
Self::PlaybackCompatibility => "媒体/辅助类兼容规则",
Self::NullableReceiver => "接收者非空语义无法证明",
Self::UnsupportedOpcode => "不支持的指令",
Expand Down
8 changes: 6 additions & 2 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ GUI 安装包已经内置 Xop PVM2 Packer:Packer 路径留空即使用内置

PVM2 自 v7 起已支持普通/复杂条件分支、`switch`、异常表与 `throw`、对象/原始数组、标准反射调用所需的 invoke 路径,以及 `monitor-enter/exit` 同步语义。每次构建会改变虚拟 Opcode、虚拟寄存器映射、立即数编码、Handler 顺序,并从三套 Dispatcher 模板中选择一套;覆盖报告中的 `isa` 可用于确认变体。仍不满足契约的方法(例如个别 `invoke-custom`/`invoke-polymorphic`、超出寄存器或代码预算的方法)必须记入跳过原因,不能当作成功。

为保证音频/视频拖动和解码器状态,内置 Packer 会把播放器、解码器、音频/波形类及其 Kotlin/R8 合成访问器整体留在 ART;RecyclerView 适配器、Widget/View/Binding、资源/文件 Helper(兼容历史包名中的 `hepler`)也留在 ART,避免空接收者、回调和资源 ID 语义被 PVM2 改写。报告会以 `compatibility` 记录这些跳过项。资源 PAS2 同样默认跳过常见音视频扩展名,避免把需要随机访问的媒体流包装成只读顺序流。
为保证音频/视频拖动、解码器状态和框架回调,内置 Packer 对播放器、音频/波形、RecyclerView 适配器、Widget/View/Binding、资源/文件 Helper(兼容历史包名中的 `hepler`)执行方法兼容检查。涉及框架或对象状态的方法及 Kotlin/R8 合成访问器保留在 ART;符合下文 PVM2 方法级规则的独立计算方法可以转换。逐方法报告保留兼容排除分类。资源 PAS2 同样默认跳过常见音视频扩展名,避免把需要随机访问的媒体流包装成只读顺序流。

这些是按 DEX 描述符、方法指令和 Android 生命周期边界计算的通用规则,不依赖某个业务包名或某个应用的类名。PVM2 对对象接收者执行路径敏感的控制流保护:`if-eqz`/`if-nez` 已证明非空的路径可以继续虚拟化,多个路径合流时只保留所有路径都能证明的非空事实;直线调用仍保持 ART 与 PVM2 相同的空接收者异常语义。跨分支或异常边界、又无法证明非空的接收者记为 `nullable_receiver` 并保留 ART,本地创建且可证明非空的对象仍可继续虚拟化。静态调用不会被误当作需要接收者证明的实例调用。工具对无法证明语义等价的方法失败关闭并保留 ART;这能显著降低兼容风险,但不能对任意第三方 APK、厂商 ROM 或未提供的业务 Native SDK 做绝对“零崩溃”保证,正式发布仍需用目标 APK 和设备矩阵回归。

Expand Down Expand Up @@ -543,7 +543,11 @@ shield protect --input input.apk --output protected.apk \

启用 PVM2 的成功输出旁会生成 `protected.apk.protection.json` 或 `protected.aab.protection.json`。统计分别展示转换成功率、选中方法覆盖率、原始指令字节覆盖率和必保方法覆盖率;未声明必保方法时该指标为 `null`,不记为 100%。这些百分比仅针对选择范围,不代表整个应用。报告包含逐方法原因、最终索引与产物摘要,不包含密钥或明文镜像,也不进入安装包。

选择范围在兼容性过滤**之前**统计。前缀命中的 UI/导航、生成桥接和数据/资源基础设施方法仍计入分母,分别记录 `ui_runtime_glue`、`compiler_generated_bridge`、`data_resource_runtime_glue`,保持 ART 执行。不能用排除这些方法之后的候选数量作为整个前缀的覆盖率分母;精确必保清单只对该清单负责,不表示应用的关键业务已经全部识别。升级前的报告可能遗漏这三类排除项,完整前缀的覆盖率需用新打包器重新生成。
选择范围在兼容性过滤**之前**统计。UI/导航、数据/资源辅助和媒体命名不再直接排除整类:没有对象/数组参数、对象状态访问、外部调用、同步或异常处理的基本类型计算方法,可以继续进入 PVM2 指令与产物检查。私有和静态方法可在框架类中单独转换;其它实例方法仅在直接继承 `Object`、不实现接口且不覆盖 `hashCode/finalize` 契约时适用此放行规则。分支、循环和数值运算仍须通过现有编译器检查,不能只凭命名认定可转换。

构造器、静态初始化器、生成桥接/合成方法和仍涉及框架状态的候选保持原兼容边界;未解析的外部或跨 DEX 继承契约不据此扩大虚方法范围。跳过项仍计入覆盖率分母,并保留 `ui_runtime_glue`、`compiler_generated_bridge`、`data_resource_runtime_glue` 或 `playback_compatibility` 等实际分类。精确必保清单同样受方法兼容检查约束,必保项被排除时任务失败,不会自动降级。所有候选都不可转换时仍返回 `PVM2_ZERO_METHODS`,不会把零转换记为成功。这些规则不代表已识别应用全部关键业务;完整覆盖率需用新打包器重新生成。

严格模式的 70% 转换成功率门槛保持原口径:类兼容预筛排除项不算编译尝试,媒体准入失败仍计入。该指标与完整选择范围覆盖率分别报告;例如 1 个计算方法转换、1 个界面回调保留时,转换成功率可以为 100%,选中方法覆盖率仍只有 50%。

使用 `shield sign` 或 GUI 自动签名时,公共签名流程会重新比对 DEX 并更新最终文件摘要。另用外部签名工具会改变文件摘要,原报告不再对应签名后的文件。报告为本地构建记录,不是不可伪造的安全认证。新能力要求从当前源码重建的 Packer(`make build-pvm2`),旧 JAR 即使镜像版本相同也会被明确拒绝。

Expand Down
2 changes: 1 addition & 1 deletion shield-stub/compat/api19-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shield-stub/compat/api19-rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mocikashield-api19"
version = "1.8.1"
version = "1.8.2"
edition = "2021"
license = "MIT OR Apache-2.0"
build = "../../src/main/rust/build.rs"
Expand Down
2 changes: 1 addition & 1 deletion shield-stub/src/main/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mocikashield"
version = "1.8.1"
version = "1.8.2"
edition = "2021"
license = "MIT OR Apache-2.0"

Expand Down
Loading
Loading