How to rip code off an Arduino?

I am not quite sure where I should post this but here we go...

A few months ago I wrote a sketch for my Arduino Pro Micro, but then my computer corrupted and I lost the original sketch file, since I forgot how it was written, is there anyway to rip the hex code off an Arduino Pro Micro?

Thanks first!

Read a binary from an Arduino board

Generate command

First, we're going to do a dummy upload in the Arduino IDE in order to get it to help us generate the avrdude command used to read the program from the Arduino board:

  1. Plug your Arduino board into your computer.
  2. Select your board from the Arduino IDE's Tools > Board menu.
  3. Select your board's port from the Tools > Port menu.
  4. :warning: VERY IMPORTANT: Unplug your board from your computer.
  5. Select File > Preferences from the Arduino IDE menus.
  6. Check the box next to "Show verbose output during > upload".
  7. Click the "OK" button.
  8. Select Sketch > Upload from the Arduino IDE menus.
  9. Wait for the upload to fail.
    the previous procedure was intended only to get the IDE to generate the command. It was expected to fail since the board was not connected.
  10. Scroll up the black console window at the bottom of the Arduino IDE window until you see the avrdude command that was generated for the upload.
    It will look something like this:
    E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i
    
  11. Select the full text of the upload command.
  12. Press Ctrl + C.
    This will copy the upload command to the clipboard.

Adapt command

Next, you need to modify the upload command to read the hex file out of your Arduino board:

  1. Start a text editor program.
  2. In the text editor window, press Ctrl + V.
    This will paste the command into the text editor.
    The end of the command will look something like this:
    -D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i
    
    That is the part of the command that tells it to write.
  3. Replace that part of the command with the command that tells AVRDUDE to read:
    -Uflash:r:readfile.hex:i
    
    That will cause the read file to be named readfile.hex, which will be saved to whichever folder you run the command from. So now the full command looks something like this:
    E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:r:readfile.hex:i
    
  4. If the paths in the command contain spaces, wrap the paths in quotes.

Run command

  1. Plug your Arduino board into your computer.
  2. Copy and paste the command from the text editor to the command line
  3. If you are using to an ATmega32U4-based board (e.g., Leonardo, Micro, Yun), you'll need to press and release the reset button on the board immediately after running the command.
    If you are using a Pro Micro, use a wire to momentarily connect the RST and GND pins.
    If you are using a Yun, press and release the "32U4 RST" button quickly twice.
    Wait about a second after resetting the board before running the command.
  4. Run the command.
  5. Wait for the command to finish successfully.

You will now find the read binary in a file named readfile.hex in the current folder.

Writing the binary to an Arduino board

You can follow a similar procedure to write the file to another Arduino board.

:red_exclamation_mark: Remember that this file was compiled specifically for the Arduino board you read it from. You can't use it with an Arduino board that has a different configuration.
For example, if you read it from an Uno, it is compiled for an ATmega328P running at 16 MHz with a boot section of 0.5 kB.

Generate command

First, we're going to do a dummy upload in the Arduino IDE in order to get it to help us generate the avrdude command used to write the program to the Arduino board:

  1. Plug the Arduino board you want to write to into your computer.
  2. Select your board from the Arduino IDE's Tools > Board menu.
  3. Select your board's port from the Tools > Port menu.
  4. Select File > Preferences from the Arduino IDE menus.
  5. Check the box next to "Show verbose output during > upload".
  6. Click the "OK" button.
  7. Select Sketch > Upload from the Arduino IDE menus.
  8. Wait for the upload to finish.
  9. Scroll up the black console window at the bottom of the Arduino IDE window until you see the avrdude command that was generated for the upload. It will look something like this:
    E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i
    
  10. Select the full text of the upload command.
  11. Press Ctrl + C.
    This will copy the upload command to the clipboard.

Adapt command

Next, you need to modify the upload command to write the hex file you read from your other Arduino board:

  1. Start a text editor program.
  2. In the text editor window, press Ctrl + V.
    This will paste the command into the text editor.
    The end of the command will look something like this:
    -D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i
    
    That is the part of the command that tells it to write.
  3. Replace the filename in that part of the command with the name of the file you read:
    -Uflash:w:readfile.hex:i
    
    So now the full command looks something like this:
    E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:w:readfile.hex:i
    
  4. If the paths in the command contain spaces, wrap the paths in quotes.
  5. Plug your Arduino board into your computer.
  6. Copy and paste the command from the text editor to the command line.
  7. If you are uploading to an ATmega32U4-based board (e.g., Leonardo, Micro, Yun), you'll need to press and release the reset button on the board before running the command.
    If you are using a Pro Micro, use a wire to momentarily connect the RST and GND pins.
    If you are using a Yun, press and release the "32U4 RST" button quickly twice.
    Wait about one second before running the command.
  8. Run the command.
  9. Wait for the writing process to finish successfully.

Hey pert! Thanks for replying!

I have dumped the entire "logfile" into notepad so that I could read it easier, but the trouble is I can't see the line you were talking about:

E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i

I know filenames and paths vary from computer to computer but I still wasn't able to find the line. I don't know if it is related but I use the Microsoft Store version of the Arduino IDE. I have attached the "logfile" so you could have a look. Thanks first!

logfile.txt (10.2 KB)

OK, the problem is that my instructions were written with the boards like the Uno, that don't have native USB, in mind.

