Après la loooooooonnnngue introduction au défi de Déplombage Mode d'Emploi 4, il était bien évident que j'allais devoir revenir dessus pour un décorticage en règle. Alors oui, Kristo lui-même dans DEPME 5 en avait fourni une solution complète. On va donc prendre une voie différente de la sienne en Boot Traçant pour retrouver par nous-même les routines intéressantes. Cette approche est une nouvelle fois facilement utilisable car l'affichage de la page à signer ne se trouve pas très loin après le Boot du Disk. Allez c'est parti !

]CALL -151
 
*1600
 
; Le principe est toujours le même. On cherche le JMP vers le Boot1
; (la phase suivante). Il se trouve forcément en page 08.
; J'ai mis ici une bonne partie de cette page car il y a quelques petites
; choses à remarquer qui pourraient bien nous être utiles pour la suite :
 
0801-   E0 60       CPX   #$60
0803-   A9 62       LDA   #$62
0805-   20 8D 08    JSR   $088D ; à suivre !
0808-   A9 B6       LDA   #$B6
080A-   85 27       STA   $27
080C-   BD 8C C0    LDA   $C08C,X
080F-   10 FB       BPL   $080C
0811-   49 D5       EOR   #$D5
0813-   D0 F7       BNE   $080C
0815-   BD 8C C0    LDA   $C08C,X
0818-   10 FB       BPL   $0815
081A-   C9 AA       CMP   #$AA
081C-   D0 F3       BNE   $0811
081E-   BD 8C C0    LDA   $C08C,X
0821-   10 FB       BPL   $081E
0823-   C9 AD       CMP   #$AD
0825-   D0 EA       BNE   $0811
0827-   A9 00       LDA   #$00
0829-   A0 56       LDY   #$56
082B-   84 3C       STY   $3C
082D-   BC 8C C0    LDY   $C08C,X
0830-   10 FB       BPL   $082D
0832-   59 D6 02    EOR   $02D6,Y
0835-   A4 3C       LDY   $3C
0837-   88          DEY
0838-   99 00 03    STA   $0300,Y
083B-   D0 EE       BNE   $082B
083D-   84 3C       STY   $3C
083F-   BC 8C C0    LDY   $C08C,X
0842-   10 FB       BPL   $083F
0844-   59 D6 02    EOR   $02D6,Y
0847-   A4 3C       LDY   $3C
0849-   91 26       STA   ($26),Y
084B-   C8          INY
084C-   D0 EF       BNE   $083D
084E-   BC 8C C0    LDY   $C08C,X
0851-   10 FB       BPL   $084E
0853-   59 D6 02    EOR   $02D6,Y
0856-   D0 41       BNE   $0899
0858-   A0 00       LDY   #$00
085A-   A2 56       LDX   #$56
085C-   CA          DEX
085D-   30 FB       BMI   $085A
085F-   B1 26       LDA   ($26),Y
0861-   5E 00 03    LSR   $0300,X
0864-   2A          ROL
0865-   5E 00 03    LSR   $0300,X
0868-   2A          ROL
0869-   91 26       STA   ($26),Y
086B-   C8          INY
086C-   D0 EE       BNE   $085C
086E-   E6 27       INC   $27
0870-   A2 60       LDX   #$60
0872-   CE EE 08    DEC   $08EE
0875-   D0 95       BNE   $080C
0877-   20 D0 08    JSR   $08D0
087A-   A0 27       LDY   #$27
087C-   B9 A4 08    LDA   $08A4,Y
087F-   49 A0       EOR   #$A0 ; décodage du message texte d'accueil
0881-   99 00 04    STA   $0400,Y
0884-   88          DEY
0885-   10 F5       BPL   $087C
0887-   4C 00 B6    JMP   $B600 ; JMP vers le BOOT1
088A-   4C A9 FA    JMP   $FAA9
088D-   8D F4 03    STA   $03F4 ; octet de contrôle du Hi Reset
0890-   AD 51 C0    LDA   $C051
0893-   A9 00       LDA   #$00
0895-   8D F2 03    STA   $03F2 ; Vector RESET (Lo)
0898-   A9 C6       LDA   #$C6
089A-   8D F3 03    STA   $03F3 ; et Hi
089D-   2C 10 C0    BIT   $C010
08A0-   60          RTS

