prelimary support for decrypting and patching Holle bootloader

This commit is contained in:
4am 2019-02-09 23:51:41 -05:00
parent 0dab9cf097
commit 8ce6297ad1
9 changed files with 251 additions and 6 deletions

View File

@ -64,6 +64,10 @@
; set in IDBootloader() after reading T00,S00
FIRSTFILTER
;gIsHolle
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
;gIsMUSERWTS
!byte FALSE ; 0=true, 1=false
; reset before each operation

View File

@ -99,9 +99,10 @@ gIsPanglosDOS = gIsAdvent-$01 ; byte
gIsDavidson = gIsPanglosDOS-$01 ; byte
gIsRDOS13 = gIsDavidson-$01 ; byte
gIsMUSERWTS = gIsRDOS13-$01 ; byte
gIsHolle = gIsMUSERWTS-$01 ; byte
;LASTFILTER ; add new gIs* above this line
;gIsInfocom18 is a special case whose ID is not in the regular inspection path
gIsInfocom18 = gIsMUSERWTS-$01 ; byte
gIsInfocom18 = gIsHolle-$01 ; byte
;gIs13Sector is a special case whose ID is not in the regular inspection path
gIs13Sector = gIsInfocom18-$01 ; byte
;gMECCFastloadType is a special case integer whose default value cannot be #FALSE
@ -173,6 +174,7 @@ ConstructStandardDelivery = jConstructStandardDelivery
!warn "gIsPanglosDOS=",gIsPanglosDOS
!warn "gIsDavidson=",gIsDavidson
!warn "gIsMUSERWTS=",gIsMUSERWTS
!warn "gIsHolle=",gIsHolle
!warn "gIsRDOS13=",gIsRDOS13
!warn "gIsInfocom18=",gIsInfocom18
!warn "gIs13Sector=",gIs13Sector

29
src/id/holle.a Normal file
View File

@ -0,0 +1,29 @@
;-------------------------------
; IDHolle
; identify Dav Holle's encrypted bootloader
;
; in: $0800..$08FF contains T00,S00
; first page of track buffer also contains T00,S00
; out: C clear if Holle bootloader found
; C set otherwise
; all registers clobbered
; all other flags clobbered
;-------------------------------
!zone {
IDHolle
lda #$00
tax
ldy #(@searchend-@searchstart)
jsr compare ; if T00,S00,$00 ==
@searchstart
!byte $01
CLD
BIT $C081
LDA #$60
EOR $FF58
@hang BNE @hang
STA $03F3
SEI
@searchend
rts
}

View File

@ -286,6 +286,16 @@ IDBootloader
lda #s_rdos
jsr PrintByID
;
; Dav Holle encrypted bootloader
;
+ jsr IDHolle
bcs +
lda #s_holle
jsr PrintByID
lda #TRUE
sta gIsHolle
+
.useuniv
jmp UseUniversal

View File

@ -150,6 +150,7 @@ FirstMover
!source "id/advent.a"
!source "id/panglosdos.a"
!source "id/davidson.a"
!source "id/holle.a"
!source "print.a"
!source "compare.a"
!source "modify.a"
@ -842,6 +843,7 @@ _applyToAll
!source "patchers/rdosfmt.a" ; gIsRDOS13 only
!source "patchers/aacount.a"
!source "patchers/hallabs.a" ; T01 only
!source "patchers/holle.a" ; gIsHolle only
lda gPatchCount
beq .nopatches

194
src/patchers/holle.a Normal file
View File

