I have an Arduino Uno Rev3. I would like to extract and find out what code is burned on the ROM of the micro-controller board.
- How do I extract the code from the board?
- How do I figure out the original source code that went into the hex file?
Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. It only takes a minute to sign up.
Sign up to join this communityI have an Arduino Uno Rev3. I would like to extract and find out what code is burned on the ROM of the micro-controller board.
I'll answer this in two parts, #1 is relatively easy, #2 impossible to the level which I'm assuming you want.
While the specifics will depend on the revision of the Uno that you have, you'll want to use avrdude (available for linux, bundled with the OS X Arduino software) and a command similar to the following that would extract the information from an ATmega168:
avrdude -F -v -pm168 -cstk500v1 -P/dev/ttyUSB0 -b19200 -D -Uflash:r:program.bin:r
Look at the avrdude documentation to match the part parameter -p
specific to your device (or post them and we can go from there).
Since it appears that you have the Uno Rev3, that board has an ATmega328 (-pm328
). The programmer "communicates using the original STK500 protocol" thus the communication protocol flag -c
should be -cstk500v1
the command you would need (assuming the Uno is connected to /dev/ttyUSB0) follows:
avrdude -F -v -pm328p -cstk500v1 -P/dev/ttyUSB0 -b19200 -D -Uflash:r:program.bin:r
Next up your second question.
Sorry, but that's not possible. While you can get some hex to c "decompilers" the gibberish returned, while functionally correct, will not be human readable (some commercial ones, like Hex-Rays, might give you some level of human-readability).
With that said, you're best bet would be a hex to assembly translator/converter - which will still only give you a better picture of what's happening, but will still be (by definition) very low level. All variable names, comments etc would be stripped and you're still going to be left with not knowing the original source program contents - just the compiled result.
Since you're dealing with an Atmel device you could try to use the avr specific gcc toolchain avr-gcc
. Specifically, you'll need avr-objdump
using the needed MCU type flag -m atmega328
(avr5) architecture (Full List of Available Architectures, MCU types)
avr-objdump -s -m atmega328 program.hex > program.dump
It is also possible, depending on your configuration, that providing the architecture type itself (avr5) would be sufficient:
avr-objdump -s -m avr5 program.hex > program.dump
On windows for an arduino nano, you do this:
cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin"
followed by this:
"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude" -F "-CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -v -patmega328p -carduino -PCOM14 -b57600 -D-Uflash:r:c:\keep\program.bin:r
Here's the output from the above grabbing code:
avrdude2.exe: Version 6.0.1, compiled on Mar 30 2015 at 14:56:06
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch
System wide configuration file is "C:\Program Files (x86)\Arduino\
hardware\tools\avr/etc/avrdude.conf"
Using Port : COM14
Using Programmer : arduino
Overriding Baud Rate : 57600
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 360
0 3600 0xff 0xff
flash 65 6 128 0 yes 32768 128 256 450
0 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 450
0 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 450
0 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 450
0 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 450
0 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: 2
Firmware Version: 1.16
Vtarget : 0.0 V
Varef : 0.0 V
Oscillator : Off
SCK period : 0.1 us
avrdude2.exe: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude2.exe: Device signature = 0x1e950f
avrdude2.exe: safemode: lfuse reads as 0
avrdude2.exe: safemode: hfuse reads as 0
avrdude2.exe: safemode: efuse reads as 0
avrdude2.exe: reading flash memory:
Reading | ################################################## | 100% 9.49s
avrdude2.exe: writing output file "c:\keep\program.bin"
avrdude2.exe: safemode: lfuse reads as 0
avrdude2.exe: safemode: hfuse reads as 0
avrdude2.exe: safemode: efuse reads as 0
avrdude2.exe: safemode: Fuses OK (H:00, E:00, L:00)
avrdude2.exe done. Thank you.
and this is the resulting file:-
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin>dir c:\keep\program.bin
Volume in drive C has no label.
Volume Serial Number is EE8C-DFB9
Directory of c:\keep
19/02/2016 07:00 PM 32,670 program.bin
1 File(s) 32,670 bytes
0 Dir(s) 41,416,818,688 bytes free
I renamed my "avrdude.exe" to "avrdude2.exe" and wrote a shim named "avrdude.exe" which calls the real one after outputting what the arduino does to build to my target device.
The original command my system used to build was:-
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude "-CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -v -patmega328p -carduino -PCOM14 -b57600 -D -Uflash:w:C:\Users\user\AppData\Local\Temp\build4588201597642272956.tmp/TFT_Baja2.cpp.hex:i
Interesting fact: the hex dump included fragments of other code I'd written... this suggests some very interesting privacy and security problems for anyone shipping arduinos which have been previously used for other things...
If you're using boards other than a nano, my shim was:
#!perl
use strict;
foreach(@ARGV){$_=qq("$_") if(/\s/)}; # DOS Wants quotes around space-embedded paramaters!
foreach(@ARGV){$_='-v' if($_ eq '-q');} # go verbose instead of silent
my $parms=join(" ",@ARGV);
open(OUT,">>","C:\\keep\\avrdude.log") || warn "Cannot write: $!";
print OUT "\n" . &db_now() . " $0 $parms\n"; close(OUT);
my $rc=`avrdude2.exe $parms`;
open(OUT,">>","C:\\keep\\avrdude.log"); print OUT $rc; close(OUT);
print $rc;
# Return "now()" in mysql default format.
sub db_now {
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
return sprintf("%04d-%02d-%02d %02d:%02d:%02d",1900+$year,$mon+1,$mday,$hour,$min,$sec);
}
compiled to a windows .exe using:
perlapp avrdude.pl
enjoy!
There is a way to recompile with this opensource app, called RetDec: