christo / revenge

Reverse Engineering Environment for Retro-Programming
GNU General Public License v3.0
6 stars 1 forks source link
6502 c64 disassembler retrocomputing reverse-engineering vic20

Revenge

Reverse Engineering Environment

Project Status: pre alpha (it does work on the various binaries I'm currently testing with)

The idea is a web-based reverse engineering environment with very small initial goals: binary file type detection and simple disassembly of 6502 machine code for the Vic-20 and C64.

It's implemented in TypeScript as a first project for learning the language.

Beyond the small initial goals lies a vast land of unfulfilled wishes.

Quick Start

After checking out this repo, from a terminal shell in the root directory, run the sanity script to confirm you have the relevant tools installed:

./sanity.sh

Features

TODO

System Support Status

The design aims to reduce the effort of supporting multiple different systems, however at this stage only VIC-20 and C64 carts, prg files and BASIC files have been tested and there is no comprehensive test suite yet. Also, I'm not sure how feasible it would be to support some systems. Within the communities of each system, different assembler tool chains are more prevalent.

In general, project scope includes support for 6502-based and Z80-based 80s Microcomputers and a generous subset of the more common assembler syntax dialects. The following table shows estimations, not promises.

Machines Status CPU Family
VIC-20, C64 In Progress 6502
Apple II, BBC B Planned 6502
NES Probable 6502
ZX Spectrum Planned Z80
SNES ? 6502
Microbee, TRS-80 ? Z80
Oric, Atari 8-bit ? 6502
Gameboy series ? Z80*
VZ-200 / VZ-300 / Laser ? Z80

Design Notes

Machine language basic loaders often use base 10 data sequences of bytes. This is a low compression format. Higher radix formats can be used as strings, rem comments or some other transport format and the encoding of the instruction data can be a custom, variable-length compression format.

Peep-hole optimiser. See documented optimisations.

Patchy comprehensions - in a given disassembly, is the byte literal treated as a zero-page address? If so, or if it is a 16-bit address for, say, a load or store, is there some kernal symbol for that address or is it a JSR destination?

Run small trial executions in the background to score various areas as code or data. Detect code sequences that modify code (self-modifying code is harder to understand, although if the only change during simulation is to a memory address that is read from, and not thereafter jumped to or used as an index for a branch, signs point to likely separation between code and data).

Try to make this multipronged analysis somewhat automatic so the user can just confirm simple hunches or heuristic interpretations.

Pattern Recogniser and Macro Synthesiser

Canonicalisation

The canonical form of a piece of interpreted data enables divergent yet semantically equivalent forms to be recognised. In the case of character data, the canonical form might make the reverse form equivalent. In the case of code, the canonical form will have equivalences that, for example use the y register instead of the x register, all else being equal. Canonical forms for code may execute in a different number of cycles or use a different number of bytes or have instructions in a different order (some design is required to analyse alternate orderings with preservation of semantics). Canonicalisation is a form of program transformation where the goal is to identify use-case-specific essence.

Interactive Disassembly

While as much detection as possible is ideal, detection cannot be perfect and all designation options should be selectable by the user.

Assembly Dialects

Dialects should define equivalent alternative generation options for particular parts and the user can choose which suits the given part. Also, guesses should be smart.

A command line required to assemble the file in a given assembler should be provided in a comment at the top of the generated output (this implies the filename must also be specified). CPU designation and, system symbol imports etc. can only be specified on the command line or by environment variables on some assemblers as opposed to having assembler directives for them. While trying not to get into OS-specifics, command-lines are necessarily going to be OS-specific.

Within a dialect, different options may be selectable in a config form, so preferred output styling can be tweaked.

The disassembly of the C64 Kernal and friends

Assembler dialects being considered:

Vasm "Oldstyle"

Oldstyle is one of the supported dialects in vasm, Ben Eater's choice.

Some noteworthy features of Vasm "oldstyle":

Kick Assembler

Kick Assembler by Mads Nielsen is free, although closed source, it is free to use and it one of the most popular assemblers in the C64 community mostly for its rich scripting-language-like assembler directives and macros.

Others:

Common Dialect Variations

Assemblers may accept a lot of syntax beyond the minimum required for generating disassembly, for example, macros and includes. Ultimately it would be great to be able to synthesise macros from binaries, but at first, only the minimum necessary syntax may be supported.

Reverse Engineering Tools

Useful Resources

Reading List