# EMU 1.0
**Category**: Emulation \**Points**: 462 \**Author**: trupples
## Challenge
Solved with NOT_MASTER08.
The EMU 1.0 digitisation project, lead in 2005 by Tahlia E., aimed toimmortalise the almost forgotten EMU 1.0 architecture's program collection.They did not fully succeed, and all their work fell to obscurity, but a naughtyelf got their hands on Tahlia's manual and a few of her programs. The currentissue is they can't find a working EMU 1.0 machine to actually run theprograms. Figure out how the computer worked and get the code running!
**Hint!** Don't get bogged down with the described details! You only need toemulate the overall behaviour of the instructions, not necessarily imitatetheir exact implementation. High-level emulation works as well.
## Solution
We are given `mandelbrot.rom` and a manual explaining how to build an emulatorto run it.
After building the [emulator](https://github.com/qxxxb/emu/), I tried to run the ROM.
```$ ~/Downloads/pypy3.7-v7.3.3-linux64/bin/pypy3 emu.py roms/mandelflag.rompygame 2.0.0 (SDL 2.0.12, python 3.7.9)Hello from the pygame community. https://www.pygame.org/contribute.html........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................,,,,,,,,,,,.............................................................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,.................................................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,........................................................................................,,,,,,,,,,,,,,,,,,,,,---,,,,,,,,,,,,,,,,,,,..................................................................................,,,,,,,,,,,,,,,,,,,,,,,,--~--,,,,,,,,,,,,,,,,,,,.............................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,--##------,,,,,,,,,,,,,,,,........................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----~#-~##--,,,,,,,,,,,,,,,,,...................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------~#~-----,,,,,,,,,,,,,,,,,,..............................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---#--#####~----,,,,,,,,,,,,,,,,,,,,.........................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---###########~#~---,,,,,,,,,,,,,,,,,,,......................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~###########~----,,,,,,,,,,,,,,,,,,,..................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------#############------,,,,,,,,,,,,,,,,,,..............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----~----------~###########~---------------,,,,,,,,,,..........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---###~~---#####################~###--------#--,,,,,,,,,.....................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---##################################~~-~##~~###,,,,,,,,,,.................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~##########################################-,,,,,,,,,,,............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------~#########################################--,,,,,,,,,,,,.......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~############################################~----,,,,,,,,,,,,...................,,,,,,,,,,,,,,,,,,,,,---------------------------~#############################################----,,,,,,,,,,,................,,,,,,,,,,,,,,,,,,,,,,,,--~#--------#~------------##################################################~-,,,,,,,,,,,.............,,,,,,,,,,,,,,,,,,,,,,,,,,---#~#~#---~###~-#-------~##################################################--,,,,,,,,,,,............,,,,,,,,,,,,,,,,,,,,,,,,,------~###############~---~#################################################---,,,,,,,,,,,,,.........,,,,,,,,,,,,,,,,,,,,,,,,,,-------~#################~~####################################################-,,,,,,,,,,,,,.........,,,,,,,,,,,,,,,,,,,,,,,,-------~#######################################################################---,,,,,,,,,,,,,.........,,,,,,,,,,,,,,,,,,,,,----~----~#########################################################################-,,,,,,,,,,,,,,,........,,,,,,,,,,,,,,,,,--------~############################################################################---,,,,,,,,,,,,,,,........,,,,,,,---------------#-~###########################################################################~---,,,,,,,,,,,,,,,,........##################################################################################################~-----,,,,,,,,,,,,,,,,........,,,,,,,---------------#-~###########################################################################~---,,,,,,,,,,,,,,,,........,,,,,,,,,,,,,,,,,--------~############################################################################---,,,,,,,,,,,,,,,........,,,,,,,,,,,,,,,,,,,,,----~----~#########################################################################-,,,,,,,,,,,,,,,........,,,,,,,,,,,,,,,,,,,,,,,,-------~#######################################################################---,,,,,,,,,,,,,.........,,,,,,,,,,,,,,,,,,,,,,,,,,-------~#################~~####################################################-,,,,,,,,,,,,,...........,,,,,,,,,,,,,,,,,,,,,,,,,------~###############~---~#################################################---,,,,,,,,,,,,,............,,,,,,,,,,,,,,,,,,,,,,,,,,---#~#~#---~###~-#-------~##################################################--,,,,,,,,,,,...............,,,,,,,,,,,,,,,,,,,,,,,,--~#--------#~------------##################################################~-,,,,,,,,,,,..................,,,,,,,,,,,,,,,,,,,,,---------------------------~#############################################----,,,,,,,,,,,......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~############################################~----,,,,,,,,,,,,..........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------~#########################################--,,,,,,,,,,,,...............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~##########################################-,,,,,,,,,,,...................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---##################################~~-~##~~###,,,,,,,,,,........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---###~~---#####################~###--------#--,,,,,,,,,............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----~----------~###########~---------------,,,,,,,,,,................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------#############------,,,,,,,,,,,,,,,,,,....................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------~###########~----,,,,,,,,,,,,,,,,,,,.......................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---###########~#~---,,,,,,,,,,,,,,,,,,,...........................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---#--#####~----,,,,,,,,,,,,,,,,,,,,...............................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------~#~-----,,,,,,,,,,,,,,,,,,....................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----~#-~##--,,,,,,,,,,,,,,,,,.........................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,--##------,,,,,,,,,,,,,,,,..............................................................................,,,,,,,,,,,,,,,,,,,,,,,,--~--,,,,,,,,,,,,,,,,,,,...................................................................................,,,,,,,,,,,,,,,,,,,,,---,,,,,,,,,,,,,,,,,,,.........................................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................................................................................................,,,,,,,,,,,,,,,,,,,,,,,,,,..............................................................................................................,,,,,,,,,,,.............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................HEYHEY KIDWANT SUM...FLAG?> MAYBE_3CP Z.G#7$[G[ND5~N#VEEHNI|Y```
After the mandelbrot is printed, I'm prompted for input.I didn't know what to type, so I wrote `MAYBE`.Apparently that was not the correct response, because I got some garbageprinted back.Looks like some kind XOR or ROT cipher.
Taking a look at the disassembly we see this:```asm0257:   LBL    1537, 00258:   IO     r1, SERIAL_INCOMING, r00259:   CMPUG  r1, 30260: - JUP    1537, r00261:   IO     r60, SERIAL_READ, r00262:   IO     r61, SERIAL_READ, r00263:   IO     r0, SERIAL_READ, r00264:   IO     r0, SERIAL_READ, r0```
The `SERIAL_INCOMING` device returns the number characters that can be read.We can see that it loops until more than 3 characters are buffered.Then it reads the first two characters and discards the next two.
Since only two characters are used, we can just bruteforce all possible bigramsinstead of reversing the encryption.
To do this, I saved the machine state using Python `pickle` after the mandelbrotwas printed. Then in a separate script, I repeatedly loaded the saved stateback and tried different inputs until the output contained `X-MAS`, the flagprefix.
```pythonwith open('emu_state.pkl', 'rb') as f:    emu = pickle.load(f)
for bigram in itertools.product(serial_dict, repeat=2):    payload = ''.join(bigram) + 'AA'    m = copy.deepcopy(emu)    m.out = io.StringIO()    m.buffer = payload    m.run()    output = m.out.getvalue()    print('{}: {}'.format(payload, output))```
Eventually it found it:```...Y{AA: ^AG$*=$MD[/G/ND5~N#VE4+HRX-Y}AA: }M8OW(V56IN1G1ND5~N#VEB4JJ#)Y#AA: X-MAS{EMU~L3G3ND5~N#VER_D1E}```
# Talkative
**Category**: Emulation \**Points**: 490 \**Author**: trupples
## Challenge
Now that you have an EMU 1.0 emulator, go make a network card and come chatwith us! \ \P.S. you don't need to implement the server card to get the flag
Target: `nc challs.xmas.htsp.ro 5100`
**Hint!** While you don't need to implement a server network card, to get theflag you still need to understand what the server does to your messages.
## Solution
I disassembled `talkative-server-redacted.rom` and annotated it:```asm000:   ADDI   r12, r0, 61001:   ADDI   r13, r0, 36002:   LBL    512, 0003:   ADDI   r1, r0, 2004:   IO     r0, ENET_CONN_CTRL, r1005:   IO     r1, ENET_INCOMING, r0006:   CMPUL  r1, 40007: + JUP    512, r0 # If we have less than 40 chars, keep reading
008:   ADDI   r50, r0, 62 # Store the first 4 chars (username?)009:   IO     r8, ENET_RECV, r0010:   IO     r9, ENET_RECV, r0011:   IO     r10, ENET_RECV, r0012:   IO     r11, ENET_RECV, r0013:   ADDI   r2, r0, 14
# Recv payload to registers r14 to r50 (exclusive)014:   LBL    513, 0015:   IO     r1, ENET_RECV, r0016:   ST     [r2+0], r1017:   ADDI   r2, r2, 1018:   CMPUL  r2, 50
# Print to username and payload020:   ADDI   r2, r0, 8021:   LBL    513, 0022:   LD     r1, [r2+0]023:   IO     r0, SERIAL_WRITE, r1024:   ADDI   r2, r2, 1025:   CMPUL  r2, 51026: + JUP    513, r0
027:   CMPEQ  r0, r0028: + CMPEQ  r24, 36 # Must pass all these checks029: + CMPEQ  r21, 36030: + CMPEQ  r40, 10031: + CMPEQ  r45, 21032: + CMPEQ  r11, 28033: + CMPEQ  r27, 29034: + CMPEQ  r23, 14035: + CMPEQ  r39, 22036: + CMPEQ  r34, 10037: + CMPEQ  r29, 14038: + CMPEQ  r14, 18039: + CMPEQ  r35, 23040: + CMPEQ  r43, 21041: + CMPEQ  r9, 22042: + CMPEQ  r8, 34043: + CMPEQ  r17, 18044: + CMPEQ  r18, 16045: + CMPEQ  r36, 36046: + CMPEQ  r47, 21047: + CMPEQ  r20, 29048: + CMPEQ  r44, 24049: + CMPEQ  r16, 22050: + CMPEQ  r15, 36051: + CMPEQ  r22, 11052: + CMPEQ  r38, 38053: + CMPEQ  r48, 24054: + CMPEQ  r26, 14055: + CMPEQ  r49, 21056: + CMPEQ  r37, 33057: + CMPEQ  r46, 24058: + CMPEQ  r32, 29059: + CMPEQ  r25, 11060: + CMPEQ  r41, 28061: + CMPEQ  r19, 17062: + CMPEQ  r33, 17063: + CMPEQ  r31, 36064: + CMPEQ  r28, 29065: + CMPEQ  r10, 10066: + CMPEQ  r42, 36067: + CMPEQ  r30, 27068: + JDN    4095, r0 # Jump to flag...```
The important parts are the `CMPEQ` instructions from `028` to `067`.To get the flag we just need a payload to pass those checks.
I wrote a [script](https://github.com/qxxxb/emu/blob/master/talkative.py) toautomate this. This was the correct payload```USERNAME: YMASPAYLOAD: I MIGHT BE BETTER THAN X-MAS LOLOLOL```
# GAMEBREAK + Demo Party
**Category**: Emulation \**Points**: 500 \**Author**: trupples, Milkdrop
## Challenge
The greatest step towards the popularization of the EMU 1.0 was its entry intothe home entertainment market, starting with the release of the PlutonGAMEBREAK extension. We don't have much to go on but a crumpled up referencecard from a developer, a picture of a retail box, a ROM that supposedly usesthe graphics and memory extensions, and a reconstructed picture of what itshould display.
The external memory seemed to have had 256k slots which are 18-bit addresable.The old screens are 64x64 with 6 bit color (2 bits per channel), and theJoysticks have an 8-direction stick and two buttons (X, Y).
Implement the GAMEBREAK devices and make a nice demo to get some points!
## Solution
After implementing the MEM and GPU (I didn't have time to implement D-PADunfortunately), I was able to run `win.rom`:
![](win.png)
The next challenge was to create my own ROM.
I like Nyan Cat, so went to [www.nyan.cat](http://www.nyan.cat/) andgot an Xmas Nyan.Next I scaled it down to fit inside the 64x64 window and then split in intoframes.```convert -coalesce xmas_small.gif f.png```
I wrote a script to read the pixels from each frame. The idea was to hard-codeeach pixel into the tape and store the entire animation in the memory unit.
It ended up looking something like this:```pythondef mem_write_imm(i):    return [        Ins.from_values(Op.ADDI, Cond.UN, 1, 0, i),        Ins.from_io(Cond.UN, 0, IoDevice.MEM_WRITE, 1),    ]
tape = []for f in frames:    for row in f:        for px in row:            c = unscale_color(px)  # EMU uses 64-bit color            tape += mem_write_imm(c)```
To draw a row, I wrote this function:```pythondef draw_row():    color = temp_reg()    x = temp_reg()  # gpu_x + offset    (la, lb) = new_label()
    return [        # Loop through GPU X from 0..width        Ins.from_values(Op.ADDI, Cond.UN, rs['gpu_x'], 0, 0),        Ins.from_values(Op.LBL, Cond.UN, la, lb, 0),
        # offset = 14        Ins.from_values(Op.ADDI, Cond.UN, x, rs['gpu_x'], 14),        Ins.from_io(Cond.UN, 0, IoDevice.GPU_X, x),
        # Get pixel color from frames stored in memory unit        Ins.from_io(Cond.UN, color, IoDevice.MEM_READ, 0),        Ins.from_io(Cond.UN, 0, IoDevice.GPU_DRAW, color),
        Ins.from_values(Op.ADDI, Cond.UN, rs['gpu_x'], rs['gpu_x'], 1),        Ins.from_cmp(Cond.UN, CmpType.RA_IB, Cm.EQ, rs['gpu_x'], width),        Ins.from_values(Op.JUP, Cond.FA, la, lb, 0),    ]```
To draw a frame, I could just re-use the `draw_row` function but increment`GPU_Y` on each iteration.```pythondef draw_frame():    ans = []
    y = temp_reg()  # gpu_y + offset    (la, lb) = new_label()
    ans += [        # Loop through GPU Y from 0..height        Ins.from_values(Op.ADDI, Cond.UN, rs['gpu_y'], 0, 0),        Ins.from_values(Op.LBL, Cond.UN, la, lb, 0),
        Ins.from_values(Op.ADDI, Cond.UN, y, rs['gpu_y'], 18),        Ins.from_io(Cond.UN, 0, IoDevice.GPU_Y, y),    ]
    ans += draw_row()
    ans += [        Ins.from_values(Op.ADDI, Cond.UN, rs['gpu_y'], rs['gpu_y'], 1),        Ins.from_cmp(Cond.UN, CmpType.RA_IB, Cm.EQ, rs['gpu_y'], height),        Ins.from_values(Op.JUP, Cond.FA, la, lb, 0),    ]
    return ans```
Finally, to draw the animation frame-by-frame, I could re-use the `draw_frame`function.
```pythondef draw_frames():    ans = []    (la, lb) = new_label()    wait = new_label()    cl = temp_reg()  # Clock reset
    ans += [        # Loop frame index from 0..n_frames        Ins.from_values(Op.ADDI, Cond.UN, rs['frame_i'], 0, 0),        Ins.from_values(Op.LBL, Cond.UN, la, lb, 0),    ]
    ans += draw_frame()
    ans += [        # Reset clock to draw frame.        # The screen is updated when the clock is reset.        Ins.from_values(Op.ADDI, Cond.UN, cl, 0, 1),        Ins.from_io(Cond.UN, 0, IoDevice.CLOCK_LO_CS, cl),
        # Wait 0.08 seconds before drawing next frame        Ins.from_values(Op.LBL, Cond.UN, wait[0], wait[1], 0),        Ins.from_io(Cond.UN, cl, IoDevice.CLOCK_LO_CS, 0),        Ins.from_cmp(Cond.UN, CmpType.RA_IB, Cm.UL, cl, 8),        Ins.from_values(Op.JUP, Cond.TR, wait[0], wait[1], 0),
        # Next frame        Ins.from_values(Op.ADDI, Cond.UN, rs['frame_i'], rs['frame_i'], 1),        Ins.from_cmp(Cond.UN, CmpType.RA_IB, Cm.EQ, rs['frame_i'], n_frames),        Ins.from_values(Op.JUP, Cond.FA, la, lb, 0),
        # Loop the animation
        # Set frame index to 0        Ins.from_values(Op.ADDI, Cond.UN, rs['frame_i'], 0, 0),
        # Reset memory pointer        Ins.from_io(Cond.UN, 0, IoDevice.MEM_ADDR_HI, 0),        Ins.from_io(Cond.UN, 0, IoDevice.MEM_ADDR_MID, 0),        Ins.from_io(Cond.UN, 0, IoDevice.MEM_ADDR_LO, 0),
        Ins.from_values(Op.JUP, Cond.UN, la, lb, 0),    ]
    return ans```
The full script is [here](https://github.com/qxxxb/emu/blob/master/nyan.py).This is the final output:
![](https://raw.githubusercontent.com/qxxxb/emu/master/imgs/output.gif)