Search code examples
binaryreverse-engineeringdecompiling8051

Decompiling 8051 binary, read from EEPROM


I'm trying to decompile the firmware of a Logitech Freedom 2.4 Cordless Joystick. I've managed to get something of the EEPROM. (here) The EEPROM that is used is the Microchip 25AA320, which is a 32Kbit SPI-EEPROM. The MCU is a nRF24E1G , that contains a 8051 MCU. The ROM should be 4096 bytes, so I think that my reading program looped over it self 4 times. I managed to extract a 4kB ROM (here), but the start of the file doesn't look clean.

I loaded both files into IDA Pro and Ghidra and selected the 8051 processor. They don't generate anything useful.

Could anyone help me decompiling this ROM?

I used this Arduino Sketch to dump the rom. Together with this python script

## Author: Arpan Das
## Date:   Fri Jan 11 12:16:59 2019 +0530
## URL: https://github.com/Cyberster/SPI-Based-EEPROM-Reader-Writer

## It listens to serial port and writes contents into a file
## requires pySerial to be installed 
import sys 
import serial
import time
start = time.time()

MEMORY_SIZE = 4096 # In bytes
serial_port = 'COM5'
baud_rate = 115200 # In arduino, Serial.begin(baud_rate)
write_to_file_path = "dump.rom"

output_file = open(write_to_file_path, "wb")
ser = serial.Serial(serial_port, baud_rate)

print("Press d for dump ROM else CTRL+C to exit.")
ch = sys.stdin.read(1)

if ch == 'd':
    ser.write('d')
    for i in range(MEMORY_SIZE/32): # i.e. MEMORY_SIZE / 32
        # wait until arduino response with 'W' i.e. 1 byte of data write request
        while (ser.read() != 'W'): continue
        ser.write('G') # sends back write request granted signal

        for j in range(32):
            byte = ser.read(1);
            output_file.write(byte);

        print(str(MEMORY_SIZE - (i * 32)) + " bytes remaining.")

print '\nIt took', time.time()-start, ' seconds.'

Solution

  • This is what I did, the next part left is for you. My machine is a Win10 notebook, however I used unix tools because they are so capable.

    First of all, I divided the 16KB dump into four 4KB parts. The first one was different from the other three. And the provided 4KB dump is different to all of these parts. I did not investigate this further, and simply took one of the other three parts that are all equal.

    $ split -b 4K LogitechFreedom2.4CordlessJoystick.rom part
    $ cmp partaa partab
    partaa partab differ: byte 1, line 1
    $ cmp partab partac
    $ cmp partac partad
    $ cmp dump.rom partaa
    dump.rom partaa differ: byte 9, line 1
    $ cmp dump.rom partab
    dump.rom partab differ: byte 1, line 1
    

    From the microcontroller's data sheet I learned that the EEPROM contents has a header of at least 3 bytes (chapter 10.2 at page 61).

    These bytes are:

    0b   Version = 00, Reserved = 00, SPEED = 0.5MHz, XO_FREQ = 16MHz
    03   Offset to start of user program = 3
    0f   Number of 256 bytes block = 15 
    

    The last entry seems to be off by one, because there seems to be code in the 16th block, too.

    Anyway, these bytes look decent, so I cut the first 3 bytes.

    $ dd if=partad of=rom.bin bs=1 skip=3
    4093+0 records in
    4093+0 records out
    4093 bytes (4,1 kB, 4,0 KiB) copied, 0,0270132 s, 152 kB/s
    $ dd if=partad of=head.bin bs=1 count=3
    3+0 records in
    3+0 records out
    3 bytes copied, 0,0043809 s, 0,7 kB/s
    $ od -Ax -t x1 rom.bin > rom.hex
    $ od -Ax -t x1 head.bin > head.hex
    

    The hex files are nice for loading them into an editor and look around.

    I loaded the remaining 4093 bytes into a disassembler I once wrote and peeked around a bit. It looks promising, so I think you can go on without me now:

    C0000:  ljmp    C0F54
    
    C0003:  setb    021H.2
            reti
    
    C000B:  xch     a,r5
            inc     r6
            xrl     a,r6
            mov     a,#0B2H
            movc    a,@a+pc
            movx    @r1,a
            mov     r7,a
            setb    021H.2
            reti
    
    C0F54:  mov     psw,#000H
            mov     sp,#07BH
            mov     r0,#0FFH
            mov     @r0,#000H
            djnz    r0,C0F5C
            ljmp    C0C09