dspl1236/PCM-Explorer
GitHub: dspl1236/PCM-Explorer
PCM Explorer 是一款只读的桌面浏览器,用于在主流操作系统上解析并浏览保时捷 PCM 和奥迪 MMI 车机硬盘镜像中的 Harman 变体 QNX6 文件系统。
Stars: 0 | Forks: 0
# PCM Explorer
**在您的桌面上以只读模式打开并浏览保时捷 PCM 或奥迪 MMI 主机的硬盘。**
这些主机运行 QNX 系统,其硬盘使用 QNX6 "power-safe" 文件系统。Windows 无法
读取它。macOS 无法读取它。Linux 内置了针对 QNX 6.4+ 的只读 `qnx6` 驱动程序,但这与这些主机实际使用的 Harman 变体并不完全匹配。因此,当主机
损坏并且您对硬盘进行镜像时,您会得到一个 40 GB 的文件,但没有任何程序能打开它。
本工具可以打开它。
```
python explorer.py # desktop UI
python explorer.py disk.img # partitions + filesystem detection
python explorer.py disk.img ls P2 # list every file
python explorer.py disk.img cat P2 /HBdata/version.txt
python explorer.py disk.img extract P2 /Browser ./out # pull a file or a whole folder
python explorer.py disk.img verify P2 # filesystem self-test
```
## 它的功能
- **映射分区**并识别每个分区的文件系统,从 QNX6 超级块中读取真实的几何参数
(块大小、inode 计数、分配组)。
- **列出所有文件和文件夹**,包含大小、权限和 inode 编号。
- **读取文件内容** — 在 UI 中预览、`cat` 到 stdout,或者将单个文件
或整个文件夹树提取到磁盘。支持处理任意大小的文件、稀疏空洞和符号链接。
- **自我校验**,对比文件系统自身的账目(见下文)。
- **抢救模式**,适用于损坏严重无法挂载的硬盘,并提供任意字节偏移量的十六进制视图。
## 它真的有效吗?
对于恢复工具来说,这是问得对的问题,因此它自带了一个 `verify` 命令,
可以根据文件系统自身的记录来校验读取器:
```
[PASS] geometry (plen/bs) - num_blocks == 16
[PASS] inode census 376 live, superblock says 376
[PASS] block bitmap 546413 clear, superblock says 546413 free
[PASS] directory identity 20 directories checked, 0 inconsistent
```
块位图检查是最有趣的一项:它通过完全不同的根节点和块链到达位图,这与 inode 逻辑不同,因此它独立地确认了读取器正在正确的位置进行查找。
在开发过程中,提取的字节也经过了内容验证 — 硬盘上的每一个 PNG
块 CRC(970/970),所有 47 个二进制文件上的 ELF 节表(其中几个的结尾*恰好*在 EOF 处,这证明了多级文件映射的最后一个块是正确的),
SQLite 数据库上的 `PRAGMA integrity_check`,以及通过两级间接寻址正确读取的 387 MB 映像的 ISO9660 描述符。
## 抢救模式
如果硬盘损坏严重导致超级块无法读取,`salvage` 依然可以恢复目录结构。每个 QNX6 目录块都会自我标识 — 它的第一个条目是 `.`,保存着自己的 inode 编号,第二个是 `..`,保存着其父目录的 inode 编号 — 因此,扫描原始分区以寻找该特征可以在完全没有元数据的情况下重建层级结构。您可以获得名称和结构,但无法获得内容,这通常足以了解硬盘上曾有什么,以及是否值得进行更深度的恢复。
## 工作原理
该格式在 [docs/QNX6-NOTES.md](docs/QNX6-NOTES.md) 中有文档说明 — 足以让您编写自己的读取器。简短版本是:一切都取决于一个常量。块号是相对于*数据区域*的起始位置,而不是相对于分区的:
```
image_offset(block B) = partition_base + 0x3000 + B * blocksize
```
错过了那 12 KiB,每个间接链都会落入无关的数据中,读取时就会好像文件系统到处都是空洞一样 — 这正是为什么这个变体看起来像是专有的原因。其实
并不是。有了正确的起始位置,它就与公开的 QNX6 布局相匹配。
## 安装
需要 **Python 3.8+**。Tkinter 随 Windows 和 macOS 上的 Python 一起提供;在 Linux 上您可能需要
`sudo apt install python3-tk`。没有其他依赖项。
```
git clone https://github.com/dspl1236/PCM-Explorer
cd PCM-Explorer
python explorer.py
```
不想安装 Python 的 Windows 用户可以从
[Releases](../../releases) 下载预构建的 `.exe` 文件。它没有签名,因此 SmartScreen 会在首次运行时警告 —
点击“更多信息” → “仍要运行”,或者如果您不想这样,直接使用 Python 版本即可。
## 硬盘镜像
从主机中取出 2.5 英寸硬盘,并使用任何块复制工具对其进行镜像 — Win32DiskImager,
`dd`,Clonezilla,或者带有镜像软件的 USB 底座。制作一个**完整的原始扇区镜像**,而不是
文件级别的备份:
```
dd if=/dev/sdX of=pcm.img bs=4M status=progress # Linux/macOS
```
然后打开 `pcm.img`。典型的 PCM 3.1 布局是三个 QNX 分区 — 一个约 2 GB 的系统
分区,一个约 1 GB 的应用程序分区,其余部分用于导航数据。
## 安全性
镜像以只读模式(`rb`)打开,并且本项目中的任何代码路径都不会对其进行写入。使用
副本而不是原始硬盘仍然是正确的习惯。
**隐私提示:** 主机硬盘包含 VIN、保存的导航目的地、手机
配对和通话记录。请将镜像 — 以及任何导出的树 — 视为个人数据。这里的
`.gitignore` 特意排除了 `*.img`,这样您就不会意外提交它。
## Audi MMI
MMI 3G/3GP 硬盘也是由 Harman 制造的,并且也是 **QNX6** — 其上的每个分区都是
使用 `mkqnx6fs` 创建的,并且它们重用了与保时捷硬盘相同的分区类型字节(`0x4D`/`0x4E`/`0x4F`)。不过,它们的作用不同:在 MMI 硬盘上,`0x4D` 是导航
分区,而在 PCM 上,它是系统分区。因此,类型字节只是一个提示,而不是一个
答案 — 本工具会探测每个分区以寻找真实的超级块,而不是轻信它。
MMI 还在**扩展分区**内放置了另外五个分区(`gracenode`、`mmebackup1`、`persistence`、
`img-cache`、`pv-cache`),因此 PCM Explorer 会遍历扩展引导记录链,并将逻辑分区列为 `L1`、`L2`、… 停在
四个主条目处将错过硬盘的大部分内容,包括 `persistence`。
该布局源自 [DrGER 的 MMI3G-HDD-Prep-Tool](https://github.com/DrGER2/MMI3G-HDD-Prep-Tool),
即用于格式化这些硬盘的工具。扩展分区的处理已针对根据该布局构建的
合成硬盘进行了验证;**它尚未针对真实的 MMI 镜像运行过** —
如果您有这方面的镜像,提个 issue 说明它是否有效将会非常有用。
## 贡献
欢迎来自其他主机的镜像,特别是 **Audi MMI** 和 **PCM 4.x**。如果该工具
在您的镜像上报告 `unknown`,这是一个非常值得提 issue 的数据点:
分区表、大小以及每个分区的前 512 字节足以作为起点。
它的姊妹项目 [PCM-Forge](https://github.com/dspl1236/PCM-Forge) 涵盖了 PCM 3.1 的激活
码和车载工具。
MIT 授权。仅限您拥有的硬件上的研究和个人使用。
标签:Python, QNX, 数字取证, 数据恢复, 文件系统, 无后门, 自动化脚本, 逆向工具