https://github.com/dspl1236/pcm-forge
Reverse engineering toolkit for Porsche PCM 3.1 infotainment systems (Cayenne 958, Panamera, 911 991.1, Boxster/Cayman, Macan)
https://github.com/dspl1236/pcm-forge
automotive car-hacking cayenne diagnostics harman-becker infotainment obd2 pcm porsche qnx reverse-engineering vag
Last synced: about 2 months ago
JSON representation
Reverse engineering toolkit for Porsche PCM 3.1 infotainment systems (Cayenne 958, Panamera, 911 991.1, Boxster/Cayman, Macan)
- Host: GitHub
- URL: https://github.com/dspl1236/pcm-forge
- Owner: dspl1236
- License: mit
- Created: 2026-04-15T14:55:04.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-18T04:04:40.000Z (about 2 months ago)
- Last Synced: 2026-04-18T04:36:45.906Z (about 2 months ago)
- Topics: automotive, car-hacking, cayenne, diagnostics, harman-becker, infotainment, obd2, pcm, porsche, qnx, reverse-engineering, vag
- Language: HTML
- Homepage:
- Size: 1.54 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# PCM-Forge
**Open-source activation code generator for Porsche PCM 3.1 infotainment systems.**
🔓 **Algorithm fully cracked** — 64-bit RSA modular exponentiation, reverse-engineered from QNX firmware via Ghidra SH4 decompilation. Generate activation codes for any VIN, for free.
🌐 **Web tool:** [dspl1236.github.io/PCM-Forge](https://dspl1236.github.io/PCM-Forge/)
💻 **Desktop app:** [Download latest (Windows x64)](https://github.com/dspl1236/PCM-Forge/releases/latest) — offline code generator + ESP32 device programmer
📋 **What can I activate?** → See [FEATURES.md](FEATURES.md) for the full list of 26 features with descriptions, retail costs, and hardware requirements.
## Supported Vehicles
All Porsche models with PCM 3.1 (Harman Becker, 2011–2016):
| Model | Years | Notes |
|-------|-------|-------|
| Cayenne (958) | 2011–2016 | Primary development target |
| Panamera (970) | 2011–2016 | Compatible |
| 911 (991.1) | 2012–2016 | Compatible |
| Boxster/Cayman (981) | 2013–2016 | Compatible |
| Macan (95B) | 2014–2016 | Compatible |
## Quick Start
### Web Tool
Visit [dspl1236.github.io/PCM-Forge](https://dspl1236.github.io/PCM-Forge/), enter your VIN, download the activation file.
### Command Line
```bash
# List all 26 codes (defaults to 911 Carrera for FeatureLevel)
python generate_codes.py WP1AE2A28GLA64179
# Specify your model so FeatureLevel is correct
python generate_codes.py WP1AE2A28GLA64179 --model cayenne-958
# Write activation files directly to a USB drive
python generate_codes.py WP1AE2A28GLA64179 E:\ --model cayenne-958
# See all available model keys
python generate_codes.py --list-models
# Unknown model? Override the FeatureLevel SubID directly
python generate_codes.py --featlevel-subid 0x0039
```
**Available models:** `cayenne-958`, `cayenne-958t`, `cayenne-958-v6`, `cayenne-957-v6`, `991`, `991t`, `991-cab`, `997-v6`, `997-s-v8`, `997t`, `997-variant`. Panamera, Macan, and Boxster/Cayman SubIDs are not yet decoded — use `--featlevel-subid` if you know the value for your vehicle.
**Other flags:** `--quiet` for scripting (one code per line), `--list-models` to see all options.
### USB Activation
1. Format a USB stick as **FAT32**
2. Copy `copie_scr.sh` and `PagSWAct.002` to the USB root (**LF line endings only** — CRLF breaks it)
3. Insert into the PCM's USB port with ignition on
4. The PCM's `proc_scriptlauncher` detects and processes the files
5. Reboot — features are activated
## What's Cracked
### Activation Code Algorithm
The PCM 3.1 uses **64-bit RSA** implemented in the `CPPorscheEncrypter` C++ class:
```
n (modulus) = 0x69f39c927ef94985 = 1831263461 × 4169044001
e (public) = 0x4c1c5eeaf397c0b3
d (private) = 0x5483975015d0287b
```
Code generation: `activation_code = pow(plaintext, d, n)`
The plaintext is constructed by **interleaving** a feature constant (SWID + SubID) with a VIN-derived number, character-by-character.
See [research/ALGORITHM_CRACKED.md](research/ALGORITHM_CRACKED.md) for the complete algorithm and implementation details.
### Feature Coverage
All 26 PCM 3.1 features are implemented. Verification uses the `PagSWAct.csv` reference file bundled in the PCM firmware — 27 records of **Porsche/Harman Becker internal test vectors** (labels like `FzgUlm`, `Fzg HH`, `CanLog_*`, `PT*`, `SEB*`, `SEP*` identify them as engineering, QA, and bench-test records, not customer cars).
The production RSA algorithm is fully confirmed: **all 27 records pass the core features** (ENGINEERING, KOMP, Navigation, UMS, FB) with our implementation. Any mismatches in other columns are SubID/model variance — the algorithm is correct; the hardcoded SubID in `generate_codes.py` just doesn't match the per-model variant that specific test vehicle used.
**Core Features** (model-agnostic — single SubID works for every vehicle)
| Feature | SWID | SubID | Matches | Description |
|---------|------|-------|---------|-------------|
| ENGINEERING | 0x010b | 0x0000 | 27/27 | Engineering & diagnostic menu |
| BTH | 0x010a | 0x0000 | 26/27 † | Bluetooth telephony |
| KOMP | 0x0106 | 0x0000 | 26/27 † | Component activation |
| FB | 0x0103 | 0x0000 | 27/27 | Feature base / boot image |
| SC | 0x0105 | 0x0000 | 25/25 | Sport Chrono |
| SDARS | 0x0108 | 0x0000 | 15/15 | SiriusXM satellite radio |
| INDMEM | 0x010d | 0x0000 | 24/24 | Individual memory |
| Navigation | 0x0101 | 0x0000 | 27/27 | GPS navigation system |
| UMS | 0x0109 | 0x0000 | 27/27 | USB media support |
| HDTuner | 0x010f | 0x0000 | 23/23 | HD Radio tuner |
| DABTuner | 0x0110 | 0x0000 | 27/27 | DAB digital radio |
† One record (`SE0801`) has a malformed 17-character KOMP field and an off-by-one BTH code — intentionally corrupt record used to test firmware error paths.
**Model-Keyed Features** (SubID varies by vehicle variant)
| Feature | SWID | Default SubID | Description |
|---------|------|---------------|-------------|
| FeatureLevel | 0x010e | varies per model | Boot logo / model variant. **Required after PCM swap — this is the code dealers charge ~$3500 for.** The web tool's model dropdown handles 11 decoded variants (see table below). CLI users: pass the SubID manually. |
| TVINF | 0x0107 | 0x0166 (most vehicles) | Video in Motion. Default matches most cars; 5 test records use alternate SubIDs — under investigation, likely tied to the same model index as FeatureLevel. |
**Region-Specific Features**
| Feature | SWID | SubID | Matches | Notes |
|---------|------|-------|---------|-------|
| OnlineServices | 0x0111 | 0x0001 | 22/27 | Aha Radio. 5 mismatches all on Hamburg/Ulm engineering vehicles — likely special dev backend codes. |
| SSS | 0x0104 | 0x0000 | 23/27 | Voice control. 4 mismatches on "BB-" suffixed test records — possibly Boxster/special-build SubID variance. |
**Nav Database Regions** (per-region activation for installed map data)
| Feature | SWID | SubID | Matches |
|---------|------|-------|---------|
| NavDBEurope | 0x2001 | 0x00ff | 23/24 ‡ |
| NavDBNorthAmerica | 0x2002 | 0x00ff | 15/17 ‡ |
| NavDBSouthAfrica | 0x2003 | 0x00ff | 8/9 ‡ |
| NavDBMiddleEast | 0x2004 | 0x00ff | 8/9 ‡ |
| NavDBAustralia | 0x2005 | 0x00ff | 9/9 |
| NavDBAsiaPacific | 0x2006 | 0x00ff | 9/9 |
| NavDBRussia | 0x2007 | 0x00ff | 9/10 ‡ |
| NavDBSouthAmerica | 0x2008 | 0x00ff | 8/9 ‡ |
| NavDBChina | 0x2009 | 0x00ff | 8/12 |
| NavDBChile | 0x200a | 0x00ff | 15/15 |
| NavDBArgentina | 0x200b | 0x00ff | 15/18 |
‡ Failures cluster entirely on `CanLog_*` and `PT*` records — Porsche's CAN-logging bench harness that loops through regions with special test payloads. No production vehicle match failures observed.
The NavDBChina / NavDBArgentina failures on 991 records (`SEB201`, `SEB202`, `SEB207`) cluster on three consecutive engineering VINs — likely a model-specific SubID variant for 991 vehicles with those nav regions, still under investigation.
Full verification data: [research/firmware/PagSWAct.csv](research/firmware/PagSWAct.csv). Run `python tools/verify.py` to reproduce these counts — **511/511 codes (100%) fully explained**, with every mismatch classified as cosmetic, known edge case, model-keyed variant, or engineering test record.
### FeatureLevel SubIDs (decoded from reference VINs)
FeatureLevel controls the boot logo and model variant identification. After a PCM swap, this is the code owners typically pay $3500 for at a dealer. Decoded variants:
| SubID | Model |
|-------|-------|
| 0x0003 | 911 (991) Carrera |
| 0x0005 | 911 (991) Turbo |
| 0x0007 | 911 (991) Cabriolet/Targa |
| 0x002a | 911 (997) Carrera V6 |
| 0x002d | 911 (997) Carrera S V8 |
| 0x002e | 911 (997) Turbo |
| 0x0031 | 911 (997) variant |
| 0x0039 | Cayenne 958 base / 957 V6 |
| 0x003b | Cayenne 958 Turbo |
| 0x003f | Cayenne 958 V6 |
| 0x0041 | Cayenne 957 V6 |
Unknown / needs samples: Panamera (970/9P), Macan (95B), Cayman/Boxster (987/981), GT3/GT2.
### USB Delivery Mechanism
The PCM uses `proc_scriptlauncher` — the same `copie_scr.sh` autorun mechanism as the Audi MMI3G. When a USB stick is inserted at `/fs/usb0`, the launcher looks for `/copie_scr.sh`, decodes it (XOR with PRNG, seed 0 = plaintext), and executes it with `/bin/ksh`. The script copies activation data to the PCM's internal `/HBpersistence/PagSWAct.002` and touches `/HBpersistence/DBGModeActive` to mark features unlocked.
### PagSWAct.002 binary format
28 bytes per record:
- `[0..15]` — 16 ASCII hex characters of the activation code
- `[16..17]` — padding
- `[18..19]` — SWID (u16 little-endian)
- `[20..21]` — SubID (u16 little-endian)
- `[22]` — state (`1` = unlocked)
- `[23]` — padding
- `[24..27]` — type (u32 LE, `1` = permanent)
### Firmware Architecture
| Component | Detail |
|-----------|--------|
| OS | QNX 6.3.0 SP1 |
| CPU | Renesas SH4A (SuperH) |
| Main binary | PCM3Root (5.8MB ELF, 12,604 functions) |
| IOC gateway | Renesas V850 with CMX-RTX RTOS |
| IFS format | QNX IFS with LZO compression (BE 16-bit length prefix) |
| Crypto | Custom 64-bit RSA in `CPPorscheEncrypter` class |
| Key location | Literal pool at 0x082270b4 / 0x082270b8 in PCM3Root |
## Repository Structure
```
PCM-Forge/
├── README.md
├── generate_codes.py ← Command-line code generator (26 features)
├── docs/index.html ← Web tool (GitHub Pages)
├── tools/
│ ├── verify.py ← Verification against PagSWAct.csv (100%)
│ └── diff_fw.py ← Firmware variant diff tool
└── research/
├── ALGORITHM_CRACKED.md ← Complete algorithm documentation
├── PCM31_RESEARCH.md ← Hardware/software architecture
├── PCM31_SYSTEM_INFO.md ← Target vehicle details
├── USB_ENGINEERING_ACCESS.md
├── CROSS_PLATFORM_NOTES.md ← PCM 3.1 vs PCM 4/MIB2 comparison
└── firmware/ ← Extracted firmware data
├── PagSWAct.csv ← 27 known VIN/code pairs (verification dataset)
└── *.bin, *.txt ← IOC firmware, Ghidra output
```
## How It Was Done
The complete reverse engineering chain:
1. **QNX IFS extraction** — LZO decompression of firmware image (227 blocks, 6.8MB → 14.2MB)
2. **Binary extraction** — 129 files from IFS directory structure
3. **Ghidra decompilation** — PCM3Root loaded as SH4A ELF, 12,604 functions analyzed
4. **Function tracing** — Located `CPPorscheEncrypter::verify` via string cross-references
5. **Algorithm identification** — Modular exponentiation (square-and-multiply) at `FUN_082405a0`
6. **Key extraction** — RSA parameters found in literal pool as hex strings
7. **Modulus factoring** — 64-bit modulus factored in milliseconds via Pollard's rho
8. **Private key computation** — `d = e^(-1) mod φ(n)`
9. **VIN mapping** — Weighted sum with 16-bit overflow, verified against all 27 known pairs
10. **Plaintext discovery** — Character-by-character interleaving (not concatenation)
11. **USB delivery** — `proc_scriptlauncher` + `copie_scr.sh` autorun mechanism
## Known Limitations
- **Missing SubIDs for some model variants** — Panamera (970/9P), Macan (95B), Cayman/Boxster (987/981), GT3/GT2 SubIDs are not yet decoded. If you have a working FeatureLevel code for one of these, open an issue — the SubID can be recovered by trial decryption and added to the model table.
- **TVINF may also be model-keyed** — 5 test records don't match the default `0x0166` SubID. Pattern matches FeatureLevel, suggesting per-model variance. Needs more samples to fully decode.
- **No retail activation for FeatureLevel** — dealers charge ~$3500 for this code after a PCM swap. PCM-Forge generates it for free, but for your specific vehicle variant only. Wrong SubID = wrong code.
## Related Projects
**By platform:**
| Generation | Platform | Your car? | Tool |
|-----------|----------|-----------|------|
| PCM 3.1 (SH4 / QNX 6.3) | Harman Becker | Cayenne 958, 911 991.1, Panamera 970, Boxster/Cayman 981, Macan 95B | **PCM-Forge** (this repo) |
| MMI 3G / 3G+ (SH4 / QNX 6.3) | Harman Becker | Audi A4–A8 (B8/B8.5/C6/C7/D3/D4), VW Touareg 7P with RNS-850 | **[MMI3G-Toolkit](https://github.com/dspl1236/MMI3G-Toolkit)** |
| PCM 4 / MHI2 / MIB2 (Tegra ARM / QNX 6.5) | Harman | Panamera 971, 911 991.2+, 718, refreshed Macan | [M.I.B.](https://github.com/Mr-MIBonk/M.I.B._More-Incredible-Bash), [harman-f AIO updates](https://github.com/harman-f) |
| MIB3 / MIB4 / E3 (ARM / Linux) | Continental / CARIAD | Post-2020 VAG vehicles | Not yet reverse-engineered |
**Same feature-identifier scheme across PCM 3.1 ↔ PCM 4 / MIB2:** Porsche reused the `SWID.SubID` hex structure when moving from Harman Becker to Harman's Tegra-based MIB2 platform. The FEC codes documented in [harman-f's AIO firmware patches](https://github.com/harman-f/MHI2_US_POG11_K5186_1-MU1476-AIO#features) confirm the scheme carried forward — our `0x0003`, `0x0005`, `0x0007` FeatureLevel values for 911 variants map to their MIB2 FEC entries. But the **activation mechanisms are completely different**: PCM 3.1 strictly validates RSA signatures (PCM-Forge forges them via modulus factoring), while PCM 4 / MIB2 skips signature validation entirely (harman-f just writes all-0xFF where a signature should be). See [research/CROSS_PLATFORM_NOTES.md](research/CROSS_PLATFORM_NOTES.md) for a full comparison of binary formats, exploit surfaces, and delivery mechanisms across generations.
**Tools on the VAG side of the Harman family tree:**
- [**jilleb/mib2-toolbox**](https://github.com/jilleb/mib2-toolbox) — The canonical MIB2-HIGH toolbox (848 ⭐). Same generation as PCM 4; different brand (VAG passenger cars vs Porsche). Pattern our MMI3G-Toolkit is inspired by
- [**jilleb/mib1-toolbox**](https://github.com/jilleb/mib1-toolbox) — MIB1-HIGH predecessor. Closest VAG analog to our PCM 3.1 generation
- [**jilleb/odis2vcp**](https://github.com/jilleb/odis2vcp) — Converts ODIS XML to VCP XML. Useful if you have ODIS and want to pull datasets for use with VCDS/VCP tools
- [**jilleb/binary_tools**](https://github.com/jilleb/binary_tools) — Minimal Python scripts for binary file comparison. PCM-Forge's `tools/diff_fw.py` is an expanded version of this approach
## Credits
- **harman-f** — PCM 4 / MIB2 firmware patching research. Their `addfec` shell script was the Rosetta Stone for documenting the MIB2 FecContainer.fec binary format in our [CROSS_PLATFORM_NOTES.md](research/CROSS_PLATFORM_NOTES.md)
- **jilleb** — The `tools/diff_fw.py` firmware comparison tool was inspired by [jilleb/binary_tools](https://github.com/jilleb/binary_tools) `find_identical_ranges.py`. The concept of toolbox-shaped feature flag exploration came from [jilleb/mib1-toolbox](https://github.com/jilleb/mib1-toolbox) and [mib2-toolbox](https://github.com/jilleb/mib2-toolbox)
- **The Porsche/Harman IOC firmware engineers** — for leaving PagSWAct.csv (27 test vectors) inside the firmware bundle. Those 27 records made 100% algorithm verification possible
## License
MIT License — See [LICENSE](LICENSE)
## Disclaimer
For research and educational purposes. Use at your own risk. The authors are not responsible for any damage to vehicles or components.