hacktricks/src/hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md

163 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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}}