Bien on a trouvé le JMP vers le Boot1. Il faut donc shunter ce JMP $B600 pour reprendre la main juste avant. On modifie donc "notre" routine chargement Boot0 en RAM :

16F8 : 4C 10 17  ; on remplace le JMP $801 par un JMP $1710
 
; on place le patch qui viendra modifier le JMP $B600 une fois le Boot0 chargé
; en $800, patch qui nous fera sauter en $1720
 
1710 : A9 20 8D 88 08 A9 17 8D 89 08 4C 01 08
1720 : 4C 65 FF ; on récupère la main !

Et on garde dans un coin de notre tête les infos concernant le Vecteur de Reset. On pourrait en avoir besoin plus tard...
Et on continue :

*1600G ; on relance notre boot et on récupère la main
; après l'affichage du message texte
* B600L ; on regarde un peu ce que contient le Boot1
 
; note : j'ai supprimé dans la suite tous les NOP du code pour éclaircir un peu.
 
B600-   EE F4 03    INC   $03F4 ; à noter ! Concerne le Reset Vector
B603-   A9 00       LDA   #$00
B605-   8D 9A B7    STA   $B79A
B608-   AD E8 C0    LDA   $C0E8
B60B-   A9 20       LDA   #$20
B60D-   85 E6       STA   $E6
B611-   8D 52 C0    STA   $C052 ; plein écran
B614-   8D 54 C0    STA   $C054 ; page 1
B617-   8D 57 C0    STA   $C057 ; Hires
B61A-   8D 50 C0    STA   $C050 ; mode graphique
B631-   AD E9 C0    LDA   $C0E9
B634-   A9 46       LDA   #$46
B637-   8D 4F BA    STA   $BA4F
B63A-   A9 01       LDA   #$01
B63D-   8D 4B BA    STA   $BA4B
B640-   A9 00       LDA   #$00
B643-   8D 4C BA    STA   $BA4C
B646-   A9 00       LDA   #$00
B649-   8D 4D BA    STA   $BA4D
B64C-   A9 60       LDA   #$60
B64F-   8D 4E BA    STA   $BA4E
B652-   A9 00       LDA   #$00
B655-   8D 6B B6    STA   $B66B ; modification du $C600
B658-   A9 60       LDA   #$60
B65B-   8D 6C B6    STA   $B66C ; en $6000
B65E-   8D 51 C0    STA   $C051
B661-   20 6D B6    JSR   $B66D
B664-   8D E8 C0    STA   $C0E8
B667-   20 2F FB    JSR   $FB2F
B66A-   4C 00 C6    JMP   $C600 ; saut vers BOOT2
B66D-   AD 4B BA    LDA   $BA4B

On ne tombe bien sûr pas dans le panneau du JMP $C600. Il est modifié juste avant. On voit donc que le Boot2 se fera en $6000. On doit donc patcher cette modification ( !) pour pouvoir récupérer la main après le chargement du Boot2 :

*1720 : A9 65 8D 53 B6 A9 FF 8D 59 B6 4C 00 B6
*1720L
1720 : LDA #$65
1722 : STA $B653
1725 : LDA #$FF
1727 : STA $B659
172A : JMP $B600
 
*1600G ; on relance notre boot
*
*6000L ; et on inspecte le résultat :
 
6000-   20 1D 60    JSR   $601D
6003-   A9 00       LDA   #$00
6005-   85 6A       STA   $6A
6007-   20 67 60    JSR   $6067
600A-   20 CF 64    JSR   $64CF
600D-   20 80 64    JSR   $6480
6010-   20 54 64    JSR   $6454
6013-   20 9A 63    JSR   $639A
6016-   A9 00       LDA   #$00
6018-   85 FF       STA   $FF
601A-   20 10 7B    JSR   $7B10
601D-   A9 D5       LDA   #$D5
601F-   20 F4 F3    JSR   $F3F4
6022-   60          RTS

