OplusDigestUtils 是一个只读的 .NET 工具,用于解析 OPPO、realme 和 OnePlus 固件中的 Oplus 自定义 Digest MBN/ELF。它可以读取 Digest 头和分区记录,并借助 QcomImageUtils 识别 OEM、SoC、Root CA 哈希以及封装镜像的哈希表验证状态。
仓库包含类库和 Windows 命令行工具,既可以集成到 .NET 项目中,也可以直接解析一个或多个 Digest 文件。
- 解析 Oplus 自定义 Digest 的头部和分区表。
- 提取分区标签、文件名、读写权限、起始扇区、扇区数量和哈希值。
- 识别 Qualcomm 镜像中的 OEM、SoC 和 Root CA 哈希。
- 返回封装镜像的 Qualcomm 哈希表验证状态。
- 提供文件路径和
ReadOnlySpan<byte>两种类库 API。 - CLI 支持多个文件、普通文本输出和 JSON 输出。
- 支持
netstandard2.0和net10.0,并提供 Windows Native AOT 发布配置。
- 仅支持包含 Oplus 自定义 Digest 数据的 MBN/ELF,不支持仅包含 Qualcomm 标准哈希表的普通 Digest 格式。
- 当前实现按 Oplus Digest 的固定 MBN/ELF 布局定位数据,采用其他偏移或封装方式的变体可能无法解析。
- CLI 和
TryParse(string, ...)只接受文件,不支持目录或固件包自动解包;请先从固件包中提取 Digest 文件。 - CLI 和文件路径 API 会拒绝大于 64 KiB 的输入。
ReadOnlySpan<byte>重载不执行这项额外的 64 KiB 预检查。 HashHex是从 Digest 分区记录中读取的值。本项目不会加载对应的分区镜像,也不会重新计算并比对这些分区哈希。VerificationStatus表示封装 Qualcomm 镜像的哈希表状态,不等同于分区镜像验证结果,也不代表固件一定能够安全刷写或启动。- 文件不存在、无法访问等 I/O 错误目前可能直接抛出异常;调用文件 API 前应确保路径指向可读的普通文件。
| 项目 | 目标框架 | 用途 |
|---|---|---|
OplusDigestUtils | netstandard2.0、net10.0 | 可打包的解析类库 |
OplusDigestUtils.App | net10.0-windows | 支持 Native AOT 的 Windows CLI |
CI 成功发布类库后,可通过 NuGet 安装。版本号由日期和提交哈希组成,并带有预发布标识,因此安装时需要允许预发布版本:
dotnet add package OplusDigestUtils --prerelease如果需要直接引用源码项目:
<ItemGroup>
<ProjectReferenceInclude="../OplusDigestUtils/OplusDigestUtils.csproj" />
</ItemGroup>CI 成功发布 CLI 后,可从 GitHub Releases 下载与系统架构匹配的自包含 Native AOT 可执行文件:
win-x64:64 位 Intel/AMD Windowswin-x86:32 位 Intel/AMD Windowswin-arm64:ARM64 Windows
发布文件名包含运行时标识、版本日期和提交哈希。自包含可执行文件不要求目标系统预先安装 .NET 运行时。
以下示例中的 OplusDigestUtils.App.exe 表示下载后重命名的文件或本地构建产物。
OplusDigestUtils.App.exe <Digest 文件路径> [更多文件路径] [--json]
解析单个文件:
.\OplusDigestUtils.App.exe".\digest.mbn"解析多个文件并输出 JSON:
.\OplusDigestUtils.App.exe".\digest.mbn"".\digest.elf"--json直接从源码运行:
dotnet run --project OplusDigestUtils.App/OplusDigestUtils.App.csproj -c Release --".\digest.mbn"--json| 参数 | 说明 |
|---|---|
<Digest 文件路径> [更多文件路径] | 一个或多个 Digest 文件;路径包含空格时需要加引号 |
--json | 输出缩进后的 JSON;单个结果为对象,多个结果为数组 |
-h、--help | 显示用法 |
未指定 --json 时,CLI 会输出解析状态、OEM、SoC、验证状态、Root CA 哈希、Digest 头和每条分区记录。多文件模式会保留每个输入的独立结果;常规的结构解析失败不会阻止后续文件继续解析。
| 退出码 | 含义 |
|---|---|
0 | 所有文件均解析成功,或仅请求帮助 |
1 | 至少一个文件解析失败 |
2 | 未提供文件或传入未知的 -- 选项 |
以上是程序正常控制流程中的退出码;未处理的文件系统异常可能由运行时返回其他退出码。
OplusDigestParser 实现了 IOplusDigestParser。文件路径重载适合直接读取 Digest 文件:
usingOplusDigestUtils;usingOplusDigestUtils.Models;IOplusDigestParserparser=newOplusDigestParser();if(!parser.TryParse("digest.mbn",outOplusDigestParseResultresult)){Console.Error.WriteLine(result.ErrorMessage);return;}Console.WriteLine($"OEM: {result.OemType}");Console.WriteLine($"SoC: {result.SocType}");Console.WriteLine($"Root CA: {result.RootCaHashHex}");Console.WriteLine($"Hash table: {result.VerificationStatus}");foreach(OplusDigestPartitionpartitioninresult.Digest.Partitions){Console.WriteLine($"{partition.Label}: {partition.FileName}, "+$"sector={partition.StartSector}, count={partition.Sectors}, "+$"hash={partition.HashHex}");}已有内存数据时,可以使用 Span 重载:
byte[]data=File.ReadAllBytes("digest.elf");if(!parser.TryParse(data,outOplusDigestParseResultresult))Console.Error.WriteLine(result.ErrorMessage);
TryParse返回true、或IsSuccess为true,只表示 Qualcomm 外层镜像及 Oplus Digest 结构解析成功。是否通过封装镜像哈希表检查,必须另外判断VerificationStatus;即使该字段为Invalid,结构解析仍可能成功。
| 字段 | 含义 |
|---|---|
IsSuccess | Oplus Digest 结构是否解析成功 |
Digest.Header | Digest 头,包括 Magic、版本、头长度、分区数量和分区记录长度 |
Digest.Partitions | 分区记录集合 |
OemType | 从 Qualcomm 外层镜像识别出的 OEM 类型 |
SocType | 从 Qualcomm 外层镜像识别出的 SoC 类型 |
RootCaHashHex | Root CA 哈希的十六进制字符串 |
VerificationStatus | Qualcomm 外层镜像的哈希表验证状态 |
ErrorMessage | 结构解析失败时的错误信息;成功时为 null |
每个 OplusDigestPartition 包含以下字段:
| 字段 | 含义 |
|---|---|
Label | 分区标签 |
FileName | Digest 中记录的分区文件名 |
AllowRead | 是否允许读取 |
AllowWrite | 是否允许写入 |
StartSector | 起始扇区 |
Sectors | 扇区数量 |
HashHex | Digest 中记录的分区哈希十六进制字符串 |
VerificationStatus 使用 QcomVerificationStatus,常见状态包括 NotChecked、NotPresent、Valid、Invalid 和 Unsupported。
需要 .NET 10 SDK。在仓库根目录执行:
dotnet restore OplusDigestUtils.slnx
dotnet build OplusDigestUtils.slnx -c Release --no-restore发布 Windows x64 Native AOT CLI:
dotnet restore OplusDigestUtils.App/OplusDigestUtils.App.csproj -r win-x64
dotnet publish OplusDigestUtils.App/OplusDigestUtils.App.csproj `-c Release `-r win-x64 `--self-contained true `--no-restore `-o artifacts/win-x64可将 RID 替换为 win-x86 或 win-arm64。本地 Native AOT 发布还需要 Windows C/C++ 原生编译工具链。
本项目基于 MIT License 开源。