Analyse protection cassette Loriciels
-------------------------------------

La protection cassette Loriciels est un chargeur protege qui a
ete employe sur une bonne partie des programmes vendus par cet
editeur francais. Il se reconnait aisement par la presence d'une
page ecran avec un petit chat.
A ma connaissance, il existe deux versions de cette protection.
Le petit laius qui suit vous donne des explications utiles sur 
le fonctionnement de cette protection pas ininteressante. 


Version 1
*********

L'etude ci-dessous a ete faite avec le jeu 3d-Fight, celebrissime
jeu de tir spatial !

Etape 1
-------
Lorsque l'on essaie de transferer ce jeu, on est de prime abord
confiant. La cassette contient deux fichiers "standards".

* un loader Basic protege.
* une routine binaire, dont la fonction est de charger un fichier
  sans en-tete qui est le "vrai" loader du programme.

Un desassemblage de la routine binaire confirme cette impression,
elle utilise le vecteur &BCA1, qui permet de charger en memoire
un fichier sans en-tete.

Probleme, lorsque l'on a transfere ces fichiers et qu'on essaie de
les utiliser, il ne se passe rien ! La routine contenue dans le
loader binaire n'est rien d'autre qu'un piege a couillon...

En etudiant de plus pres le chargeur Basic, on s'apercoit que ce
dernier contient des lignes cachees.

Ligne 20 : POKE &9FFF,55:POKE &9FFE,55
Ligne 35 : IF PEEK(&BC66)=&70 THEN CALL &B807+28 ELSE CALL &B11F+28

Faites les apparaitre avec les POKE suivants en mode direct :

POKE &170,10
POKE &192,9

Nouveau souci : les adresses appelees par ces lignes ne contiennent 
pas de code valide. Le loader doit donc exploiter une astuce pour 
faire en sorte qu'il y ait des instructions dans ces cases memoires.

Afin d'en etre sur, modifions le chargeur Basic en rajoutant
une ligne 31 comme suit (pour un CPC 664 ou 6128) :

31 FOR i=0 TO 70:POKE &BE80+i,PEEK(&B11F+28+i):NEXT:END

Une fois modifie, lancez-le et quand le loader binaire est charge,
desassemblez en &BE80. On obtient ceci :

BE80    F3              DI
BE81    01 E9 B0        LD BC,&B0E9   ; vecteur systeme ?
BE84    CD 65 BC        CALL &BC65    ; Init du MOS
BE87    21 68 90        LD HL,&9068
BE8A    11 36 03        LD DE,&336
BE8D    3E E0           LD A,&E0
BE8F    CD A1 BC        CALL &BCA1    ; vecteur systeme chargement
BE92    D2 00 00        JP NC,&0000   ; fichier monobloc
BE95    21 A0 90        LD HL,&90A0   ; adresse d'execution du loader
BE98    18 E8           JR &BE82        
BE9A    C3 E5 91        JP &91E5

Si on desassemble en &BE82, on trouve l'instruction suivante :

BE82    E9 B0           JP (HL)
	
Cela ressemble furieusement au programme binaire charge en xxxx, a ceci
pres que l'octet de synchronisation lors de l'appel de la routine &BCA1 est
different. Si on lance en mode direct la routine, ca marche !

D'ou viennent ces donnees ? Elles sont tout simplement stockees dans le header
du fichier "!". Pour vous en persuader, demarrez le TRANSFORMATEUR 3000 de 
chez MBC, et chargez l'editeur d'en-tetes K7.

Bien, nous savons donc maintenant charger correctement en memoire le loader 
principal. Il ne nous reste plus qu'a comprendre comment ce dernier 
fonctionne. Sans entrer dans les details, une rapide analyse permet de deviner
qu'il est facile a detourner, et qu'il contient toutes les informations dont
nous avons besoin pour sauvegarder sur disquette le programme charge. 

Nous avons :

en &9068 : l'adresse d'implantation du fichier charge
en &906A : la longueur du fichier charge
en &906C : l'adresse d'execution (codee) du fichier.
en &906E : le nom du fichier.

Pour sauvegarder le fichier une fois en memoire, il suffit de detourner la
routine decodant l'adresse d'execution (en &91D2). Pour le reste, sachez que 
le loader utilise directement des routines de chargement situees dans la ROM 
inferieure du CPC, dans la zone correspondant au MOS. Autre bizarrerie, le
petit chat n'est pas un sprite, mais bien une serie de caracteres redefinis !

Pour voir tout cela par vous meme, jettez un oeil sur le fichier LOADER1.TXT

Version 2
*********

