如何找出 Arduino ROM 上烧毁的内容?

逆向工程 反编译 只读存储器 倾倒
2021-06-26 01:05:31

我有一个 Arduino Uno Rev3。我想提取并找出微控制器板的ROM上烧录的代码。

  1. 如何从板上提取代码?
  2. 如何找出进入 hex 文件的原始源代码?
3个回答

我将分两部分回答这个问题,#1 相对容易,#2 不可能达到我假设你想要的水平。

1. 从 Uno 中提取十六进制代码:

虽然细节将取决于您拥有的 Uno 的修订版,但您需要使用 avrdude(可用于 linux,与 OS X Arduino 软件捆绑在一起)和类似于以下的命令,该命令将从 ATmega168 中提取信息:

avrdude -F -v -pm168 -cstk500v1 -P/dev/ttyUSB0 -b19200 -D -Uflash:r:program.bin:r

查看avrdude 文档以匹配-p特定于您的设备的部件参数(或发布它们,我们可以从那里开始)。

因为看起来你有Uno Rev3那块板子有一个 ATmega328 ( -pm328)。程序员“使用原始 STK500 协议进行通信”,因此通信协议标志-c应该是-cstk500v1您需要的命令(假设 Uno 连接到 /dev/ttyUSB0)如下:

avrdude -F -v -pm328p -cstk500v1 -P/dev/ttyUSB0 -b19200 -D -Uflash:r:program.bin:r

接下来是你的第二个问题。

2. 将十六进制代码转换为原始源代码:

对不起,但那是不可能的。虽然你可以得到一些十六进制到 c 的“反编译器”,但返回的胡言乱语虽然功能正确,但不会是人类可读的(一些商业的,比如 Hex-Rays,可能会给你某种程度的人类可读性)。

话虽如此,你最好打赌是汇编翻译器/转换器的十六进制 - 这仍然只能让你更好地了解正在发生的事情,但仍然(根据定义)非常低。所有变量名、注释等都将被删除,您仍然不知道原始源程序的内容——只知道编译结果。

由于您正在处理 Atmel 设备,因此您可以尝试使用特定于 avr 的 gcc 工具链avr-gcc具体来说,您需要avr-objdump使用所需的 MCU 类型标志-m atmega328(avr5) 架构(可用架构的完整列表、MCU 类型

avr-objdump -s -m atmega328 program.hex > program.dump

根据您的配置,也有可能提供架构类型本身 (avr5) 就足够了:

avr-objdump -s -m avr5 program.hex > program.dump

在 arduino nano 的 windows 上,你可以这样做:

cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin"

其次是:

"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

这是上面抓取代码的输出:

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.

这是生成的文件:-

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

我将我的“avrdude.exe”重命名为“avrdude2.exe”并编写了一个名为“avrdude.exe”的垫片,它在输出arduino为我的目标设备所做的构建后调用真实的垫片。

我的系统用来构建的原始命令是:-

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

有趣的事实:十六进制转储包含我编写的其他代码的片段……这对于任何运送以前用于其他事情的 arduino 的人来说,暗示了一些非常有趣的隐私和安全问题……

如果您使用的是 nano 以外的板,我的垫片是:

#!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);
}

使用以下命令编译为 windows .exe:

perlapp avrdude.pl

请享用!

有一种方法可以使用这个开源应用程序重新编译,称为 RetDec:

https://github.com/avast-tl/retdec