With boards like your Pro Micro, if you don't have a port selected from the Arduino IDE's Tools > Port menu, the avrdude command will never be executed.

Select Tools > Port > COM1 in the Arduino IDE and then try again.

Good to know, I'll save this thread.
Everything I do now I back up on gitHub, but you never know....

Any chance this would work on an ESP board?

The ESP boards don't use avrdude as the upload tool. They use something called esptool. So you'd need to check whether esptool has a similar capability of reading from the chip. I don't have a lot of experience with the Espressif chips, so I have no idea. But it's possible you could use a similar procedure to the one I describe here for the ESP chips.

oyan244:
... my computer corrupted and I lost the original sketch file, since I forgot how it was written, is there anyway to rip the hex code off an Arduino Pro Micro?

You can read the f/w image from the Arduino (Assuming the fuses allow it) and save it to a file which can be used to burn into another Arduino (as long as it is the same board type) but you can't ever recover the orignal sketch source code.

--- bill

SteveMann:
Good to know, I'll save this thread.
Everything I do now I back up on gitHub, but you never know....

Any chance this would work on an ESP board?

Hey pert! sorry for the late reply!
I have poked around recently to try to get the avrdude command you were talking about but I am having some trouble reading the logfile itself, I found a line that said something like this though:

C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\tools\avr/bin/avrdude -CC:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf -v -patmega32u4 -cavr109 -PCOM1 -b57600 -D -Uflash:w:C:\Users\oyan2\AppData\Local\Temp\arduino_build_184337/sketch_dec17b.ino.hex:i

Is it this line or am I wrong?
Again, I have attached the logfile for further reading.
Thanks a lot for helping!

logfile.txt (43.7 KB)

That is it. I'm not sure what the implications might be of avrdude being under the installation folder of the Windows App Store version of the Arduino IDE. I know there are strict security restrictions on that folder that make it very difficult to make any modifications to the contents, but you're not making any modifications, so it's probably no problem.

Give it a try and let us know how it goes.

Hey pert, so I am up to the part with command prompt now, I tried reading it but it errors out:

C:\Users\oyan2>D:\Software\Arduino\hardware\tools\avr/bin/avrdude -CD:\Software\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega32u4 -cavr109 -PCOM5 -b57600 -D -Uflash:w:C:\Users\oyan2\AppData\Local\Temp\arduino_build_998198/sketch_dec18a.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "D:\Software\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         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  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 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 : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: reading input file "C:\Users\oyan2\AppData\Local\Temp\arduino_build_998198/sketch_dec18a.hex"
avrdude: can't open input file C:\Users\oyan2\AppData\Local\Temp\arduino_build_998198/sketch_dec18a.hex: No such file or directory
avrdude: read from file 'C:\Users\oyanAppData\Local\Temp\arduino_build_998198/sketch_dec18a.hex' failed

avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)

avrdude done.  Thank you.

It would be great if you could have a look! P.S I ran this command when the Arduino is in bootlader mode, and also I switched to the non-Windows Store version of the IDE

That is the write command. The command you get from the Arduino IDE is just the base for the command you need to craft to do the read. It looks like you just copy/pasted it without making any changes. Check my instructions:

pert:
Next, you need to modify the upload command to read the hex file out of your Arduino board:

Start a text editor program.

In the text editor window, press Ctrl + V. This will paste the command into the text editor. The end of the command will look something like this:

-D -Uflash:w:C:\Users\per\AppData\Local\Temp\arduino_build_91864/sketch_jan22b.ino.hex:i

That is the part of the command that tells it to write.

Replace that part of the command with the command that tells AVRDUDE to read:

-Uflash:r:readfile.hex:i

That will cause the read file to be named “readfile.hex”, which will be saved to whichever folder you run the command from. So now the full command looks something like this:

E:\Arduino\hardware\tools\avr\avrdude -CE:\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM17 -b115200 -D -Uflash:r:readfile.hex:i

You told avrdude to write to the flash. You probably want to read from the flash.
The "op" field should be a 'r' not a 'w'.
See the man page for the options: AVRDUDE: 2.2 Programmers accepting extended parameters

--- bill

Thanks Bill and pert, that really helped! Also, there is no way to decode the hex file and get the original code am I right?

" there is no way to decode the hex file and get the original code am I right?"

you are indeed right. what you see is compiled code. compiled code strips out LongDetailedVariableNames and void FunctionNames and replaces them. it's like baking cookies, you can't get back to eggs and flour.

You can probably translate the hex into assembler, but the C++ would have to be deduced from that. You may find it easier to rewrite the code from scratch - I know I would.

wildbill:
You can probably translate the hex into assembler, but the C++ would have to be deduced from that. You may find it easier to rewrite the code from scratch - I know I would.

Yeah, years ago before we had such levels of optimization, there were tools that could do an ok job at getting back to the orignal C code.
But now the gcc optimizations are so intense that even source level debugging can be difficult even when the debugger as access to the orignal source code because the final code is so different than what the user wrote.

--- bill

Code is usually better when it's written for the second time. :slight_smile:

aarg:
Code is usually better when it's written for the second time. :slight_smile:

This should be a meme. Sort of like "The grass is always greener over the septic tank".

Just another question here...
I have an ATTiny85 and I am also trying to rip the code off it, is it possible to achieve this action through the Arduino ISP?