Index du Forum
IDENTIFICATION SERVEUR : 10.0.97.129 - CLIENT : 54.224.166.141

 FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres   Groupes d'utilisateursGroupes d'utilisateurs   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 

Shanghai v1.1 IIgs (Activision, 1987)

 
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 2945
Localisation: Le Chesnay, France

MessagePosté le: Mer 04 Nov 2015, 17:29    Sujet du message: Shanghai v1.1 IIgs (Activision, 1987) Répondre en citant

We all know that "ancient" tile game. Published by Activision for the Apple IIgs, we also had Shanghai II with more variations and tiles.

We'll work with version 1.1 (there's a 1.1 sticker on the disk label) and the usage of the protection result is interesting, I think the crack is also Smile

Protection type
It is an Activision product. As usual, we have the eighth block which cannot be read. The protection check routine tries to read that block. If the result is an I/O error (#$27) then we have an original, otherwise we have a copy and the game quits... but not for this one!
Here, the result of the check routine is put in the accumulator: A=1 means original, A=0 means copy. The returned value is stored in a memory address and is used to determine the random seed.

With an original, the random seed is set by the number of ticks in the system. With a copy, the random seed is set to 1, always 1. That is a funny trick!

How to remove the protection
There are two possibilities:
1. You force A to be 1
2. You bypass the check of A

In both cases:
- Launch Block.Warden
- (P)refix /SHANGHAI/SYSTEM
- (F)ollow START

For option 1:
- offset $54: 22 -> AF (from JSL to LDAL)
- offset $79E4: 7A 78 -> A2 01 (from $787A to $01A2)
For option 2:
- offset $54: 22 -> AF (from JSL to LDAL)
- offset $4748: F0 -> 80 (from BEQ to BRA)

We'll discuss the reverse boot trace and the two options in the next messages.

Reboot and... enjoy,

LoGo
11/2015


Dernière édition par toinet le Lun 11 Jan 2016, 16:21; édité 1 fois
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 2945
Localisation: Le Chesnay, France

MessagePosté le: Mer 04 Nov 2015, 17:49    Sujet du message: Répondre en citant

We'll reverse boot-trace the code from the code that reads the I/O'ed block to the main calling address.

As usual, with the Activision titles, we either search for the 22 A8 00 E1 22 00 pattern (ProDOS 16 READ_BLOCK call) or with $C0EC. Here, we are lucky with the P16 call:

Code:

01/7F18: B09E                       BCS   $7EB8                                 
01/7F1A: AD4F7E                     LDA   $7E4F                                 
01/7F1D: F00A                       BEQ   $7F29                                 
01/7F1F: A9FF                       LDA   #$FF                                 
01/7F21: 8D2881                     STA   $8128                                 
01/7F24: A900                       LDA   #$00                                 
01/7F26: 8D2781                     STA   $8127                                 
01/7F29: C230                       REP   #$30                                 
01/7F2B: 22A800E1                   JSL   GSOS                                 
01/7F2F: 2200                       DW    $0022           ; READ_BLOCK         
01/7F31: 24810100                   ADRL  $00018124                             
01/7F35: C210                       REP   #$10                                 
01/7F37: E220                       SEP   #$20                                 
01/7F39: 08                         PHP                                         
01/7F3A: AD4F7E                     LDA   $7E4F                                 
01/7F3D: F003                       BEQ   $7F42                                 
01/7F3F: 20D480                     JSR   $80D4                                 
01/7F42: 28                         PLP                                         
01/7F43: F003                       BEQ   $7F48                                 
01/7F45: 8270FF                     BRL   $7EB8                                 


The entry point of the routine is at $7E54. We enter with the device number in A and the block number to read in Y.

Code:

01/7E54: 8D2481                     STA   $8124           ; device number       
01/7E57: 8C2A81                     STY   $812A           ; block number       
01/7E5A: 9C2C81                     STZ   $812C                                 
01/7E5D: 8E2E81                     STX   $812E                                 
01/7E60: A9357C                     LDA   #$7C35                               
01/7E63: 8D2681                     STA   $8126                                 
01/7E66: A97C01                     LDA   #>$7C35                               
01/7E69: 2900FF                     AND   #$FF00                               
01/7E6C: EB                         XBA                                         
01/7E6D: 8D2881                     STA   $8128                                 
01/7E70: C210                       REP   #$10                                 
01/7E72: E220                       SEP   #$20                                 
01/7E74: A900                       LDA   #$00                                 
01/7E76: 8550                       STA   $50                                   
01/7E78: 8552                       STA   $52                                   
01/7E7A: 8553                       STA   $53                                   
01/7E7C: 8A                         TXA                                         
01/7E7D: 2970                       AND   #$70                                 
01/7E7F: 4A                         LSR                                         
01/7E80: 4A                         LSR                                         


It is called at $7A8E with Y containing the value of $7C19 which is... 7. Good catch: the I/O'ed block number.

Code:

01/7A76: 20197A                     JSR   $7A19                                 
01/7A79: A90000                     LDA   #$0000                               
01/7A7C: 8D097C                     STA   $7C09                                 
01/7A7F: AD2B7C                     LDA   $7C2B                                 
01/7A82: 8D157C                     STA   $7C15                                 
01/7A85: AD317C                     LDA   $7C31                                 
01/7A88: AE337C                     LDX   $7C33                                 
01/7A8B: AC197C                     LDY   $7C19           ; block 7             
01/7A8E: 20547E                     JSR   $7E54           ; read block         
01/7A91: C230                       REP   #$30                                 
01/7A93: C90000                     CMP   #$0000                               
01/7A96: F003                       BEQ   $7A9B                                 
01/7A98: 82CD00                     BRL   $7B68                                 
01/7A9B: C210                       REP   #$10                                 
01/7A9D: E220                       SEP   #$20                                 
01/7A9F: 8B                         PHB                                         
01/7AA0: 68                         PLA                                         
01/7AA1: C230                       REP   #$30                                 
01/7AA3: 8502                       STA   $02                                   
01/7AA5: 8506                       STA   $06                                   


Going up brings us at a routine set at $787A which is the main protection check routine:

Code:

01/787A: 18                         CLC                   ; entry point         
01/787B: FB                         XCE                                         
01/787C: C230                       REP   #$30                                 
01/787E: 0B                         PHD                                         
01/787F: 8B                         PHB                                         
01/7880: DA                         PHX                                         
01/7881: 5A                         PHY                                         
01/7882: 228D7901                   JSL   $01798D         ; init protection     
01/7886: B014                       BCS   $789C                                 
01/7888: 20A178                     JSR   $78A1                                 
01/788B: 22627A01                   JSL   $017A62         ; check it           
01/788F: 48                         PHA                                         
01/7890: AD527E                     LDA   $7E52                                 
01/7893: 48                         PHA                                         
01/7894: A202112200                 _DisposeAll                                 
01/789B: 68                         PLA                                         
01/789C: 7A                         PLY                                         
01/789D: FA                         PLX                                         
01/789E: AB                         PLB                                         
01/789F: 2B                         PLD                                         


And the routine is called at... $F and the result is stored at $5D0F

Code:

01/0000: 4C0300                     JMP   $0003                                 
01/0003: 4B                         PHK                                         
01/0004: AB                         PLB                                         
01/0005: 7B                         TDC                                         
01/0006: 8D955C                     STA   $5C95                                 
01/0009: A2295D                     LDX   #$5D29                               
01/000C: A00100                     LDY   #^$5D29                               
01/000F: 227A7801                   JSL   $01787A         ; call protection     
01/0013: 8D0F5D                     STA   $5D0F           ; save result         
01/0016: 203000                     JSR   $0030                                 
01/0019: 201901                     JSR   $0119                                 
01/001C: 201302                     JSR   $0213                                 
01/001F: 20E203                     JSR   $03E2                                 
01/0022: 207346                     JSR   $4673                                 
01/0025: 22A800E1                   JSL   GSOS                                 
01/0029: 2900                       DW    $0029           ; Quit               
01/002B: 995D0100                   ADRL  $00015D99                             
01/002F: 6B                         RTL                                         
01/0030: AD34C0                     LDA   CLOCKCTL                             
01/0033: 8DAF5C                     STA   $5CAF                                 


Let's see where the $5D0F result is used:

Code:

01/4760: F40000                     PEA   $0000                                 
01/4763: F40000                     PEA   $0000                                 
01/4766: A203252200                 _GetTick                                   
01/476D: A204872200                 _SetRandSeed          ; set the random seed
01/4774: AD0F5D                     LDA   $5D0F           ; original?           
01/4777: C90100                     CMP   #$0001          ; means we have 1     
01/477A: F00D                       BEQ   $4789                                 
01/477C: F40000                     PEA   $0000           ; a copy, we have 0   
01/477F: F40100                     PEA   $0001           ; copy forces a fixed
01/4782: A204872200                 _SetRandSeed                               
01/4789: A02001                     LDY   #$0120                               
01/478C: 5A                         PHY                                         
01/478D: F40000                     PEA   $0000                                 
01/4790: A204862200                 _Random                                     
01/4797: 68                         PLA                                         
01/4798: 29FF00                     AND   #$00FF                               
01/479B: D003                       BNE   $47A0                                 
01/479D: A94D00                     LDA   #$004D                               
01/47A0: C99100                     CMP   #$0091                               
01/47A3: 9001                       BCC   $47A6                                 


That is why we must tell the program we have an original otherwise the random seed would be set to 1...


Dernière édition par toinet le Mer 04 Nov 2015, 17:53; édité 1 fois
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 2945
Localisation: Le Chesnay, France

MessagePosté le: Mer 04 Nov 2015, 17:52    Sujet du message: Répondre en citant

We'll first study the option 2 in two steps:
1. We bypass the call to the protection check
We replace the JSL $01787A with a LDAL $01787A

Code:

01/0000: 4C0300                     JMP   $0003                                 
01/0003: 4B                         PHK                                         
01/0004: AB                         PLB                                         
01/0005: 7B                         TDC                                         
01/0006: 8D955C                     STA   $5C95                                 
01/0009: A2295D                     LDX   #$5D29                               
01/000C: A00100                     LDY   #^$5D29                               
01/000F: AF7A7801                   LDAL  $01787A         ; call protection     
01/0013: 8D0F5D                     STA   $5D0F           ; save result         
01/0016: 203000                     JSR   $0030                                 
01/0019: 201901                     JSR   $0119                                 
01/001C: 201302                     JSR   $0213                                 
01/001F: 20E203                     JSR   $03E2                                 
01/0022: 207346                     JSR   $4673                                 
01/0025: 22A800E1                   JSL   GSOS                                 
01/0029: 2900                       DW    $0029           ; Quit               
01/002B: 995D0100                   ADRL  $00015D99                             
01/002F: 6B                         RTL                                         
01/0030: AD34C0                     LDA   CLOCKCTL                             
01/0033: 8DAF5C                     STA   $5CAF                                 


2. skip the fixed random seed.
We just replace the BEQ $4789 with a BRA $4789

Code:

01/4760: F40000                     PEA   $0000                                 
01/4763: F40000                     PEA   $0000                                 
01/4766: A203252200                 _GetTick                                   
01/476D: A204872200                 _SetRandSeed          ; set the random seed
01/4774: AD0F5D                     LDA   $5D0F           ; original?           
01/4777: C90100                     CMP   #$0001          ; means we have 1     
01/477A: 800D                       BRA   $4789                                 
01/477C: F40000                     PEA   $0000           ; a copy, we have 0   
01/477F: F40100                     PEA   $0001           ; copy forces a fixed
01/4782: A204872200                 _SetRandSeed                               
01/4789: A02001                     LDY   #$0120                               
01/478C: 5A                         PHY                                         
01/478D: F40000                     PEA   $0000                                 
01/4790: A204862200                 _Random                                     
01/4797: 68                         PLA                                         
01/4798: 29FF00                     AND   #$00FF                               
01/479B: D003                       BNE   $47A0                                 
01/479D: A94D00                     LDA   #$004D                               
01/47A0: C99100                     CMP   #$0091                               
01/47A3: 9001                       BCC   $47A6                                 
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 2945
Localisation: Le Chesnay, France

MessagePosté le: Mer 04 Nov 2015, 18:10    Sujet du message: Répondre en citant

Now, the option 1 which is trickier because we will play with the OMF segment (for more information, refer to the GS/OS reference, Addison-Wesley 55020, pages 441-480) with a focus on the cReloc record type on page 461.

1. We need to change the JSL with a LDAL

Code:

01/0000: 4C0300                     JMP   $0003                                 
01/0003: 4B                         PHK                                         
01/0004: AB                         PLB                                         
01/0005: 7B                         TDC                                         
01/0006: 8D955C                     STA   $5C95                                 
01/0009: A2295D                     LDX   #$5D29                               
01/000C: A00100                     LDY   #^$5D29                               
01/000F: AF7A7801                   LDAL  $01787A         ; call protection     
01/0013: 8D0F5D                     STA   $5D0F           ; save result         
01/0016: 203000                     JSR   $0030                                 
01/0019: 201901                     JSR   $0119                                 
01/001C: 201302                     JSR   $0213                                 
01/001F: 20E203                     JSR   $03E2                                 
01/0022: 207346                     JSR   $4673                                 
01/0025: 22A800E1                   JSL   GSOS                                 
01/0029: 2900                       DW    $0029           ; Quit               
01/002B: 995D0100                   ADRL  $00015D99                             
01/002F: 6B                         RTL                                         
01/0030: AD34C0                     LDA   CLOCKCTL                             
01/0033: 8DAF5C                     STA   $5CAF                                 


2. We change the cReloc of address $10...
2.1 We want to save a 1 in $5D0F. Where do we have a constant value of #$0001 in the code? We have one at $01A2.
2.2 Now, instead of JSL $01787A, we want LDAL $0101A2. How do we do? We change the cReloc linked to the JSL (now LDAL) $01787A.

We browse the OMF segment with Block.Warden. The OMF segment is stored after the code. As we have one segment of length $8166, the OMF segment is close to this address. Once we have it, we analyze the first entries that we must compare with the first lines of code.

If you look closely at the code above, the offsets to patch to match the address of the code in memory are:
- $0001 from the JMP $0003
- $0007 from the STA $5C95
- $000A from the LDX #$5D29
- $000D from the LDY #^$5D29
- $0010 from the JSL $01787A

So, what do we have the entries in the OMF segment?

Code:

F5 02 00 01 00 03 00 => Patch 2 bytes at offset $0001, set value $0003
F5 02 00 07 00 95 5C => Patch 2 bytes at offset $0007, set value $5C95
F5 02 00 0A 00 29 5D => Patch 2 bytes at offset $000A, set value $5D29
F5 02 F0 0D 00 29 5D => Patch 2 bytes at offset $000D, set value $5D29 with a bitshift
F5 03 00 10 00 7A 78 => Patch 3 bytes at offset $0010, set value $787A

The set value is relative to the program address in memory. The result is $0003 if the program starts at address $0000, or $0007 if it starts at $0004 (because $0004 + $0003 is $0007)

We will just change the above entry with:

F5 02 00 10 00 A2 01 => Patch offset $0001, set value $01A2


And now we have:

Code:

01/0000: 4C0300                     JMP   $0003                                 
01/0003: 4B                         PHK                                         
01/0004: AB                         PLB                                         
01/0005: 7B                         TDC                                         
01/0006: 8D955C                     STA   $5C95                                 
01/0009: A2295D                     LDX   #$5D29                               
01/000C: A00100                     LDY   #^$5D29                               
01/000F: AFA20101                   LDAL  $0101A2         ; get a #$0001     
01/0013: 8D0F5D                     STA   $5D0F           ; save result         
01/0016: 203000                     JSR   $0030                                 
01/0019: 201901                     JSR   $0119                                 
01/001C: 201302                     JSR   $0213                                 
01/001F: 20E203                     JSR   $03E2                                 
01/0022: 207346                     JSR   $4673                                 
01/0025: 22A800E1                   JSL   GSOS                                 
01/0029: 2900                       DW    $0029           ; Quit               
01/002B: 995D0100                   ADRL  $00015D99                             
01/002F: 6B                         RTL                                         
01/0030: AD34C0                     LDA   CLOCKCTL                             
01/0033: 8DAF5C                     STA   $5CAF                                 


We're done! Isn't that funny?
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1

 
Sauter vers:  
Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com