WIP: Golden Axe 2 security obfuscation bypass.

PCB problems and fixes
Post Reply
Asure
Posts: 573
Joined: April 17th, 2013, 5:16 pm
Location: Netherlands
eBay: asure_nl

WIP: Golden Axe 2 security obfuscation bypass.

Post by Asure »

Soon i will be releasing a set of roms to bypass a broken security daughter card on your Golden Axe 2.
As a proof of concept, i started to look into this a few days ago, and it turned out really easy.
Sega used a very lazy assembler, programmer, QA checker and what have you. Read below to find out how botched up the Golden Axe 2 release was..

I did this in October, around the 10th, and shared the info with a few people. On oct 21st, the info ended up on TCRF.net.
Maybe a coincidence. Whoever posted there please come forward where you found this. (Rabidrabid, who are you?)

Roms will be released around christmas, just like i did last year with the Espgaluda score save mod. Have patience :)

Preface
Let's explain a bit about GA2 and security the daughter card. It has a NEC V25 cpu on it, some ram, a rom (already dumped) and sits on the bus. It is designed to stop bootleggers. Sega had lots of games heavily bootlegged, and they lost revenue because of this. Previous platforms have battery backed 68K main cpu's with encryption tables that helped deter bootleggers for a looong time. Some of the System32 games have FD1149 solutions on them which today are still not fully understood. What went wrong with Golden Axe 2? It is a top-tier title with a strong IP that should be properly protected, right?

Bootup
The main cpu can 'talk' to the daughter card by shared ram. When the game boots, maincpu and secure v25 cpu start up. The game waits for some magic string to appear in RAM otherwise the main cpu code will stay in a loop. Other than that, there is also some sprite data reading from shared ram. If the daughter card dies, the game won't start. If you bypass the magic string check, the sprites will be looking like they are on LSD. Seems decent enough right?

Flaws
- Main cpu code not encrypted.
- Expected string can be seen in main cpu code roms. (oops.)
- Expected palletes may be guessed or even brute forced.
- Hardware emulation in 1992 could have seen the content of the encrypted cpu ram..

The attack
The game is fully emulated in MAME for a long time. Source code is available. The game wants a 'WAKE UP! ...' string or it won't boot.
The secure cpu is also fully emulated. There is just some simple opcode obfuscation going on, nothing serious. (first obvious sign of lazyness: Obfuscation is not security.)
I started to look at the ram space for the encrypted cpu to see what the game put there, and what the security cpu was doing. It soon became clear this was going to be a boring job.

- The security cpu creates a page of static data in the shared ram.
- Nothing ever changes in this shared ram.
- Then it sits there idle. Doing nothing.

This could be easier than i thought.

Stupid assembler
I went to look at the rom to see if i was missing any code that the security board might jump to in special cases. There could be some triggers or events i had missed in the main cpu.
Disassembling the obfuscated rom would allow me to see any such hidden surprises. I was really hoping for somekind of a surprise. But not like what i found.
I saw a big issue. Sega had used an assembler that was super sloppy. It had produced a ROM and filled the emptyness with 'random data' from the pc/disk/ram.
Except, it had picked the source code of the V25 encrypted program. Not scrambled. Nicely formatted too.

Code: Select all


;------------------------------------------------------------------------------
;	SFR INITIAL
;------------------------------------------------------------------------------

INIT	PROC

_INIT:
	mov	aw,0
	mov	ds0,aw
	mov	aw,0ff00h
	mov	ds1,aw
	mov	cw,9
	ldea	ix,ITDT
INITLP:
	mov	iy,word ptr ds0:[ix]
	mov	dl,byte ptr ds0:[ix+2]
	mov	byte ptr ds1:[iy],dl
	add	ix,4
	dec	cw
	bnz	INITLP
	RET

INIT	ENDP


;------------------------------------------------------------------------------
;	V25 read/write check
;------------------------------------------------------------------------------

RW22	PROC

_RW22:
	mov	ch,byte ptr ds1:[ix+1]
	cmp	ch,20h				; V25 r/w start ?
	bne	_RW22

	mov	bw,8				; counter offset (0008h)
	mov	dh,byte ptr ds1:[ix+6h]		; add data
	mov	dl,byte ptr ds1:[ix+7h]		; write start data
LP_22:
	call	AD_SET

	mov	byte ptr ds1:[iy],dl		; RAM data write
	mov	cl,byte ptr ds1:[iy]		; RAM data read
	cmp	cl,dl
	bnz	R22_NG

	add	dl,dh
	inc	bw
	cmp	bw,7f0h				;stack area (10h) keep
	bnz	LP_22

	mov	ch,22h				; RAM OK data set
	call	SET_ON
	RET

R22_NG:
	mov	ch,2ah				; RAM NG data set
	call	SET_ON
	RET

RW22	ENDP


;------------------------------------------------------------------------------
;	V25 read / V60 write check
;------------------------------------------------------------------------------

RW26	PROC

