Advanced OS disassembler and reverse-engineering tool.
Go to file
Dr-Carlos ac7f1eb073 _if: clang-format 2023-08-27 20:08:15 +09:30
base-library base-library: add minimal library example 2020-02-28 16:50:08 +01:00
include/fxos _ic: also print claims owned by provided address 2023-08-20 20:27:52 +02:00
lib _ic: also print claims owned by provided address 2023-08-20 20:27:52 +02:00
shell _if: clang-format 2023-08-27 20:08:15 +09:30
.clang-format Improve command classification 2022-04-15 06:09:18 +09:30
.git-blame-ignore-revs meta: ignore previous commit in git blame 2022-04-14 15:31:54 +01:00
.gitignore initial system: instruction load, target creation 2019-12-14 22:33:57 +01:00
CMakeLists.txt Improve command classification 2022-04-15 06:09:18 +09:30
README.md Update syntax in README 2022-12-04 21:40:57 +10:30

README.md

fxos

fxos is an extended disassembler specifically used to reverse-engineer the OS, bootcode, and syscalls of CASIO fx and fx-CG series. It used to be part of the fxSDK. If you have a use for fxos, then be sure to also check the Planète Casio bible, which gathers most of the reverse-engineering knowledge and research of the community.

If you're familiar with IDA, Ghidra, or other industry-grade reverse-engineering tools, then fxos won't be able to compete. This is more of a scripting playground with very OS-centric features for me. Some of the things it can do that usual tools might not do directly include:

  • Finding OS-specific data like bootcode/OS headers/footers, dates, versions
  • Computing and checking checksums
  • Analyzing syscall tables and consistently identifying syscall table entries
  • (TODO) Comparing functions across OS versions to find changes

On the other hand, there are no call graph, cross-references, or function type analysis (yet). I have plans for a simple abstract interpreter to bridge some of the gap between pure disassembly and decompilation.

fxos runs on Linux and should build successfully on MacOS. If there are compatibility issues with your favorite system, let me know.

Building

fxos is mainly standalone; to build, you will need the following tools. The versions indicated are the ones I use, and clearly not the minimum requirements.

  • g++ (9.2.0)
  • flex (2.6.4)
  • CMake (3.15) and make (eg. 4.2.1)

The only real configure option is the install path. CMake's default is /usr/local; a viable alternative is $HOME/.local.

% cmake -B build # -DCMAKE_INSTALL_PREFIX=$HOME/.local
% make -C build -j$(nproc) install

Setting up the library

fxos works with a library of files ranging from OS binaries to assembler instruction tables to scripts. The library is formed of one or more folders defined in the FXOS_PATH environment variable.

Folders in the path serve two purposes:

  • Any fxosrc file at the root of a folder is executed at startup.
  • All paths are interpreted relative to the FXOS_PATH.

Unless you want to redo the research by yourself, I suggest using shared community data from the fxdoc repository. New folders could be created easily on the same model; read the fxosrc script to see how it is structured.

Main concepts

fxos has a command-line interface kind of like rizin. Type ? to get a list of commands, and any command name followed by ? to get help on a particular command (eg. vc?).

The dot command . is used to run a script, which is a file with a series of fxos commands. This is used at startup to run every fxosrc script found in the FXOS_PATH.

Notations

  • Identifiers/names are C identifiers but dots (.) are allowed.
  • Usual decimal, hex (0x), binary (0b) values.
  • Syscalls are identified with %<hex>, such as %01e.
  • $ is the current position in the selected virtual space.
  • Commands accept arithmetic but only within parentheses; you can write e (1+2) but not e 1+2.
  • Ranges can be specified as <start>:<length> or <start>..<end>.
  • Paths should use quotes: "/os/fx/3.10/3.10.bin". Only identifiers/names can be written without quotes in commands.
  • Commands can be chained with ;.
  • Anything from a # to end of line is a comment.

Virtual spaces

A virtual space is an emulation of the calculator's virtual memory. Usually there is one for each OS being studied. Each virtual space has a number of bindings, which is a mapping from a virtual address to a file (usually a dump of the calculator's ROM or RAM). Use vl to show the virtual spaces and their bindings. The name of the current virtual space is shown in the prompt along with the current position, for instance:

cg_3.60 @ 0x80000000>

A new empty space can be created with vc, and then files can be mapped manually with vm. File paths are interpreted relative to FXOS_PATH folders even if they start with /.

Finally, the vs command is used to switch between different virtual spaces.

Symbols

Each virtual space can have symbols defined, which are names associated to either addresses or syscall numbers. ms will define a new symbol at an explicit address or syscall entry (which is kept symbolic, ie. it will work across different OS versions) and is lists all symbols for a virtual space.

File formats

Besides fxos scripts and the actual binary files being used, there is currently only one other type of data file: assembly instruction listings. See asm/sh3.txt for an explanation of the syntax; essentially each line has:

  • The opcode pattern, a 16-character string using 01nmdi.
  • A mnemonic.
  • Zero, one or two arguments among a finite set.

Here is an excerpt from the SH-4A extensions table.

type: assembly
name: sh-4a-extensions
---

0000nnnn01110011  movco.l r0, @rn
0000mmmm01100011  movli.l @rm, r0
0100mmmm10101001  movua.l @rm, r0
0100mmmm11101001  movua.l @rm+, r0
0000nnnn11000011  movca.l r0, @rn

Internally, fxos keeps a table with all 65536 opcodes and fills it with instances of instructions described in assembly tables.

(TODO) Disassembly listings are intended to be produced and maintained by fxos while still being edited by hand. In order for this to work properly, manual edits should only use #-comments, either at the start of a line or with a # symbol followed by a space (to distinguish from constants like #3):

# Set SR.BL = 1 (block interrupt) and SR.IMASK = 0x00*0 (error ?)
  4143a:       04 02           stc     sr,r4           # get SR register.
  4143c:       e5 10           mov     #16,r5          # r5 = 0x00000010

Contributing issues, results, and code

Any bug reports, issues and improvement suggestions are welcome. See the bug tracker.

If you have reverse-engineering results so share, the best place to do so is on the Planète Casio bible. Ping me or Breizh_craft on the Planète Casio shoutbox to have an SSH access set up for you.

PRs are also most welcome. Before submitting code, make sure to run clang-format to avoid any editor/configuration mishaps:

% clang-format -i include/**/*.h lib/**/*.cpp shell/**/*.cpp