@ -0,0 +1,194 @@
;-------------------------------
; #HOLLE
; encrypted bootloader hides an evil RWTS
;
; tested on
; - Sherwood Forest (Phoenix Software)
; - Mad Rat (Phoenix Software)
; - Masquerade (Phoenix Software)
; - Bats in the Belfry (Phoenix Software)
; - Bouncing Kamungas (Penguin Software)
; - Crime Wave (Penguin Software)
; - Thunder Bombs (Penguin Software)
; - The Spy Strikes Back (Penguin Software)
;-------------------------------
!zone {
bit gMode ; nothing to do here in verify-only mode
bmi +
- jmp .exit
+ bvc - ; nothing to do here in demuffin mode
lda gIsHolle
beq +
jmp .exit
+ lda gTrack
beq @DecryptBootloader
; TODO search for secondary RWTS here
; TODO search for secondary volume checks here
jmp .exit
@DecryptBootloader ; we've read the entire disk, now we're on track 0
jsr ReorderBuffer
ldy #(@decrypt1End-@decrypt1Start)
jsr SearchTrack; find decryption loop #1
@decrypt1Start
LDX #WILDCARD
- EOR $082D,X
STA $0110,X
DEX
BPL -
@decrypt1End
bcs @PatchBootloader
clc ; set up a decryption loop to simulate this one
adc #BASEPAGE
sta @decrypt1+2
sta @decrypt1_eor+2
inx
stx @decrypt1+1
inx
stx @decrypt1_eor+1
ldy #(@decrypt2End-@decrypt2Start)
jsr SearchTrack; find decryption loop #2
@decrypt2Start
LDX $082B
- EOR $0900,X
STA $0500,X
INX
BNE -
@decrypt2End
bcs @PatchBootloader
clc ; set up a decryption loop to simulate this one
adc #BASEPAGE
sta @decrypt2_load+2
sta @decrypt2_store+2
sta @decrypt2_eor+2
inx
inx
inx
stx @decrypt2_eor+1
lda #BASEPAGE
sta @decrypt1_load+2
sta @decrypt1_store+2
sta @decrypt2+2
lda #s_decryptrwts
jsr PrintByID
inc gPatchCount
lda #$4C
@decrypt1
ldx $FDFD ; simulate the decryption within the track buffer
@decrypt1_load
- eor $FD2D,x
@decrypt1_store
sta $FD2D,x
dex
bpl -
ldy #$03
@decrypt2
ldx $FD2B
@decrypt2_load
- eor $FD00,x
@decrypt2_store
sta $FD00,x
inx
bne -
inc @decrypt2_load+2
inc @decrypt2_store+2
dey
bne -
lda #$BD ; LDA abs,X opcode
@decrypt1_eor
sta $FDFD ; EOR -> LDA so now decryption loop #1 is just a copy loop
@decrypt2_eor
sta $FDFD ; EOR -> LDA so now decryption loop #2 is just a copy loop
@PatchBootloader
jsr ReorderBuffer
ldy #(@addressEpilogueEnd-@addressEpilogueStart)
jsr SearchTrack
@addressEpilogueStart
!byte $C9,WILDCARD
BNE +
CLC
RTS
+ SEC
RTS
@addressEpilogueEnd
bcs +
inx
ldy #$01
jsr modify ; normalize address epilogue 1st nibble
!byte $DE
+
ldy #(@dataPrologue3End-@dataPrologue3Start)
jsr SearchTrack
@dataPrologue3Start
EOR #$AD
!byte $D0,$E7
PHP
!byte $20
@dataPrologue3End
bcs +
inx
inx
inx
inx
ldy #$02
jsr modify ; disable CPU-burning JSR after data prologue
!byte $F0,$03
+
ldy #(@dataEpilogue1End-@dataEpilogue1Start)
jsr SearchTrack
@dataEpilogue1Start
!byte $C9,WILDCARD
!byte $D0,$9B
NOP
@dataEpilogue1End
bcs +
inx
ldy #$01
jsr modify ; normalize data epilogue 1st nibble
!byte $DE
+
ldy #(@dataEpilogue3End-@dataEpilogue3Start)
jsr SearchTrack
@dataEpilogue3Start
!byte $EB
!byte $D0,$86
@dataEpilogue3End
bcs +
inx
inx
ldy #$01
jsr modify ; ignore data epilogue 3rd nibble
!byte $00
+
ldy #(@diskVolumeEnd-@diskVolumeStart)
jsr SearchTrack
@diskVolumeStart
LDY $2F
@diskVolumeEnd
bcs +
ldy #$02
jsr modify ; don't use disk volume number to initialize data field checksum
LDY #$00
+
ldy #(@alternatingTrackEnd-@alternatingTrackStart)
jsr SearchTrack
@alternatingTrackStart
EOR $01
AND #$01
@alternatingTrackEnd
bcs +
ldy #$01
jsr modify
!byte $A9 ; EOR -> LDA so alternating track check always passes
+
jmp .exit
.reorderAndExit
jsr ReorderBuffer
.exit
}

View File

@ -126,7 +126,7 @@
;
bit gMode
bpl +
lda #s_protdosw
lda #s_decryptrwts
jsr PrintByID
+ ldx #BASEPAGE
inx

View File

@ -76,7 +76,7 @@ StringTable
!word .bcs08
!word .jmpb660
!word .protdos
!word .protdosw
!word .decryptrwts
!word .protserial
!word .fbff
!word .encoded44
@ -129,6 +129,7 @@ StringTable
!word .dakin5
!word .springboard
!word .hallabs
!word .holle
;
; Text can contain substitution strings, which
; are replaced by current values at runtime. Each
@ -354,7 +355,7 @@ StringTable
!text "the data prologue by jumping to $B660.",$8D,$00
.protdos
!text "T00,S01 Found encrypted RWTS, key=$%0",$8D,$00
.protdosw
.decryptrwts
!text "T00 Decrypting RWTS before writing",$8D,$00
.protserial
!text "T%t,S%3 Erasing serial number %0%1%2",$8D,$00
@ -475,4 +476,6 @@ StringTable
!text "the address epilogue",$8D,$00
.hallabs
!text "T%t,S%0 Found HAL Labs protection check",$8D,$00
.holle
!text "T00,S00 Found Holle bootloader",$8D,$00
}

View File

@ -62,7 +62,7 @@ s_lsr6a = $38
s_bcs08 = $39
s_jmpb660 = $3A
s_protdos = $3B
s_protdosw = $3C
s_decryptrwts =$3C
s_protserial = $3D
s_fbff = $3E
s_encoded44 = $3F
@ -115,4 +115,5 @@ s_13sector = $6D
s_dakin5 = $6E
s_springboard =$6F
s_hallabs = $70
STRINGCOUNT = $71
s_holle = $71
STRINGCOUNT = $72