feat(assets): brouiller les blocs embarques dans l'exe
Le frontend etait lisible dans l'onglet Image de Process Explorer, avec les commentaires. BuildAssets.ps1 brouille chaque fichier avant brcc32, PM.EmbeddedAssets le debrouille au moment de servir. C'est de l'opacite, pas du secret : la cle est dans l'exe. Ca supprime strings et l'onglet Image ; la memoire, un debogueur et la reponse HTTP rendent toujours le texte. D'ou XOR plutot qu'AES — a securite egale (nulle contre qui a l'exe), dix lignes, et aucune force affichee qu'on n'a pas. Une magie PMA1 prefixe le clair : sans elle, deux constantes qui derivent serviraient du binaire au navigateur, ecran blanc sans trace. Verifie en comparant les flux des deux cotes bloc par bloc, puis par aller-retour sur app.js, index.html et style.css. Le frontend ne se trouve plus dans le binaire. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,44 @@ Toute modif `index.html` / `js/` / `css/` nécessite :
|
||||
Sans étape 1, l'exe embarque l'ancienne version des assets — le bug le
|
||||
plus courant après modif frontend.
|
||||
|
||||
### Blocs embarqués brouillés
|
||||
|
||||
Depuis 2026-09-05, `BuildAssets.ps1` **brouille** chaque fichier avant de le
|
||||
donner à `brcc32` (dans `assets/obf/`, gitignoré ; les sources en clair ne sont
|
||||
jamais touchées) et `PM.EmbeddedAssets.DeobfuscateAsset` le débrouille au moment
|
||||
de servir.
|
||||
|
||||
```
|
||||
bloc i = SHA256( secret(32) || nom de ressource UTF-8 || i en 4 octets LE )
|
||||
sortie = XOR( magie 'PMA1' + contenu du fichier )
|
||||
```
|
||||
|
||||
- **C'est de l'opacité, pas du secret.** La clé est dans l'exe : qui tient le
|
||||
binaire retrouve le texte. Ce que ça supprime, c'est l'onglet *Image* de
|
||||
Process Explorer et n'importe quel `strings` — le frontend n'est plus lisible
|
||||
en survolant le fichier. L'onglet *Memory*, un débogueur ou la réponse HTTP le
|
||||
rendent toujours : WebView2 doit recevoir du JavaScript en clair pour
|
||||
l'exécuter. D'où **XOR plutôt qu'AES** : à sécurité rigoureusement égale
|
||||
(nulle, contre qui a l'exe), dix lignes au lieu d'un appel CNG, et surtout
|
||||
aucune force affichée qu'on n'a pas.
|
||||
- Le flux dépend du **nom de la ressource** : tous les fichiers commencent par
|
||||
les mêmes lignes de commentaire, un flux commun rendrait ces préfixes
|
||||
identiques d'un bloc à l'autre.
|
||||
- **La magie `PMA1` préfixe le clair.** Sans elle, une clé qui a dérivé entre le
|
||||
script et l'exe servirait du binaire au navigateur : écran blanc, aucune
|
||||
trace. Avec elle, `TryServeEmbedded` refuse. **Symptôme à reconnaître :
|
||||
`/index.html` en 404 juste après avoir touché `AssetObfSecret` d'un seul
|
||||
côté** — les deux constantes (`$ObfSecret` / `AssetObfSecret`) doivent rester
|
||||
identiques.
|
||||
- **Coût mesuré : 2,45 ms** pour les 820 Ko embarqués (AES chronométré comme
|
||||
borne haute ; le XOR est plus rapide), une seule fois au chargement de la
|
||||
page. À comparer aux ~650 ms d'Argon2id au déverrouillage.
|
||||
- **Les tests frontend ne sont pas concernés** : ils lisent les `.js` sur le
|
||||
disque, jamais le `.res`.
|
||||
- Vérifié en comparant les flux des deux côtés bloc par bloc (ils doivent être
|
||||
identiques au bit près) puis en refaisant l'aller-retour sur `app.js`,
|
||||
`index.html` et `style.css`.
|
||||
|
||||
### Découpage frontend (§3.1, en cours)
|
||||
|
||||
`app.js` (~12k lignes) est **progressivement scindé** en fichiers classic-script
|
||||
|
||||
Reference in New Issue
Block a user