Exe d'essai qui saute l'ecran, licence retiree : toasts « Not found », impossible d'entrer. Le 404 est le generique d'une route inexistante, donc aucun indice qu'une verification de licence existe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Système de licences — scénario d'essai
Écrit le 2026-09-05, après la séance qui a posé la vérification hors ligne, le liage au poste et l'écran d'activation.
Ce plan ne cherche pas à montrer que ça marche : il cherche les endroits où ça casserait sans prévenir. Un système de licences échoue de deux façons opposées, et les deux coûtent cher — refuser un client qui a payé, ou ouvrir à quelqu'un qui n'a rien. Chaque essai ci-dessous vise l'une des deux.
Ce que la séance a déjà appris, et qui vaut d'être gardé en tête : l'empreinte du poste dépendait de l'ordre de démarrage. Selon que WMI répondait ou non, la même machine se présentait sous deux identités et refusait sa propre licence. Rien dans une utilisation normale ne l'aurait montré. D'où la série D.
Préparation
L'outil de remise à zéro : pose un fichier config.txt à côté de l'exe
(n'importe quel contenu, même vide). Un bouton rouge Deactivate (debug)
apparaît alors au bas de Settings → Licence : il efface la licence rangée et
rien d'autre. Sans config.txt le bouton n'apparaît pas, et la commande
sous-jacente est de toute façon inerte — un exe livré ne peut pas être
désactivé par ce chemin.
Ne supprime %LOCALAPPDATA%\PMServer\prefs.bin qu'en dernier recours : ça
désactive aussi, mais emporte le mode de déverrouillage, le nom retenu et les
réglages de sync.
Ce qu'il faut sous la main :
- ta licence valable, liée à ce poste ;
- l'Installation ID de ce poste (Settings → Licence, ou l'écran d'activation) ;
tools/licence.ps1et la clé privée.
Ordre : A → B → C → D → E. La série A établit l'état de référence ; les
suivantes le cassent volontairement.
A. Le chemin normal
- Coffre déjà activé, lancer l'application. À voir : l'écran d'activation n'apparaît pas. On tombe directement sur l'écran de connexion.
- Settings → Licence. À voir : Licensed to, Email, Issued et Installation ID remplis. Le nom affiché est celui que tu as tapé à l'émission — il vient de la charge utile signée, pas d'un réglage local.
- Fermer, relancer. À voir : toujours pas d'écran d'activation. C'est ce qui prouve que la licence est rangée et relue, pas seulement acceptée une fois.
B. Ce qui doit être refusé
Chaque essai part de l'écran d'activation (licence effacée).
- Chaîne quelconque : taper
nimportequoi. À voir : This licence key is not valid, en rouge. L'écran reste. - Licence tronquée : coller ta licence valable en retirant les dix derniers caractères. À voir : même refus. La signature ne tolère pas un octet.
- Charge utile trafiquée : prendre ta licence, changer un seul caractère dans la partie avant le point (le nom, l'adresse), coller. À voir : même refus. C'est l'essai qui prouve que le contenu affiché dans Settings ne peut pas être maquillé.
- Licence d'un autre poste :
coller le résultat. À voir : refus. C'est le cœur du liage — une licence parfaitement signée, mais pas pour cette machine.
tools\licence.ps1 -For "x@y.z" -Name "Autre" -Machine "AAAA-BBBB-CCCC-DDDD" - Licence d'une autre paire de clés :
coller le résultat. À voir : refus. C'est le cœur de la signature — la bonne machine, la bonne forme, mais pas ta clé. Si cet essai passait, n'importe qui pourrait fabriquer des licences. Puis supprimer
tools\licence.ps1 -Init -KeyFile "%TEMP%\faux.key" tools\licence.ps1 -For "x@y.z" -Name "Faux" -Machine "<TON ID>" -KeyFile "%TEMP%\faux.key"%TEMP%\faux.key. - Ta vraie licence, pour finir. À voir : l'écran disparaît, on passe à la connexion.
C. Ce qui ne doit PAS être refusé
Le risque symétrique, et le plus coûteux commercialement.
- Coller ta licence avec des espaces avant et après (une sélection à la
souris en attrape presque toujours).
À voir : acceptée. Le code fait
Trim. - Coller ta licence avec un retour à la ligne collé au bout. À voir : acceptée.
- Après activation, redémarrer la machine (pas seulement l'application).
À voir : toujours activée. Le port du serveur change à chaque
lancement — si la licence avait vécu dans
localStorage, elle serait perdue ici. C'est l'essai qui prouve le stockage DPAPI.
D. L'empreinte du poste — la série qui a déjà attrapé un défaut
- Noter l'Installation ID dans Settings → Licence.
- Fermer, relancer, relire. À voir : exactement le même. Un seul caractère de différence, et toutes les licences de cette machine tomberaient au prochain lancement.
- Relancer cinq fois de suite, en laissant la machine chargée (ouvrir quelques applications) pour varier les temps de démarrage. À voir : le même à chaque fois. C'est le défaut corrigé le 2026-09-05 : l'empreinte dépendait de l'initialisation de COM par WebView2, donc de la vitesse de démarrage.
- Démarrage à froid : redémarrer Windows, lancer l'application en premier. À voir : le même.
E. La portée de l'activation
- Autre compte Windows sur la même machine : ouvrir une session différente, lancer l'application. À voir : l'écran d'activation réapparaît, avec le même Installation ID. Comportement voulu : la licence est rangée par utilisateur (DPAPI), l'empreinte est celle de la machine. Ta licence y sera acceptée.
- Copier l'exe dans un autre dossier et le lancer. À voir : toujours activée. La licence ne vit pas à côté de l'exe.
- La mise à jour — le cas qu'on vivra réellement. Remplacer l'exe d'une installation existante par une nouvelle version, lancer. À voir : toujours activée. C'est l'essai le plus utile de la série : si une mise à jour désactivait, il faudrait réémettre une licence à chaque livraison, et on ne s'en apercevrait qu'au premier client mécontent.
Résultat de la première campagne — 2026-09-05
A B C D E2 E3 passés. Rien à corriger : la campagne n'a rien
trouvé, ce qui n'était pas acquis — la séance qui l'a précédée avait déjà sorti
trois défauts (empreinte dépendante de l'ordre de démarrage, message d'erreur en
cyan au lieu de rouge, licences flottantes acceptées).
E1 (autre compte Windows) n'a pas été joué — faute d'un second compte sous
la main. Ce que le code dit qu'il donnerait : écran d'activation de retour, même
Installation ID, licence acceptée telle quelle. À éprouver le jour où un client
le signale, ou avant de vendre à quelqu'un qui a plusieurs sessions.
Deux observations de la campagne, gardées parce qu'elles se reproduiront :
C3a été plus probant que prévu. Le port avait été changé à la main entre les deux lancements (8766 → 51812), donc l'origine du navigateur a réellement changé — exactement ce que l'essai veut prouver, mais pour de bon.- Un port éphémère dans le journal sans ligne de repli n'est pas un défaut :
c'est
port=0ou unconfig.txtabsent. Le repli, lui, écrit toujours « Port N unavailable » avant de se déplacer.
F. La deuxieme couche, la premiere sautee — 2026-09-16
Ne rien rapiecer : ignorer l'ecran completement et interroger l'API en direct, comme quelqu'un qui aurait saute la 1re couche. Meme requete, licence active puis retiree.
Preparation : config.txt a cote de l'exe avec port=8799,
require_token=false, require_process_check=false. Les deux derniers sont
indispensables — sinon le jeton ou le controle de processus repondent 404
AVANT la 2e couche, et l'essai ne prouve rien. A supprimer ensuite.
Deux pieges rencontres, qui fausseraient le resultat :
config.txtest lu depuis le dossier courant. Lancer l'exe d'ailleurs le prive de sa config : jeton et controle actifs, 404 partout, faux positif. Lancer avec le dossier de l'exe comme dossier de travail.- La 2e couche retient un « oui » pour la vie du processus. Fermer la
fenetre ne quitte pas (elle part dans la zone de notification) : relance =
reveil de l'ancien processus, qui repond encore
pong. Quitter par le menu de l'icone, verifier qu'aucune instance ne tourne, puis relancer.
Resultat :
| Requete | Licence active | Licence retiree |
|---|---|---|
GET /ping |
200 pong |
404 |
GET /entries, /settings, /folders |
— | 404 |
POST /register |
— | 404 — impossible de se creer un compte |
GET /index.html |
200 | 200 — l'ecran d'activation reste servi |
GET /nexiste-pas |
404 JSON | 404 JSON |
Observation : le refus de la 2e couche n'a pas un corps vide — Indy remplace
un ContentText vide par sa page 404 Not Found. Il se distingue donc d'une
route inexistante ({"error":"Not found"}), ce qui revele quelles routes
existent. Sans consequence en production (jeton et controle de processus
actifs), mais contraire au principe du verrouillage.
F bis. Meme essai, depuis l'application — 2026-09-17
L'essai F interrogeait l'API a la main. Celui-ci passe par l'application, avec
un exe d'essai compile avec LICENCE_TEST_SKIP_SCREEN : la 1re couche
repond toujours « licencie », comme si elle avait ete rapiecee. La 2e couche,
independante, verifie la vraie licence. (Construction : voir CLAUDE.md,
section de la deuxieme couche. Jamais livre.)
- Lancer l'exe d'essai, licence active : pas d'ecran d'activation, Register d'un compte de test reussit.
- Settings → Licence → Deactivate (debug), puis Quit par l'icone.
- Relancer : toujours pas d'ecran d'activation (1re couche « rapiecee »).
- Tenter d'entrer.
Resultat : toasts rouges « Not found », impossible d'entrer. Le message est le 404 generique, identique a celui d'une route inexistante — depuis le correctif du meme jour. Qui aurait rapiece la 1re couche voit une application qui ne marche pas, sans indice qu'une verification de licence existe.
Apres l'essai : reactiver la licence avec un exe normal — l'exe d'essai n'affiche jamais l'ecran d'activation.
Ce qu'aucun de ces essais ne prouve
À dire clairement, pour ne pas se croire protégé de ce qu'on ne l'est pas :
- Rapiécer l'exe pour sauter la vérification reste possible. C'est vrai de tout schéma hors ligne. La signature empêche de fabriquer des licences, pas de contourner le code qui les lit.
- Il n'y a pas de révocation. Une licence émise vaut pour toujours sur sa machine. La seule annulation possible est de régénérer la paire et de réémettre — ce qui casse toutes les autres.
- Le brouillage des blocs embarqués n'est pas du chiffrement. L'onglet Memory de Process Explorer, un débogueur ou la réponse HTTP rendent toujours le frontend en clair.
Le défaut à reconnaître sans le provoquer
Si $ObfSecret (BuildAssets.ps1) et AssetObfSecret (PM.EmbeddedAssets.pas)
divergent, la magie PMA1 tombe et le serveur refuse de servir :
/index.html en 404, fenêtre vide. Ce n'est pas une panne de licence, c'est
un désaccord de build. Symptôme à ne pas confondre.