_RW26:
	mov	ch,byte ptr ds1:[ix+1]
	cmp	ch,4fh				; V60 write end ?
	bne	_RW26

	mov	bw,8				; counter offset (0008h)
	mov	dh,byte ptr ds1:[ix+6h]		; add data
	mov	dl,byte ptr ds1:[ix+7h]		; write start data
LP_26:
	call	AD_SET

	mov	cl,byte ptr ds1:[iy]		; RAM data read
	cmp	cl,dl
	bnz	R26_NG

	add	dl,dh
	inc	bw
	cmp	bw,7f0h
	bnz	LP_26

	mov	ch,44h				; RAM OK data set
	call	SET_ON
	RET

R26_NG:
	mov	ch,4ah				; RAM NG data set
	call	SET_ON
	RET

RW26	ENDP


;------------------------------------------------------------------------------
;	V60 read / V25 write check
;------------------------------------------------------------------------------

RW62	PROC

_RW62:
	mov	ch,byte ptr ds1:[ix+1]
	cmp	ch,50h				; before result write end ?
	bne	_RW62

	mov	bw,8				; counter offset (0008h)
	mov	dh,byte ptr ds1:[ix+6h]		; add data
	mov	dl,byte ptr ds1:[ix+7efh]	; write start data
	mov	byte ptr ds1:[ix+7h],dl		; write start data
LP_62:
	call	AD_SET

	mov	byte ptr ds1:[iy],dl		; RAM data write
	add	dl,dh
	inc	bw
	cmp	bw,7f0h
	bnz	LP_62

	mov	ch,5fh				; write end code set
	call	SET_ON
	RET

RW62	ENDP





;------------------------------------------------------------------------------
;	arabian fight security routin
;------------------------------------------------------------------------------

WRITE_AXE	PROC

_RW_AXE:
	ldea	ix,PLCOL_AX
	mov	iy,0				;
	mov	cw,16				;loop count
loop:
	mov	dl,byte ptr ds0:[ix]
	mov	byte ptr ds1:[iy],dl
	add	ix,1
	add	iy,1
	dec	cw
	bnz	loop
	RET

PLAYCOL1	equ	0000000aH
PLAYCOL2	equ	00000011H
PLAYCOL3	equ	00000018H
PLAYCOL4	equ	0000001fH
ZANZOCOL1	equ	000000c5H
ZANZOCOL2	equ	000000c6H

PLCOL_AXE
	dw	PLAYCOL1		-- body color
	dw	ZANZOCOL1		-- zanzoh color
	dw	PLAYCOL2		-- body color
	dw	PLAYCOL2		-- zanzoh color
	dw	PLAYCOL3		-- body color
	dw	PLAYCOL3		-- zanzoh color
	dw	PLAYCOL4		-- body color
	dw	ZANZOCOL2		-- zanzoh color


WRITE_AXE	ENDP

;------------------------------------------------------------------------------
;	event security routin
;------------------------------------------------------------------------------

;000h~3ffh		write buff


;080h~0afh		(startup function work)

;400h~7ffh		read  buff


;------------------------------------------------------------------------------
;	start up function
;------------------------------------------------------------------------------

START_FUNC	PROC

_ST_FU:
	ldea	ix,MESS_ST
	mov	iy,080h				;start function write buff
	mov	cw,16*3				;loop count
loop_st:
	mov	dl,byte ptr ds0:[ix]
	mov	byte ptr ds1:[iy],dl
	add	ix,1
	add	iy,1
	dec	cw
	bnz	loop_st
	RET

		;0123456789abcdef	

MESS_ST	db	'wake up! GOLDEN '		;16 byte 1 group
	db	'AXE The Revenge '		;16 byte 1 group
	db	'of Death-Adder! '		;16 byte 1 group

START_FUNC	ENDP



;------------------------------------------------------------------------------
;	work ram clr
;------------------------------------------------------------------------------
WORK_RAM_CLR	PROC

_WO_RA:
	mov	iy,0000h			;work ram write adr.
	mov	cw,0400h			;loop count
	mov	dl,0000h
loop_wc:
	mov	byte ptr ds1:[iy],dl
	add	iy,1
	dec	cw
	bnz	loop_wc
	RET

WORK_RAM_CLR	ENDP

;------------------------------------------------------------------------------
;	RAM check result set routine
;------------------------------------------------------------------------------

SET_ON	PROC

_SET_ON:
	mov	byte ptr ds1:[ix+1],ch		; check result set
	mov	cl,byte ptr ds1:[ix+1]		; result set ok ?
	cmp	ch,cl
	bnz	_SET_ON

	RET

SET_ON	ENDP


;------------------------------------------------------------------------------
;	V25 address chenge & set routine	ix : 0
;						aw : chenge address
;						bw : address counter
;------------------------------------------------------------------------------

AD_SET	PROC