Arrivé à ce point, on sait que l'on n'est plus très loin. On doit encore passer l'intro et ensuite on aura l'affichage de notre fameuse page. On pourrait entrer dans chaque JSR pour voir un peu ce qu'il s'y passe. Mais c'est ici que doit agir le feeling, l'instinct du chasseur, le sixième sens du bidouilleur ! J'avoue que le mien, sur Apple II est un peu rouillé et finalement n'a jamais été très très affûté (mais j'y travaille...).
Par contre sur PC ayant un peu plus de bouteille par quelques longues années de tripatouillage d'Exe, j'ai finis par avoir quelques bons réflexes (et sur PC quand le code fait plusieurs kilo pour ne pas dire mega octets de longueur, y'a intérêt à pas trop se perdre).
Bref tout ça pour dire que face à ce genre de code, à savoir une suite de JSR vers des adresses relativement proches et finalement un JSR vers une adresse plus éloignée, quand on sait qu'il reste encore un gros passage avant ce qui nous intéresse (ça y est, ça fait tilt ?) et bien oui, on va directement vers l'adresse la plus éloignée ! De deux choses l'une, soit ce JSR arrive après affichage de notre cible (dans ce cas, on recommencera en prenant le JSR d'avant), soit il arrive avant et là on est généralement plutôt bon... Pragmatisme ? Empirisme ? Bourrinage ? Choisissez le nom que vous voulez...
Quoiqu'il en soit, concrètement que fait-on ? Et bien on y va franco :

*601A : JMP $FF59 !

On est en Boot2, plus besoin de notre routine en $1600 et des brouettes, le truc se démerde tout seul maintenant. J'ai utilisé le $FF59 plutôt que le $FF65 pour récupérer la main en mode texte et non pas à l'aveugle derrière une page Hires. N'oubliez pas les commutateurs les plus utiles dès qu'on tripatouille des programmes faisant appel au mode Hires pour pouvoir repasser d'un mode à l'autre :
C050 / C051 : Texte / Graphique
C052 / C053 : Plein Ecran / Mixte
C054 / C055 : Page 1 / Page 2
C056 / C057 : LoRes / HiRes
On peut les utiliser directement sous Monitor...

Voyons voir le résultat :

*6000G
*

Bingo ! L'intro se déroule sous nos yeux ébahis et on récupère la main juste avant notre défi !
J'attire aussi votre attention sur un point crucial : l'observation. Après le sens du chasseur, l'oeil de lynx  !
Il faut donc faire particulièrement attention à l'état du Disk. Face à un vrai Apple II, vu le bruit de la bête pas de souci, on le remarque. Face à un émulateur, c'est déjà plus discret. Prêtez donc attention à la petite loupiote verte sur AppleWin par exemple. Et que nous indique-t'elle ? En boot normal, on a le chargement de l'intro, nouveau chargement et apparition de l'image à signer.
Là on a récupéré la main juste après l'intro mais AVANT le chargement de ce qu'on peut supposer être l'image... Ce détail est particulièrement important pour la suite.
Bon inspection du résultat :

7B10-   A9 20       LDA   #$20
7B12-   8D 4F BA    STA   $BA4F
7B15-   A9 21       LDA   #$21
7B17-   8D 4B BA    STA   $BA4B
7B1A-   A9 00       LDA   #$00
7B1C-   8D 4C BA    STA   $BA4C
7B1F-   A9 00       LDA   #$00
7B21-   8D 4D BA    STA   $BA4D
7B24-   A9 40       LDA   #$40
7B26-   8D 4E BA    STA   $BA4E
7B29-   20 7D 7B    JSR   $7B7D

On aime bien les adresses en $BA00 souvent signe d'une RWTS. Ça tombe bien, à priori y'a une image à charger. Il est drôle ici de voir que ceux qui auront lu l'article Fast Boot Maker sur ce même DEPME IV, auront un certain avantage pour repérer les infos intéressantes. Ceux qui n'ont rien lu n'ont qu'à utiliser le sens du chasseur !
Que nous apprend (entre autre) cette doc :
Utilisation de la routine RWTS du FastBoot
BA4B : Piste
BA4C : Secteur
BA4D : Buffer Lo
BA4E : Buffer Hi
BA4F : Nombre Secteurs à charger.

Si on compare avec le code du dessus, je crois que tout est maintenant clair, le programme va donc charger à partir de :
Piste : $21 ($BA4B) - Secteur : $00 ($BA4C), $20 ($BA4F) secteurs vers $4000 ($BA4D/$BA4E).

Quand on sait que $4000 c'est le début de la page 2 Hires, que $20 c'est 32, la taille classique en secteur d'une image Hires, on se dit que finalement on tient le bon bout !
Vérifions un peu ce qui se passe dans le JSR qui suit :

*7B7DL
7B7D-   2C 54 C0    BIT   $C054 ; page 1 (pour qu'on ne voit pas ce qui se passe)
7B80-   2C E9 C0    BIT   $C0E9 ; drive on
7B83-   20 6D B6    JSR   $B66D ; appel RWTS
7B86-   2C E8 C0    BIT   $C0E8
7B89-   AD 05 40    LDA   $4005 ; tiens tiens !
7B8C-   C9 CC       CMP   #$CC  ; vérification de l'octet en $4005
7B8E-   4C B5 7B    JMP   $7BB5
 
*7BB5L
 
7BB5-   D0 D2       BNE   $7B89 ; on boucle si la valeur n'est pas OK !
7BB7-   4C E9 7B    JMP   $7BE9 ; sinon on va charger la suite du prog et RTS !

On sait déjà qu'un octet de la page Hires sera vérifié (avant tout décodage). Voyons voir la suite, on reprend après le JSR $7B7D :

7B2C-   A2 00       LDX   #$00
7B2E-   BD 00 7C    LDA   $A400,X
7B31-   9D 00 97    STA   $BF00,X
7B34-   E8          INX
7B35-   D0 F7       BNE   $7B2E
7B37-   CE 30 7B    DEC   $7B30
7B3A-   CE 33 7B    DEC   $7B33
7B3D-   AD 33 7B    LDA   $7B33
7B40-   C9 97       CMP   #$97
7B42-   D0 E8       BNE   $7B2C
7B44-   A0 00       LDY   #$00     ; décryptage
7B46-   B9 00 60    LDA   $4000,Y  ; de la page HIRES2
7B49-   59 01 60    EOR   $4001,Y  ; par EOR
7B4C-   4C 60 7B    JMP   $7B60
7B4F-   EA          NOP
7B50-   A2 DB       LDX   #$DB
7B52-   BD E5 7A    LDA   $7AE5,X  ; modifie $7BC0+
7B55-   49 A0       EOR   #$A0     ; par décodage
7B57-   9D E5 7A    STA   $7AE5,X  ; EOR
7B5A-   E8          INX
7B5B-   D0 F5       BNE   $7B52
7B5D-   4C 91 7B    JMP   $7B91
7B60-   99 00 60    STA   $4000,Y ;
7B63-   C8          INY
7B64-   D0 E0       BNE   $7B46
7B66-   EE 62 7B    INC   $7B62
7B69-   EE 4B 7B    INC   $7B4B
7B6C-   EE 48 7B    INC   $7B48
7B6F-   AE 62 7B    LDX   $7B62
7B72-   E0 60       CPX   #$60
7B74-   D0 D0       BNE   $7B46
7B76-   4C 50 7B    JMP   $7B50
7B79-   00          BRK
7B7A-   00          BRK
7B7B-   00          BRK
7B7C-   80          ???
7B91-   A2 2F       LDX   #$2F
7B93-   BD 51 9E    LDA   $9E51,X
7B96-   9D D0 03    STA   $03D0,X
7B99-   CA          DEX
7B9A-   10 F7       BPL   $7B93
7B9C-   A9 60       LDA   #$60
7B9E-   8D E4 9D    STA   $9DE4
7BA1-   8D E7 9D    STA   $9DE7
7BA4-   20 50 7C    JSR   $7C50
7BA7-   A9 6C       LDA   #$6C
7BA9-   EA          NOP
7BAA-   EA          NOP
7BAB-   EA          NOP
7BAC-   EA          NOP
7BAD-   EA          NOP
7BAE-   EA          NOP
7BAF-   A2 B7       LDX   #$B7
7BB1-   9A          TXS
7BB2-   4C 65 FF    JMP   $7BC0 ; saut vers partie décodée

Que se passe-t'il donc ici ? On rencontre pas mal de JMP. Je ne pense pas que le but véritable soit de compliquer le code mais tout simplement, il a bien fallu que Kristo et Godfather fassent tenir leur code de décryptage (et autres joyeusetés) dans le code par défaut d'un FAST BOOT. Ce qui explique que les instructions sont éparpillées et reliées entre elles par des JMP.

Pour simplifier :

- en $7B44+ : On a un décryptage par un EOR de la page Hires avec elle-même :
selon l'algo  : A = A EOR A+1 pour A de $4000 à $5FFF.
- en $7B50+ : On a un décryptage d'une zone de code. Pour voir ce qui s'y trouve il va donc falloir laisser le programme se décrypter et récupérer la main au moment où il saute en $7BC0 vers le code décrypté.
On modifie donc le $7BB2 en conséquence et on check ce qui doit se passer en $7BC0 :

*7BB2 : 4C 59 FF ; on patch le  JMP $7BC0
*7B10G ; on relance la routine
* ; et quand on récupère la main, on peut voir ce qui se passe en $7BC0 donc !
*7BC0L
7BC0-   A2 00       LDX   #$00 ; décryptage image part II
7BC2-   BD 00 40    LDA   $4000,X   ; EOR fixe avec $EA
7BC5-   49 EA       EOR   #$EA      ; pour tous les octets
7BC7-   9D 00 40    STA   $4000,X   ; de la page HIRES 2
7BCA-   E8          INX
7BCB-   D0 F5       BNE   $7BC2
7BCD-   EE C4 7B    INC   $7BC4
7BD0-   EE C9 7B    INC   $7BC9
7BD3-   AD C9 7B    LDA   $7BC9
7BD6-   C9 60       CMP   #$60
7BD8-   D0 E8       BNE   $7BC2
 
7BDA-   2C 55 C0    BIT   $C055		; Page 2 à l'affichage !
7BDD-   2C 10 C0    BIT   $C010		; attente
7BE0-   AD 00 C0    LDA   $C000		; d'une
7BE3-   10 FB       BPL   $7BE0		; touche
7BE5-   4C 20 7C    JMP   $7C20 	; sortie vers la suite

Et voilà, on y arrive. On a donc un nouveau décryptage de l'image avec cette fois :
B = B EOR $EA pour B de $4000 à $5FFF.

On a maintenant tout ce qu'il nous faut pour résoudre ce défi. Si si je vous assure...

Evidemment, avant de pouvoir signer l'image, il va déjà falloir commencer par la récupérer. Ici deux solutions :
- on sait où elle est sur le disque, on peut aller la lire en accès direct et faire un petit programme de décodage pour la décrypter et ainsi avoir une base pour la signature.
- on peut la récupérer dès maintenant à la hussarde ! Bah oui, le JMP $7C20 en $7BE5 a lieu quand tout est fini, il y a eu les deux décodages de l'image. Pourquoi ne pas coller un JMP $FF59 en $7BE5 et relancer en $7BC0 ?
Attention, n'oubliez pas les commutateurs dont je parlais plus haut car vous allez récupérez la main en page 2. Un C054 réglera le problème. Il ne reste plus alors qu'à booter un DOS 3.3 et à sauver l'image par un BSAVE PI.314116,A$4000,L$2000.
Vous avez bien entendu le droit de mettre un nom différent...

Une fois qu'on a l'image, on la signe avec un programme de dessin style Blazzing Paddles (d'où le PI. pour débuter le nom de l'image sinon B.P. ne retrouve pas ses petits !).

Et maintenant on va devoir créer le programme de codage inverse du double décodage utilisé par le défi, l'utiliser sur l'image, et replacer celle-ci sur le Disk, en accès direct bien sûr (cette fois, pas le choix).
<PUB> : n'oubliez pas qu'aussi bien pour la lecture que pour l'écriture, Accès Direct est à votre disposition ! (le monde est bien fait quand même...). </PUB>

Voici le source Merlin du programme de cryptage fait spécialement pour vous :

    1          ORG   $1500
    2
    3 BUF1     EQU   $06
    4 BUF2     EQU   $08
    5
    6          LDA   #$00
    7          STA   BUF1
    8          LDA   #$01
    9          STA   BUF2
   10          LDA   #$5F
   11          STA   BUF1+1
   12          STA   BUF2+1
   13
   14          LDX   #$20
   15 B1       LDY   #$FF
   16 B2       LDA   (BUF1),Y
   17          EOR   #$EA
   18          EOR   (BUF2),Y
   19          STA   (BUF1),Y
   20          DEY
   21          CPY   #$FF
   22          BNE   B2
   23          DEC   BUF1+1
   24          DEC   BUF2+1
   25          DEX
   26          BNE   B1
   27          RTS

Le cryptage se fait en une seule passe (le EOR A+1 et le EOR $EA sont groupés). De plus le programme une fois compilé reste entièrement relogeable par un BLOAD,A$xxxx car il utilise l'adressage indexé en page zéro, évitant ainsi des DEC d'adresses fixes.
Et comme d'habitude le source n'est pas commenté ! Mais après avoir suivi la résolution de ce défi, je pense que tout doit être clair...

Vous pouvez retrouver sur cette image DSK :
- le programme Accès Direct (DIRECT)
- l'image originale décryptée (enfin celle déjà signée par d'autres dont Captain Crack et Lot !) (PI.DEFI)
- l'image signée par mes soins (PI.SIGNED)
- l'image signée par mes soins recryptée (PI.CRYPTED)
- le programme CRYPT et son source Merlin
- le programme DECRYPT et son source Merlin
- des trucs effacés mais qu'on peut voir quand même avec DiskFixer !

Et bien sûr voici le DSK de DEPME 4 complet avec l'image nouvellement signée !

Un dernier petit mot sur le Reset Vector dont je parlais au début. Tous ceux adorant faire du CTRL+RESET à tour de bras auront noté que DEPME IV reboote irrésistiblement,  ne redonnant jamais la main.
On a vu que DEPME IV (en fait le FastBoot utilisé)  modifie les vecteurs lors du BOOT0 mais aussi lors du BOOT1, par un astucieux INC $3F4 !
Pourquoi astucieux ? Et bien je vais vous le dire... (oulà...)
Le Vector Reset se caractérise par 3 adresses en page 03 :
$3F2 : adresse Lo du vecteur
$3F3 : adresse Hi du vecteur
cela définit l'adresse sur laquelle foncera l'Apple quand vous ferez CTRL+RESET !
MAIS uniquement si $3F4 (l'octet de "contrôle") contient le contenu de $3F3 EOR $A5 !

Donc pour faire en sorte que DEPME IV vous rende la main après un CTRL+RESET, il faudra modifier directement avec un éditeur de secteur le Boot0 (Piste 0/Secteur 0 donc) pour y mettre :

P00:S00:93 : A9 69 (LDA #$69 ->$3F2)
P00:S00:98 : A9 FF (LDA #$FF ->$3F3)
qui  définit $FF69 en vecteur Reset

d'où (normalement) $FF EOR $A5 = $5A pour l'octet de contrôle !
Mais comme en $B600 cet octet sera incrémenté d'un, on va donc devoir mettre $5A-1 pour retomber sur nos pieds !
d'où :
P00:S00:03 : A9 59 (LDA #$59 -> $3F4)

Et voilà, vous devriez pouvoir interrompre ainsi DEPME à peu près quand vous voulez et reprendre la main !

Comme vous avez pu le remarquer, on peut très bien arriver à faire le défi sans avoir besoin de CTRL+RESET du tout. Mais cela peut éventuellement aider pour récupérer l'image décryptée sans même savoir où et comment elle l'a été !