Reverse engineer dump

Hi there! I'm completely new to arduino, but not to programming. I bought a gadget that is not behaving as expected and to my surprise the brains of the operation is an Arduino UNO.
After a bit of googling i was able to connect to it using avrdude and dump its contents.
This is the command I used to do it:
avrdude -CC:avrdude.conf -v -V -patmega328p -carduino "-PCOM10" -b115200 -D "-Uflash:r:dump.hex:i"

It worked, and as output i got the hex file and this info on the shell:

             Using Port                    : COM10
             Using Programmer              : arduino
             Overriding Baud Rate          : 115200
             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

             Programmer Type : Arduino
             Description     : Arduino
             Hardware Version: 3
             Firmware Version: 4.4
             Vtarget         : 0.3 V
             Varef           : 0.3 V
             Oscillator      : 28.800 kHz
             SCK period      : 3.3 us

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0
...

I'd like to reverse engineer the code to try to at least understand how it works and if or how I can fix it.
Using Ghidra I was able to have it decompile the dump succesfully, ( at least it appears to be ), however, being completely new to the platform I have no idea where to find the relevant information.
Where does the user code start? What are the registers, device registers addresses, memory mapped devices ecc.

Previous questions on the topic were more specific and/or were met with pessimism.
Do you know of any resource that could help me? Have you tried something similar in the past? Do you know of any tool that could help me?

Thank you!

I am curious what that gave you, can you post it, or at least some exciting part of it?

a7

The dump itself is quite long, as you would expect all internal/library functions to be included and initialized, however here's the first function in memory, which I would expect to be the first thing executed:


void FUN_code_000035(void)

{
  undefined1 *puVar1;
  
  R1 = 0;
  SREG = 0;
  R17 = '\x01';
  X = &DAT_mem_0100;
  Z = 0x15fc;
  while (puVar1 = X, (byte)X != 0x3c || X._1_1_ != (char)(R17 + ((byte)X < 0x3c))) {
    R0 = *(undefined *)(uint3)Z;
    Z = Z + 1;
    X = X + 1;
    *puVar1 = R0;
  }
  R18 = '\x05';
  X = &AES_CTRL;
  while (puVar1 = X, (byte)X != 0xa3 || X._1_1_ != (char)(R18 + ((byte)X < 0xa3))) {
    X = X + 1;
    *puVar1 = R1;
  }
  R17 = 0;
  Ylo = 0x35;
  Yhi = 0;
  TIMER4_COMPB();
  return;
}

It's disabling interrupts, initializing memory regions and setting the timer, which are all plausible operations to perform at boot time.

However interpreting every single function is quite complex and time-consuming. Therefore, I am hoping someone more knowledgeable can guide me in the right direction.

Would you mind identifying what this "gadget" is?

That looks a bit odd, since an atmega328 only has three timers, and you would normally start numbering with TIMER0.

It's an ARGB Led strip controller that connects to some PC software, but i'm having some problems with it and being an arduino it would be nice to tinker with it and maybe connect it to some other software.

If you are wanting to use it with other software, then it would be much simpler to just write your own code. Even with proprietary software running on the PC, it would probably be easier to decode the communications to the UNO than to disassembly the code.

Does the device literally have an UNO inside it, or just an atmega328?

I has an atmega328, in the silk screen there's a big UNO next to it, but no "arduino" text. I expect it to be some sort of semi-custom PCB for an arduino UNO

I'd like to retain the original functionality as much as possible, and to fix any problems i have with it

THX. About the only thing that could have made it worse is if it used goto.

Many times here the advice for reversing is the same as for trying to protect IP in code… don't.

This thing probably doesn't do anything you couldn't write, so maybe a better place to start would be to draw a schematic.

a7

One of the problems trying to reconstruct the instructions is "where to start"? Does byte 0 always begin the first machine instruction? Or does byte 1 start? or byte 100?

Ghidra looks interesting. Produced and distributed in collaboration with the U.S. NSA, who invite you to join them:

If you are a U.S. citizen interested in projects like this, to develop Ghidra 
and other cybersecurity tools for NSA to help protect our nation 
and its allies, consider applying for a career with us.

Not to mention how the NSA spies on U.S. citizens of all stripes.

I think @thanzex should have chatGPT take a crack at it.

I just noticed

  while (puVar1 = X, (byte)X != 0x3c || X._1_1_ != (char)(R17 + ((byte)X < 0x3c))) {

There is an assignment statement and the comma operator.

a7

Would probably help to look at the fuse settings to see if there is space allocated for a bootloader, etc.

With an actual UNO type board in the device, spend some time searching google, someone may actually have posted the code somewhere.

Something you can do with a code dump is print out the ASCII representation of the data. That lets you see things like text prompts, error messages, etc, that can give clues to what options are available in the code, and gives you specific things to search for on google.