mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
163 lines
6.6 KiB
Markdown
163 lines
6.6 KiB
Markdown
# Synology PAT/SPK Encrypted Archive Decryption
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## Pregled
|
||
|
||
Nekoliko Synology uređaja (DSM/BSM NAS, BeeStation, …) distribuira svoj firmware i aplikacione pakete u **kriptovanim PAT / SPK arhivama**. Te arhive se mogu dekriptovati *offline* samo uz javne preuzete datoteke zahvaljujući hard-kodiranim ključevima ugrađenim unutar zvaničnih biblioteka za ekstrakciju.
|
||
|
||
Ova stranica dokumentuje, korak po korak, kako kriptovani format funkcioniše i kako potpuno povratiti čisti tekst **TAR** koji se nalazi unutar svakog paketa. Procedura se zasniva na istraživanju Synacktiv-a sprovedenom tokom Pwn2Own Irska 2024 i implementirana je u open-source alatu [`synodecrypt`](https://github.com/synacktiv/synodecrypt).
|
||
|
||
> ⚠️ Format je potpuno isti za `*.pat` (ažuriranje sistema) i `*.spk` (aplikacija) arhive – jedino se razlikuju u paru hard-kodiranih ključeva koji se biraju.
|
||
|
||
---
|
||
|
||
## 1. Preuzmite arhivu
|
||
|
||
Ažuriranje firmware/aplikacije se obično može preuzeti sa javnog portala Synology:
|
||
```bash
|
||
$ wget https://archive.synology.com/download/Os/BSM/BSM_BST150-4T_65374.pat
|
||
```
|
||
## 2. Ispusti PAT strukturu (opciono)
|
||
|
||
`*.pat` slike su same **cpio paket** koji sadrži nekoliko datoteka (boot loader, kernel, rootfs, paketi…). Besplatni alat [`patology`](https://github.com/sud0woodo/patology) je zgodan za pregledavanje tog omota:
|
||
```bash
|
||
$ python3 patology.py --dump -i BSM_BST150-4T_65374.pat
|
||
[…]
|
||
$ ls
|
||
DiskCompatibilityDB.tar hda1.tgz rd.bin packages/ …
|
||
```
|
||
Za `*.spk` možete direktno preći na korak 3.
|
||
|
||
## 3. Izdvojite Synology biblioteke za ekstrakciju
|
||
|
||
Prava logika dekripcije se nalazi u:
|
||
|
||
* `/usr/syno/sbin/synoarchive` → glavni CLI omotač
|
||
* `/usr/lib/libsynopkg.so.1` → poziva omotač iz DSM UI
|
||
* `libsynocodesign.so` → **sadrži kriptografsku implementaciju**
|
||
|
||
Oba binarna fajla su prisutna u sistemskom rootfs (`hda1.tgz`) **i** u komprimovanom init-rd (`rd.bin`). Ako imate samo PAT, možete ih dobiti na ovaj način:
|
||
```bash
|
||
# rd.bin is LZMA-compressed CPIO
|
||
$ lzcat rd.bin | cpio -id 2>/dev/null
|
||
$ file usr/lib/libsynocodesign.so
|
||
usr/lib/libsynocodesign.so: ELF 64-bit LSB shared object, ARM aarch64, …
|
||
```
|
||
## 4. Povratak hard-kodiranih ključeva (`get_keys`)
|
||
|
||
Unutar `libsynocodesign.so` funkcija `get_keys(int keytype)` jednostavno vraća dve 128-bitne globalne promenljive za traženu porodicu arhiva:
|
||
```c
|
||
case 0: // PAT (system)
|
||
case 10:
|
||
case 11:
|
||
signature_key = qword_23A40;
|
||
master_key = qword_23A68;
|
||
break;
|
||
|
||
case 3: // SPK (applications)
|
||
signature_key = qword_23AE0;
|
||
master_key = qword_23B08;
|
||
break;
|
||
```
|
||
* **signature_key** → Ed25519 javni ključ koji se koristi za verifikaciju zaglavlja arhive.
|
||
* **master_key** → Glavni ključ koji se koristi za derivaciju ključa za enkripciju po arhivi.
|
||
|
||
Morate da izbacite ta dva konstanta samo jednom za svaku glavnu verziju DSM-a.
|
||
|
||
## 5. Struktura zaglavlja i verifikacija potpisa
|
||
|
||
`synoarchive_open()` → `support_format_synoarchive()` → `archive_read_support_format_synoarchive()` izvršava sledeće:
|
||
|
||
1. Pročitajte magiju (3 bajta) `0xBFBAAD` **ili** `0xADBEEF`.
|
||
2. Pročitajte little-endian 32-bitni `header_len`.
|
||
3. Pročitajte `header_len` bajtova + sledeći **0x40-bajtni Ed25519 potpis**.
|
||
4. Iterirajte kroz sve ugrađene javne ključeve dok `crypto_sign_verify_detached()` ne uspe.
|
||
5. Dekodirajte zaglavlje sa **MessagePack**, što daje:
|
||
```python
|
||
[
|
||
data: bytes,
|
||
entries: [ [size: int, sha256: bytes], … ],
|
||
archive_description: bytes,
|
||
serial_number: [bytes],
|
||
not_valid_before: int
|
||
]
|
||
```
|
||
`entries` kasnije omogućava libarchive da proveri integritet svake datoteke dok se dekriptuje.
|
||
|
||
## 6. Izvedi podključ po arhivi
|
||
|
||
Iz `data` blob-a sadržanog u MessagePack header-u:
|
||
|
||
* `subkey_id` = little-endian `uint64` na offsetu 0x10
|
||
* `ctx` = 7 bajtova na offsetu 0x18
|
||
|
||
32-bajtni **stream key** se dobija pomoću libsodium:
|
||
```c
|
||
crypto_kdf_derive_from_key(kdf_subkey, 32, subkey_id, ctx, master_key);
|
||
```
|
||
## 7. Synology-ov prilagođeni **libarchive** backend
|
||
|
||
Synology uključuje ispravljen libarchive koji registruje lažni "tar" format kada je magija `0xADBEEF`:
|
||
```c
|
||
register_format(
|
||
"tar", spk_bid, spk_options,
|
||
spk_read_header, spk_read_data, spk_read_data_skip,
|
||
NULL, spk_cleanup, NULL, NULL);
|
||
```
|
||
### spk_read_header()
|
||
```
|
||
- Read 0x200 bytes
|
||
- nonce = buf[0:0x18]
|
||
- cipher = buf[0x18:0x18+0x193]
|
||
- crypto_secretstream_xchacha20poly1305_init_pull(state, nonce, kdf_subkey)
|
||
- crypto_secretstream_xchacha20poly1305_pull(state, tar_hdr, …, cipher, 0x193)
|
||
```
|
||
Dešifrovani `tar_hdr` je **klasična POSIX TAR glava**.
|
||
|
||
### spk_read_data()
|
||
```
|
||
while (remaining > 0):
|
||
chunk_len = min(0x400000, remaining) + 0x11 # +tag
|
||
buf = archive_read_ahead(chunk_len)
|
||
crypto_secretstream_xchacha20poly1305_pull(state, out, …, buf, chunk_len)
|
||
remaining -= chunk_len - 0x11
|
||
```
|
||
Svaki **0x18-byte nonce** se dodaje ispred enkriptovanog dela.
|
||
|
||
Kada su svi unosi obrađeni, libarchive proizvodi savršeno validan **`.tar`** koji se može raspakovati sa bilo kojim standardnim alatom.
|
||
|
||
## 8. Dešifrujte sve sa synodecrypt
|
||
```bash
|
||
$ python3 synodecrypt.py SynologyPhotos-rtd1619b-1.7.0-0794.spk
|
||
[+] found matching keys (SPK)
|
||
[+] header signature verified
|
||
[+] 104 entries
|
||
[+] archive successfully decrypted → SynologyPhotos-rtd1619b-1.7.0-0794.tar
|
||
|
||
$ tar xf SynologyPhotos-rtd1619b-1.7.0-0794.tar
|
||
```
|
||
`synodecrypt` automatski detektuje PAT/SPK, učitava ispravne ključeve i primenjuje celu lanac opisan iznad.
|
||
|
||
## 9. Uobičajene zamke
|
||
|
||
* Ne **menjajte** `signature_key` i `master_key` – oni imaju različite svrhe.
|
||
* **Nonce** dolazi *pre* šifrovanog teksta za svaki blok (zaglavlje i podaci).
|
||
* Maksimalna veličina šifrovanog dela je **0x400000 + 0x11** (libsodium oznaka).
|
||
* Arhive kreirane za jednu generaciju DSM-a mogu preći na različite hard-kodirane ključeve u sledećem izdanju.
|
||
|
||
## 10. Dodatni alati
|
||
|
||
* [`patology`](https://github.com/sud0woodo/patology) – parsiranje/dump PAT arhiva.
|
||
* [`synodecrypt`](https://github.com/synacktiv/synodecrypt) – dešifrovanje PAT/SPK/drugo.
|
||
* [`libsodium`](https://github.com/jedisct1/libsodium) – referentna implementacija XChaCha20-Poly1305 secretstream.
|
||
* [`msgpack`](https://msgpack.org/) – serijalizacija zaglavlja.
|
||
|
||
## Reference
|
||
|
||
- [Ekstrakcija šifrovanih arhiva Synology – Synacktiv (Pwn2Own IE 2024)](https://www.synacktiv.com/publications/extraction-des-archives-chiffrees-synology-pwn2own-irlande-2024.html)
|
||
- [synodecrypt na GitHub-u](https://github.com/synacktiv/synodecrypt)
|
||
- [patology na GitHub-u](https://github.com/sud0woodo/patology)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|