ARC6969 Pt. 1

Writing an emulator / disassembler

Description

The ARC6969 is an old and forgotten architecture used in a military computers during Cold War. Although we don't have the computers anymore, we got CPU manual and a few programs.

182KB
Open
manual_1.pdf
980B
Open
rom_1.bin

Solution

The idea behind this challenge is the same as that of the previous RISC 8bit CPU challenge. The extra difficulty stems from the increased number of instructions, I/O handling, and a more complex flag register.

Comparison

There are now 4 flags that can be set by the comparison instructions.

The first three are pretty straightforward. Note that for signed numbers, the MSB determines the sign (1 for negative, 0 for positive).

The overflow flag can be a bit tricky - one trick is to check the sign of the compared operands and the result. If both RxR_x and RyR_y have the same sign, but RxRyR_x-R_y yields a different sign, then an overflow has occurred.

I/O Devices

There are two I/O interfaces - a GPU and a serial interface.

It is given that the GPU display is 64 x 32. This is represented by a 2D array, where each element represents a pixel. The GPU is not yet needed for this challenge, so we'll touch up the display_screen() function in the next challenge. The serial I/O is pretty standard - we'll accept user input one byte at a time.

One last detail - since there are subtraction instructions, we have to handle the cases where the result becomes negative. Taking the lower 8 bits is the same as subtracting the result from 256.

Putting everything together, the full emulator script is as follows:

Running the program, we're prompted for 3 bytes of user input (the "key").

After entering the key, some scrambled text is printed.

This probably means our key is wrong. Hmm... let's reverse engineer the program to understand what's going on. Running the program again, this time uncommenting all the print statements, we can track the program's execution.

First, R4 is cleared by AND-ing with 0. Then, the three bytes of user input are stored in R1, R0 and R2 respectively.

I found that after receiving the 3 bytes of input, the program repeatedly performs the following loop:

We can now translate this to the following pseudocode:

We can see that the 3-byte key is essentially used to perform the addition, XOR, and subtration operations on each byte of the flag. The loop continues until all 31 bytes of the flag are printed.

Entering the key 0, 0, 0 gives us the "original" values. We can then bruteforce the key:

The flag is YauzaCTF{H3ll0_fr0m_1969_k1dd0}.

Last updated

Was this helpful?