Trace vector decoder
A Trace Vector Decoder (TVD) is computer software that uses the trace facility of its underlying microprocessor to decode encrypted instruction opcodes just-in-time prior to execution and possibly re-encrypting them afterwards. It can be used to hinder reverse engineering when attempting to prevent software cracking as part of an overall copy protection strategy.
Certain microprocessor families (e.g. 680x0, 80x86) provide the capability to trace instructions as a means to aid in program development. A debugger might use the trace flag to single step through a program, providing the means for a programmer to monitor the execution of the program under test. However, by writing a custom exception handler for the trace exception, it is possible to gain control of the machine between the execution of every instruction.
Tracing with the Motorola 68000
The Motorola 68000 has an instruction-by-instruction tracing facility.[1] When its trace state is enabled, the processor automatically forces a trace exception after each (non-exception) instruction is executed. It is possible to leverage this facility to install a trace vector decoder exception handler that decodes the upcoming instruction outside the exception as well as re-encoding the previously decoded instruction.
The following code snippet is an example of a program initializing a trace exception handler.
MOVEM.L Stack,D0-D7/A0-A6 ; Initialize registers MOVE.L #$4E730000,-(SP) ; Push trace exception handler on to stack MOVE.L #$00000010,-(SP) MOVE.L #$0004DDB9,-(SP) MOVE.L #$BD96BDAE,-(SP) MOVE.L #$B386B586,-(SP) MOVE.L #$D046D246,-(SP) MOVE.L #$0246A71F,-(SP) MOVE.L #$00023C17,-(SP) MOVE.W #$2C6F,-(SP) MOVE.L SP,($24).W ; Set trace exception handler vector ORI.W #$A71F,SR ; Enable trace state NOP ; CPU generates a trace exception after executing this NOP ;------------------------ ... ; Code from this line would be encrypted
The following is a disassembly of the above trace exception handler loaded on the stack. The purpose of this handler is to obfuscate any traced encrypted code. Its decryption process is affected by the contents of the condition code register (CCR). For example, an arithmetic operation in the main program having the 0 number as a result, will cause zero flag bit to be set in CCR. This will cause the value in (SP) to be changed in the trace exception handler.
TraceHandler: MOVE.L (2,SP),A6 ; Load return address from supervisor stack MOVE.W (SP),D6 ; Load condition codes of the main program AND.W #$A71F,D6 ADD.W D6,D0 ADD.W D6,D1 EOR.L D1,D6 EOR.L D2,D6 EOR.L D6,(A6) ; Decode 8 bytes ahead in main EOR.L D6,(4,A6) RTE ; Return from exception
Tracing with the Intel x86
The x86 CPUs provide a trace flag that generates an exception after the execution of each instruction. The following is an example of how this might be implemented.
TraceHandler proc far push bp mov bp, sp ; Gain access to return address push bx push ds ; Return address in DS:BX lds bx, 2[bp] ; Pointer to opcode of next instruction mov bx, [bx] ; Get current instruction's opcode ... ; Decode the opcode pop ds pop bx pop bp iret ; Return from interrupt
Examples
The Rob Northen Copylock system implemented on the Amiga, Atari ST and IBM PC platforms includes a TVD. In addition to software encryption, it is used to obfuscate the code that accesses and validates the copy protected disk.[2][3].[4]
References
- ^ "MC68000 16-Bit Microprocessor Advance Information" (PDF). Motorola Inc.
- ^ Kerr, Wayne (May 2004). "Amiga cracking – A look at basic TVD's". Flashtro. Retrieved 28 August 2020.
- ^ Sevalliu, Patrik. "Rainbow Islands". Computer Archeology. Retrieved 28 August 2020.
- ^ Furlough, Fabulous. "Rob Northen's Copylock". My life behind the patch.