AST_LP:
	mov	byte ptr ds1:[ix+2],bl		; lower address set (10002h)
	mov	byte ptr ds1:[ix+3],bh		; upper address set (10004h)
	mov	cl,byte ptr ds1:[ix+2]		; lower set ok ?
	mov	ch,byte ptr ds1:[ix+3]		; upper set ok ?
	cmp	bw,cw
	bnz	AST_LP
	mov	iy,bw

	RET

AD_SET	ENDP

RMCK	ENDS


;------------------------------------------------------------------------------
;	data table
;------------------------------------------------------------------------------

RMCK	SEGMENT

	org	1000h

;xxf01=00	--pm0
;xxf02=00	--pmc0
;xxf09=00	--pm1
;xxf0a=08	--pmc1
;xxf11=00	--pm2
;xxf12=00	--pmc2
;xxfe8=00	--wtc
;xxfe9=00	--???
;xxfeb=00	--prc

ITDT	dw	0f01h,0,0f02h,0,0f09h,0,0f0ah,8,0f11h,0,0f12h,0
	dw	0fe8h,1001h,0fe9h,0,0febh,4ch

RMCK	ENDS


;------------------------------------------------------------------------------
;	reset vecter
;------------------------------------------------------------------------------

RMCK	SEGMENT

	org	0fff0h
	br	FAR PTR START

RMCK	ENDS


	END
ST_LP:
	mov	byte ptr ds1:[ix+2],bl		; lower address set (10002h)
	mov	byte ptr ds1:[ix+3],bh		; upper address set (10004h)
	mov	cl,byte ptr ds1:[ix+2]		; lower set ok ?
	mov	ch,byte ptr ds1:[ix+3]		; upper set ok ?
	cmp	bw,cw
	bnz	AST_LP
	mov	iy,bw

	RET

AD_SET	ENDP

RMCK	ENDS


;------------------------------------------------------------------------------
;	data table
;------------------------------------------------------------------------------

RMCK	SEGMENT

	org	1000h

;xxf01=00	--pm0
;xxf02=00	--pmc0
;xxf09=00	--pm1
;xxf0a=08	--pmc1
;xxf11=00	--pm2
;xxf12=00	--pmc2
;xxfe8=00	--wtc
;xxfe9=00	--???
;xxfeb=00	--prc

ITDT	dw	0f01h,0,0f02h,0,0f09h,0,0f0ah,8,0f11h,0,0f12h,0
	dw	0fe8h,1001h,0fe9h,0,0febh,4ch

RMCK	ENDS

-- Sprite table, from the assembly part:

07AF 73696E62617420202020        374     MESS_EV3        db      'sinbat          '              ;16 byte 1 group
     202020202020
07BF 72616D61796120202020        375                     db      'ramaya          '              ;16 byte 1 group
     202020202020
07CF 676F6C646F7220202020        376                     db      'goldor          '              ;16 byte 1 group
     202020202020
07DF 64617461202020202020        377                     db      'data            '              ;16 byte 1 group
     202020202020
07EF 20202020202020202020        378                     db      '                '              ;16 byte 1 group
     202020202020
07FF 20202020202020202020        379                     db      '                '              ;16 byte 1 group
     202020202020
080F 20202020202020202020        380                     db      '                '              ;16 byte 1 group
     202020202020
081F 20202020202020202020        381                     db      '                '              ;16 byte 1 group
     202020202020

So, whoever assembled this using uPD70320 Assembler V3.10 in SEC mode on 01 Sep 92 12:30:49 on a PC98 with nickname ARAMAWARI made no QA effort.
Also, another lazy sign: They re-used partial Arabian Fight routines, which could help de-obfuscate the sec cpu on that one, the emulation is not 100% on that game yet.

Work done so far:
- Moved the sprite table into ROM
- Bypassed security string
- Tested on real hardware (see here.)

Todo:
- Document the rom types if you want to convert say, F1 super lap.
- De-obfuscate the Arabian Fight sec board?
- Add AF sec emulation to MAME?
- Do the actual Xmas release :)

I wanted to play Titanfall 2 but wrote this damn wall of text.. :awe:
And yes, there's a similar situation in Arabian Fight's sec board rom, but there is a lot less source..
User avatar
Asayuki
Please Continue...
Posts: 431
Joined: August 29th, 2015, 10:16 pm
Location: Remuria, Germany

Re: WIP: Golden Axe 2 security obfuscation bypass.

Post by Asayuki »

First of all thanks for sharing this detailed insight (at the cost of your playing evening :) )
And LMAO for Sega's epic fail. Keep it coming, man!
OBTW, this belongs in the wiki ;)
My 15kHz cabinet Peplos will never power up, with any item, and I am quite proud of that.
User avatar
invzim
Posts: 472
Joined: August 17th, 2008, 5:26 pm
Location: Oslo, Norway
eBay: prrole

Re: WIP: Golden Axe 2 security obfuscation bypass.

Post by invzim »

Hey, that's a cool find! Great work!
I make and sell cool Arcade stuff, check out https://irkenlabs.com/ - In The Name of Science!
Post Reply