Free Kick security module notes (C) 2011 Charles MacDonald ---------------------------------------------------------------------------- Module composition ---------------------------------------------------------------------------- The security module is a plastic box containing a PCB potted in epoxy. It connects to a game board through a 52-pin DIL header, the pin rows are 1.7" apart with the pins on .100" centers. The module label says: "NS6201-A 1987.10" "FREE KICK" The PCB has five chip dies (glob-top), a Fujitsu MB3771 reset generator in a SOIC package, and various SMT capacitors, resistors (several 1K ohm parts are visible), and three SOT-23 packages. Perhaps these are diodes to handle switching between the internal and external power supply. The function of the chip dies are thought to be as follows: #1 - Large die, ~80 pins. Gate array. Connects to most of the module's DIL pins. #2 - Small die, ~40 pins. Confirmed to be a CMOS Z80 CPU. Has many connections to die #1. #3 - Smallest die, unknown. Very close to die #4. Possibly work RAM. #4 - Large rectangular die. ~30 pins. Likely battery backed static RAM to store Z80 program code. #5 - Large rectangular die, ~30 pins. Static RAM. Likely battery backed static RAM to store Z80 program code. Identical in size to die #4. The memory is allocated like so: Program RAM: 64K powered by internal CR2032 (3.0V) battery This RAM is battery backed to retain the game program. Work RAM: 4K powered by external 1/2 AA (3.6V) battery. This RAM is battery backed to retain high scores. It's hard to determine how the memory is distributed across the chip dies, but one possible arrangement could be: Die #3 - 4K work RAM Die #4 - 32K program RAM (first 32K of 64K) Die #5 - 32K program RAM (latter 32K of 64K) Program RAM is write-protected. There must be a way to write to it as the security modules were programed after they were assembled, but the method to write to program RAM is not currently understood. The PCB has two sides but due to its compact size not all the signals can be fully routed. Instead of using wire links to make the remaining connections, two small PCBs are adhered to the top side with large pads around the vias that make contact with matching pads on the main PCB. ---------------------------------------------------------------------------- Module pinout ---------------------------------------------------------------------------- The lower 40 pins closely follow the pinout of a regular Z80 CPU: +----v----+ EXT_BAT(-)/GND |01 52| EXT_BAT(+) +5V |02 51| +5V GND |03 50| GND +5V |04 49| RSTOUT1# GND |05 48| RSTOUT0# GND |06 47| GND A11 |07 46| A10 A12 |08 45| A9 A13 |09 44| A8 A14 |10 43| A7 A15 |11 42| A6 CLK |12 41| A5 D4 |13 40| A4 D3 |14 39| A3 D5 |15 38| A2 D6 |16 37| A1 +5V |17 36| A0 D2 |18 35| GND D7 |19 34| ??? D0 |20 33| IACK# D1 |21 32| RSTIN# INT# |22 31| BUSREQ# NMI# |23 30| WAIT# GND |24 29| BUSACK# MREQ# |25 28| WR# IORQ# |26 27| RD# +---------+ - Pins 1, 52 connect to the external 3.6V battery that powers work RAM. - None of the ground or +5V pins are common. This could imply each pair powers a different component of the module independently. - RSTIN# is a reset input from a RC reset circuit on the Free Kick PCB. This circuit does not reset any of the other components on the game board. - RSTOUT0,1# may come from the MB3771 reset generator inside the module: RSTOUT1# is driven low as long as power is applied to the module from the +5V pins. It is not used by the game board. RSTOUT0# it used to reset several components on the game board. After power is applied to the board it is asserted for 6.31 seconds, then remains deasserted during normal operation. It is additionally gated by RSTIN#, and is asserted 9ms from the falling edge of RSTIN# and deasserted 3.92 seconds after the rising edge of RSTIN#. This gating behavior allows the RC reset circuit on the main board to reset the module via RSTIN#, which in turn resets components on the main board using RSTOUT0#. - IACK# is equivalent to !M1 & !IORQ. This provides an interrupt acknowledge cycle signal without having to expose the M1# signal. - Pin 34 would be RFSH# on a regular Z80. This pin appears to always be tri-stated and may be an input or an unused pin. - Pin 24 would be HALT# on a regular Z80. Here it is a ground input. It isn't clear why HALT# isn't available, but it is seldom useful. ---------------------------------------------------------------------------- Memory and I/O map ---------------------------------------------------------------------------- Memory control register I/O port $FF is a latch that can be read and written. Only the lower 3 bits are latched, and bits 7-4 return '1' when read. The latch is reset to zero after a power-up reset, and can be written to once to define a memory mode. Once it is written the value cannot be changed until the power is cycled again. The latch defines the size of the program RAM in units of 4K beyond address $7FFF. The work RAM is always mapped to D000-DFFF regardless of the program RAM size, and any remaining addresses not assigned to program RAM or work RAM can be used for external hardware such as DIP switches, sound chips, sprite and video RAMs, etc. The memory mode settings are as follows: Mode 0 0000-7FFF : Program RAM 8000-CFFF : External memory D000-DFFF : Work RAM E000-FFFF : External memory Mode 1 0000-8FFF : Program RAM 9000-CFFF : External memory D000-DFFF : Work RAM E000-FFFF : External memory Mode 2 0000-9FFF : Program RAM A000-CFFF : External memory D000-DFFF : Work RAM E000-FFFF : External memory Mode 3 0000-AFFF : Program RAM B000-CFFF : External memory D000-DFFF : Work RAM E000-FFFF : External memory Mode 4 0000-BFFF : Program RAM C000-CFFF : External memory D000-DFFF : Work RAM E000-FFFF : External memory Mode 5 0000-CFFF : Program RAM D000-DFFF : Work RAM E000-FFFF : External memory Mode 6 0000-CFFF : Program RAM D000-DFFF : Work RAM E000-FFFF : External memory Mode 7 0000-CFFF : Program RAM D000-DFFF : Work RAM E000-EFFF : Program RAM (additional 4K) F000-FFFF : External memory Going by the progression of program RAM ranges, it looks like modes 6 and 7 would have 4K of program RAM mapped to D000-DFFF. However the work RAM has higher priority and occupies D000-DFFF instead. As a result modes 5 and 6 function identically and the program RAM assumed to be at D000-DFFF is not accessible. Free Kick uses mode 5. Switching to mode 7 to expose the extra 4K of program RAM at F000-FFFF reveals garbage data, the kind you might get when RAM is not initialized. When the game program was written into the battery backed RAM at the factory, they may have only written in the first 52K and left the remaining program RAM undefined. That would explain this data. Counter Run also uses mode 5 and Lucky 74 uses mode 4. I/O port map Only the lower 8 bits of the address bus are used when decoding I/O port addresses. xx00-xxFE : Unused (can be mapped to external hardware) xxFF : Memory control register Inactive state The address, data, and control bus are inactive under the following conditions: - Reading or writing work RAM. - Reading or writing program RAM. - Reading or writing I/O port $FF. - During an opcode fetch from any address. - During an interrupt acknowledge cycle. The inactive state is as follows: Data bus : Tristated (weakly pulled high to $FF) Address bus : Set to $FFFF MREQ#, IORQ#, RD#, WR# : Held high (inactive) ---------------------------------------------------------------------------- Processor tests ---------------------------------------------------------------------------- Tests were performed to verify different aspects about the CPU: - Z180 instructions had no effect and functioned identically to their Z80 counterparts. (e.g. MLT BC was NEG) In addition the HD647180 has 16K mask ROM and 512 bytes of internal RAM which are not used by the game assuming they were present. This ruled out the possibility that the 80-pin die was a Z180 or HD647180. - The instruction "OUT (C), 0" output $FF instead. This confirms the CPU is CMOS. CMOS Z80s output $FF and NMOS Z80s output zero. Based on these results it seems likely a standard CMOS Z80 was used. ---------------------------------------------------------------------------- Reset behavior ---------------------------------------------------------------------------- After a reset the game checks for a 256-byte pattern in work RAM. If it exists the game preserves some work RAM contents such as the high score table. If the pattern does not exist the game does some additional setup such as copying a default high score list from program RAM to work RAM, and initializing RAM data specific to the regional distributor selected by the DIP switches. The game also checksums program RAM. If the checksum fails it prints a "PROGRAM ERROR" message to video RAM. Because the code that performs this test is located in program RAM, no message will be printed if the module's battery is dead or the program RAM is otherwise corrupted. ---------------------------------------------------------------------------- Security functions ---------------------------------------------------------------------------- Overview Apart from the physical security of having battery backed RAM stored in a potted module, several security functions were implemented: - Games read the memory control latch to see if the value they wrote matches what was read back. The software restarts itself if there is a mismatch. Bootlegs have this check patched, and to accommodate the patched code the checksum check is also patched out. - When the bus request feature is used, the program RAM, work RAM, and memory control register are not accessible. Amongst other things, this prevents the program RAM from being directly read out. - The M1# and RFSH# pins aren't available which prevents opcode fetches from being detected. - The address, data, and control busses are inactive during certain kinds of bus activity (described earlier). - Opcode fetches from the external memory area seems to fetch garbage data regardless of how the bus is driven. Vulnerabilities Non-maskable interrupts can be repeatedly triggered to cause a stack overflow, pushing the stack pointer down past address zero and wrapping back around to the external memory area at $F000-$FFFF. Once the game program executes a return instruction, the return address will be popped from the stack in external memory. A circuit that detects this type of read operation could provide a user-supplied return address to resume execution at an arbitrary offset in program RAM or work RAM. ---------------------------------------------------------------------------- Dumping method ---------------------------------------------------------------------------- A custom PCB that single steps the Z80 was used, pausing execution by entering a prolonged wait state each time the external memory range was accessed. The dumping procedure for Free Kick works as follows: 1. Reset the Z80 and execute the game until it sets up the stack pointer and writes to the PSG. During setup it also set the memory mode to $05, which is not shown in the listing. 0693 : ld sp, $E000 0696 : ld a, $9F 0699 : ld b, $04 069A : ld hl, $FC00 069D : ld (hl), a ; Break here 2. Trigger NMIs repeatedly to overflow the stack and wrap around from address zero back into the external memory area. The NMI handler looks like this: 0066 : push af 0067 : xor a 0068 : ld ($F805), a ; Break here and trigger another NMI The first instruction will always be executed. So when an NMI is triggered the Z80 will push PC and AF to the stack before accepting another one. Each NMI will decrease the stack pointer by four bytes. 3. Run the NMI handler until a return instruction is executed, and supply a specific return address in external memory. The program flow looks like this: 0066 : push af : 008C : call nz, $0482 : 0482 : ld (hl), $00 0484 : call $0540 : 0540 : ld hl, ($D170) 0543 : ld a, h 0544 : or l 0545 : ret ; Set to $0060 4. The code at $0060 pops data off the stack into several registers and executes a return instruction. This is used to set up a LDIR block transfer: 0060 : pop bc ; LDIR size; set to $1000 (4K) 0061 : pop hl ; LDIR destination; set to $E000 0062 : pop de ; LDIR source, set to $0000 0063 : pop af ; Value doesn't matter 0064 : ei 0065 : ret ; Set to $009F : 009F : ldir At this point the LDIR instruction copies the internal program RAM to the external memory space where the data can be logged. The process was repeated to dump the entire 52K program RAM in 4K blocks. A variant for step #1 is to start triggering NMIs after a reset, and wait for a write operation (stack push) to the desired external memory range. This removes the dependency on having the stack pointer initialized by the game program to a known value. ---------------------------------------------------------------------------- Bootlegs ---------------------------------------------------------------------------- The program ROM from bootleg games is a dump of the entire 64K Z80 address space, including the work RAM. The work RAM contains valid data from the demo play and attract sequences, including stack data, so a stack overflow technique was not used. After disassembling the security module you can see where the battery wires go, rather than crossing over the PCB they run parallel along the edges of the board. Once the location of these wires are known, it would be possible to remove the epoxy in specific areas to get access to the vias that correspond to the data bus without interrupting the power supply. With the data bus exposed, you could use the bus request feature and read each memory address sequentially, logging the value from the internal data bus that was tapped. I suspect the bootleggers might have done this to dump the game. Regardless of the technique they used, both Free Kick and Counter Run were dumped using the same method. Bootlegs use a small PCB that is pin compatible with the security module, but with only the lower 40 pins implemented. The PCB contains a RAM (the work RAM), an EPROM with a dump of the program RAM (actually an overdump containing the dumped work RAM as well), and a PAL or PROM depending on the manufacturer that does the address decoding and generates the IACK# signal. ---------------------------------------------------------------------------- Miscellaneous ---------------------------------------------------------------------------- A X-ray image confirms Lucky '74 uses the same security module as Free Kick. Counter Run, Lucky '74, and another variant of Free Kick are still not dumped. Please get in contact with me if you can provide the security modules from these games for dumping. ---------------------------------------------------------------------------- Credits and Acknowledgements ---------------------------------------------------------------------------- - Brian Troha for donating several Free Kick boards. - Kevin Eshbach for the depotted PCB scans. - Corrado Tomaselli for information about the Free Kick bootleg. - Gabriele for information about the Counter Run bootleg and ROM/PAL dumps. - Roberto Fresca for the X-ray image of the PCB. ---------------------------------------------------------------------------- End ----------------------------------------------------------------------------