逆向工程 8051 固件

逆向工程 拆卸 固件 8051
2021-07-04 08:43:31

我想对 8051 固件二进制文件进行逆向工程,但不确定从哪里开始。该固件适用于 Real RTL8188EE 无线网卡。它位于:https : //github.com/lwfinger/rtlwifi_new/tree/master/firmware/rtlwifi

我知道(认为?)它是 8051,因为在这个芯片的 Linux 代码中有几个参考。我已经从 Linux 代码中识别出头部分是前 32 个字节。

我该如何拆卸它?我已经通过 IdaPro 以 0x20(32 位标头)的偏移量运行它,但是我得到了很多 NOP,然后是二进制垃圾,最后 Ida 似乎正确解释了指令。我运行了它,并在网上找到了一个不起眼的反汇编工具,名为 d52v336,因此我删除了前 32 个字节。它始于许多 NOP 和一系列 ORG。我把打印输出放在这里(https://pastebin.com/1M11wXiF)。代码的第一位似乎以“reti”和“lcall X4204”开头。当我查找 X4202 时,它是“X4204 equ 4204h”,这让我很困惑。也许这是代码的开头,但我不确定。

我怎么知道我的偏移量是否关闭?这是代码的真正开始吗?如果是这样,我该怎么处理那个 lcall?使困惑!

3个回答

radare2 支持 8051 如果你认为它是 8051 你的链接指向一个目录

没有ee文件有一个efw文件我在radare2中运行它似乎正在拆卸它

radare2 -AA -a 8051 固件.bin

[0x00000000]> px 16
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  e188 1000 0800 0000 1025 2156 b02b 0000  .........%!V.+..
[0x00000000]> pd 1
            ;-- b:
            ;-- r4:
            ;-- r5:
            ;-- psw:
            ;-- r7:
/ (fcn) fcn.00000000 14
|   fcn.00000000 ();
\       ,=< 0x00000000  ~   e188           ajmp loc.00000788
[0x00000000]> s 0x788
[0x00000788]> pd 5
|- loc.00000788 9
|   loc.00000788 ();
|       |      ; JMP XREF from 0x00000000 (fcn.00000000)
|       |      ; JMP XREF from 0x00000782 (loc.00000788)
|       |      ; CALL XREF from 0x0000077a (loc.00000788)
|       `=< 0x00000788      80f0           sjmp loc.0000077a
            0x0000078a      e0             movx a, @dptr
/ (fcn) fcn.0000078b 27
|   fcn.0000078b ();
|              ; UNKNOWN XREF from 0x000006db (fcn.0000061c + 191)
|              ; CALL XREF from 0x000006db (fcn.0000061c + 191)
|           0x0000078b      75f003         mov b, #0x03                ; [0x100f0:1]=255
|           0x0000078e      a4             mul ab
|           0x0000078f      24fe           add a, #0xfe
[0x00000788]>

我最近制作了一个工具,使 8051 逆向工程中的早期内容更容易,称为at51,并将无耻地使用这个答案作为展示。

首先,您希望图像正确对齐。很少有 8051 固件对齐,对于这个文件也是如此。通过使用 base 子命令,您可以获得最有可能是文件加载位置的偏移量:

$ at51 base rtl8188efw.bin
Index by likeliness:
    1: 0x3fe0 with 139
    2: 0x2526 with 63
    3: 0x6a5 with 58

请注意,第一场比赛的得分是第二场比赛的两倍多,因此它可能在 0x3fe0 处加载(由于 32 字节的标头,实际上在 0x4000 处)。

您现在可以使用 ghidra 或radare2,它们都支持 8051。为了帮助解决这个问题,由于该固件似乎与大多数 8051 固件一样使用 C51 编译,因此您还可以使用 libfind 子命令在映像中查找标准库函数。为此,您使用 C51*.LIB 形式的 C51 库文件(您可以通过下载 C51 的试用版来获取它们,因为没有人会在 Internet 上的任何位置留下名为 C51L.LIB 的文件)。

无论如何,使用对齐的图像(例如通过使用dd if=rtl8188efw.bin of=fw_aligned bs=$((0x3fe0)) seek=1)和库文件,可以得到

$ at51 libfind fw_aligned /path/to/lib/C51*.LIB
Address | Name                 | Description
0x42dd    (MAIN)                
0x44a9    ?C?IILDX              
0x44bf    ?C?LAND                long (32-bit) bitwise and
0x44cc    ?C?LOR                 long (32-bit) bitwise or
0x44d9    ?C?LLDXDATA            long (32-bit) load from xdata
0x44e5    ?C?LLDXDATA0           long (32-bit) load from xdata into r3-r0
0x44f1    ?C?OFFXADD            
0x44fd    ?C?PLDXDATA            general pointer load from xdata
0x4506    ?C?PSTXDATA            general pointer store to xdata
0x450f    ?C?CCASE              
0x4573    ?C_START              

现在您有一些函数开始的偏移量以及其中一些函数的描述,这应该会有所帮助。请注意,MAIN 位于括号中,因为它不是在库本身中找到的,而是由它引用的。

最后一件事是由 C51 生成的固件通常包含一个结构,其中存储要在启动时初始化的内存位置的值。可以使用 kinit 子命令读取该结构。您可以轻松找到该结构的偏移量,因为它是在 ?C_START 的开头加载的mov dptr, #0x45b8但似乎对于这个固件映像,这实际上是禁用的(通过在该位置插入 0)?或者也许链接器搞砸了并在结构之前而不是之后插入了 0?无论如何,如果他们没有将其归零(该结构实际​​上存在于它后面的一个字节),你会得到

$ at51 kinit -o $((0x45b9)) fw_aligned
xdata[0x8197] = 0x00
xdata[0x8198] = 0x00
xdata[0x81a4] = 0x00
xdata[0x3457..0x3468] = [0x4a, 0x57, 0x36, 0x58, 0x29, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0]

最后一个似乎是垃圾,因为它包含 8051 代码,所以也许终止 0 不小心落在了开头。

是的,这看起来像 8051 固件。

重置入口点是 0x0000,在这种情况下会跳转到 0x0788,它会继续使用有效的 8051 代码。有许多对 0x4000 以上地址的调用,因此您可能缺少 ROM 代码。

根据我的经验,radare2 ( aa, aaa)的自动分析功能与 8051 有很大的冲突。我通常只运行aar以获取所有交叉引用,然后在进行过程中手动标记代码。

我还配置e asm.jmpsub=true了更好的 8051 反汇编(一旦您开始分配标志)。

有关使用radare2 反转8051 的更多信息,请参阅此页面:https ://radare.gitbooks.io/radare2book/content/arch/8051.html