L'etude ci-dessous a ete faite avec le jeu 3d-Sub, un jeu tres peu connu. 
Accrochez-vous, les explications ne sont probablement pas tres claires, mais
la protection est elle-meme assez tordue !

Contrairement au loader de type 1, le source LOADER2.TXT ne contient pas
une etude exhaustive du chargeur, car il s'avere beaucoup plus complexe et
evolue au cours de son execution.

Ce programme se compose d'un unique fichier binaire, habtuellement nomme
** LORICIELS ** sur la cassette l'utilisant.

Quand on commence a desassembler le programme, il apparait qu'il est code, car
rien ne ressemble a une routine de chargement cassette. Il faut donc passer
par une etude pas a pas du programme.

Apres quelques gentilles attentions, la protection apparait rapidement. La
methode utilisee repose sur du code automodifie. La routine en &7830 lit une
table dont chaque entree se compose de trois octets :

* Une valeur sur 2 octets correspondant a l'octet a modifier. Elle est 
  stockee dans le registre HL.
* Une valeur sur 1 octet correspondant a l'octet a poker en memoire. Elle
  est stockee dans le registre A.

Tout serait tres simple si la routine ne contenait pas en &7842 une commande
XOR decodant l'octet dans A. On ne peut donc pas 'voir' directement quelle
valeur sera au final mise en memoire, il faut faire le calcul.

Pour compliquer les choses, la routine en &8730 est elle-meme affectee par
ces modifications, soit en &7843 (valeur servant a decoder), soit en &7846
(saut vers le debut de la routine de decodage, ou ...).
A noter egalement qu'au bout d'un certain nombre de decodages, c'est carrement
l'ordre de la table lue qui change !

On a au debut du processus :

7833    LD H,(IX+&00)
7836    LD L,(IX+&01)

Apres la 16eme 'passe', la routine de saut pointe sur &7847, qui contient a
ce moment la un CALL vers &77C9. Celle routine modifie le code en &7833 comme
suit :

&7833   LD L,(IX+&01)
&7836   LD H,(IX+&00)

La question qui se pose est, comment decoder ce genre de programme ? 
La seule solution consiste a reproduire une routine identique ailleurs en 
memoire ou a detourner la routine existante. Il faut ensuite executer "pas
a pas" cette routine pour comprendre quelles sont les modifications effectuees
sur le code et leurs consequences. Je vous l'accorde, c'est tres chiant et
long a faire. On peut donc dire bravo au programmeur qui s'est fendu de cette
protection. Il a du passer pas mal de temps a se triturer les meninges pour 
arriver a ce resultat.

Notre homme a pourtant commis une maladresse qui rend le decodage un peu moins 
difficile que prevu, la table des adresses a poker n'est pas totalement codee.
On a tot fait de reperer les endroits ou la routine de decodage est modifiee
pour lancer l'execution d'une autre routine :

en &7851        
en &787E
etc...

La technique consiste alors a compter le nombre de tours ou la boucle de
decodage fait des modifications sans "sortir" vers une routine externe afin
de l'intercepter et d'avoir du code comprehensible en memoire.

Le detournement se fait avec une routine du style :

BE80    LD HL,&7851    ; debut de la table de code automodifie
BE83    LD B,&10       ; &10 = (&78781-&7851) / 3
BE85    PUSH BC
BE86    CALL &7833
BE89    POP BC
BE8A    DJNZ &BE85
BE8C    RET

On met un RET en &7845 et on lance la routine. On obtient alors en memoire
du code modifie, qu'il faut etudier. 

Bref, je vous fais grace du processus, la routine au final implante un loader
basee sur le vecteur &BCA1 en &0040, apres avoir fait une reinitialisation
des vecteurs systemes. Il n'est a priori pas possible de la detourner, mais,
enorme defaut, le loader final est toujours le meme, a l'octet pres, quel que
soit le programme protege. Une fois que l'on a reussit a isoler ce loader,
on peut s'en reservir les yeux fermes avec d'autres logiciels proteges de la
meme facon.

Les parametres utiles au chargement d'un logiciel sont implantes en &7944 et
ne sont meme pas codes. Il devient donc facile de creer un programme de 
transfert generaliste... 

A noter qu'on ne peut pas utiliser un simple logiciel capable de lire les
fichiers sans en-tete, car les fichiers sont codes. Voir a ce sujet le 
fichier LOADER2B.TXT, qui decrit la routine de chargement finale.

Petite surprise interessante, ce chargeur est capable d'executer du code 
BASIC. Cette particularite a ete utilisee pour le jeu REVERSI CHAMPION.
