Netgear R6400v2 固件重打包

周末看到网件出新安全公告了,然后把新固件拉下来看看手上的洞被补了没。

没有哈哈哈哈,但是新版固件中debug页面开启telnet的勾选框已经没有了,不知道是不是之前报的登录程序漏洞的原因。

没有telnet就不能调试,那得多难受,试着整一个出来。这里得提一下,网件官方可以下载到所有固件,并且都是不加密的,这点十分友好。既然有固件,那想添加功能通过重打包来实现就可以了。
下面主要记录操作过程,就当是在记笔记。


先看固件结构:

1
2
3
4
5
6
7
8

x@ubuntu  6400_104120  binwalk R6400v2-V1.0.4.120_10.0.91.chk

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
58 0x3A TRX firmware header, little endian, image size: 47222784 bytes, CRC32: 0xB9C3C9B8, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x20BD98, rootfs offset: 0x0
86 0x56 LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5276608 bytes
2145746 0x20BDD2 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 45075386 bytes, 1798 inodes, blocksize: 131072 bytes, created: 2021-09-03 09:27:39

三部分组成,0x3A长度的数据 +TRX 头 + LZMA 压缩的数据 + Squashfs 文件系统,其中开始的0x3A是网件自己的头,LZMA 压缩的是linux kernel, 最后是squash格式的文件系统。

通过对比多个固件,网件自己的头是可以分析出来个大概的:

1
2
3
4
5
6
x@ubuntu  6400_104120  hexdump -C R6400v2-V1.0.4.120_10.0.91.chk -n 58
00000000 2a 23 24 5e 00 00 00 3a 01 01 00 04 78 0a 00 5b |*#$^...:....x..[|
00000010 43 6f 0a 9f 00 00 00 00 02 d0 90 00 00 00 00 00 |Co..............|
00000020 43 6f 0a 9f 0f bd 0a b5 55 31 32 48 33 33 32 54 |Co......U12H332T|
00000030 30 30 5f 4e 45 54 47 45 41 52 |00_NETGEAR|
0000003a

0-8字节是固定的, 9-0x10字节是固件的版本号

0x10-0x17, 0x20-0x27是checksum信息

0x18-0x1f是固件的大小

0x28-0x39是固件的设备相关信息

更具体的可以自己去分析一下packet文件,记得网上有人分析过。

TRX 的结构如下:

1
2
3
4
5
6
7
struct trx_header {
uint32_t magic; /* "HDR0" */
uint32_t len; /* Length of file including header */
uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
uint32_t flag_version; /* 0:15 flags, 16:31 version */
uint32_t offsets[4]; /* Offsets of partitions from start of header */
};

将固件解包后在文件系统中翻了翻,发现busybox以及utelnetd相关文件都还在,只是web接口没了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
x@ubuntu  6400_104120  binwalk -Me R6400v2-V1.0.4.120_10.0.91.chk 

Scan Time: 2021-09-28 21:34:05
Target File: /home/x/Documents/iot/firmware/netgear/fuckyou/6400_104120/R6400v2-V1.0.4.120_10.0.91.chk
MD5 Checksum: bb55c02b824c5d2afbdf1f8788a62643
Signatures: 411

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
58 0x3A TRX firmware header, little endian, image size: 47222784 bytes, CRC32: 0xB9C3C9B8, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x20BD98, rootfs offset: 0x0
86 0x56 LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5276608 bytes
2145746 0x20BDD2 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 45075386 bytes, 1798 inodes, blocksize: 131072 bytes, created: 2021-09-03 09:27:39

Scan Time: 2021-09-28 21:34:14
Target File: /home/x/Documents/iot/firmware/netgear/fuckyou/6400_104120/_R6400v2-V1.0.4.120_10.0.91.chk.extracted/56
MD5 Checksum: 85dfc4101805b3eca170875f7418e335
Signatures: 411

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
131072 0x20000 ASCII cpio archive (SVR4 with no CRC), file name: "/dev", file name length: "0x00000005", file size: "0x00000000"
131188 0x20074 ASCII cpio archive (SVR4 with no CRC), file name: "/dev/console", file name length: "0x0000000D", file size: "0x00000000"
131312 0x200F0 ASCII cpio archive (SVR4 with no CRC), file name: "/root", file name length: "0x00000006", file size: "0x00000000"
131428 0x20164 ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
278363 0x43F5B LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 64 bytes
2314105 0x234F79 Certificate in DER format (x509 v3), header length: 4, sequence length: 1284
2314221 0x234FED Certificate in DER format (x509 v3), header length: 4, sequence length: 1288
3537773 0x35FB6D Certificate in DER format (x509 v3), header length: 4, sequence length: 1292
3537777 0x35FB71 Certificate in DER format (x509 v3), header length: 4, sequence length: 1304
3537781 0x35FB75 Certificate in DER format (x509 v3), header length: 4, sequence length: 1308
3903676 0x3B90BC Linux kernel version 2.6.36
3992328 0x3CEB08 CRC32 polynomial table, little endian
4028004 0x3D7664 VxWorks symbol table, little endian, first entry: [type: initialized data, code address: 0xC04848C6, symbol address: 0xFFFF0012]
4030056 0x3D7E68 CRC32 polynomial table, little endian
4510908 0x44D4BC Unix path: /home/eric/R6400v2/V1.0.4.120_10.0.91/2020_12_24_BSP_6.37.15.7_R6400v2_Armor/components/opensource/linux/linux-2.6.36/arch/arm/i
4638201 0x46C5F9 xz compressed data
4751925 0x488235 Neighborly text, "NeighborSolicits init(): can't add protocol"
4751942 0x488246 Neighborly text, "NeighborAdvertisementsd protocol"
4754040 0x488A78 Neighborly text, "neighbor %.2x%.2x.%pM lostename link %s to %s"
5154935 0x4EA877 LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 32 bytes

Scan Time: 2021-09-28 21:34:15
Target File: /home/x/Documents/iot/firmware/netgear/fuckyou/6400_104120/_R6400v2-V1.0.4.120_10.0.91.chk.extracted/_56.extracted/43F5B
MD5 Checksum: 3b5d3c7d207e37dceeedd301e35e2e58
Signatures: 411

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------

Scan Time: 2021-09-28 21:34:15
Target File: /home/x/Documents/iot/firmware/netgear/fuckyou/6400_104120/_R6400v2-V1.0.4.120_10.0.91.chk.extracted/_56.extracted/4EA877
MD5 Checksum: 70bc8f4b72a86921468bf8e8441dce51
Signatures: 411

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------

x@ubuntu  6400_104120  find _R6400v2-V1.0.4.120_10.0.91.chk.extracted/squashfs-root/ -name "*telnetd*"
_R6400v2-V1.0.4.120_10.0.91.chk.extracted/squashfs-root/bin/utelnetd
_R6400v2-V1.0.4.120_10.0.91.chk.extracted/squashfs-root/usr/sbin/telnetd

那我们只要修改文件系统在启动的时候开启telnet就好了,虽然没有init相关脚本,但是我们在找一个没有参数的程序,做个”劫持“也能达到目的:

1
2
3
4
mv /usr/sbin/dlnad /usr/sbin/dlnadd
echo "#!/bin/sh" > /usr/sbin/dlnad
echo "/bin/utelnetd -p 12580 &" >> /usr/sbin/dlnad
echo "/usr/sbin/dlnadd &" >> /usr/sbin/dlnad

接下来就要考虑如何将固件重新打包并能够正常刷进路由器中,固件解包时,只要binwalk跑一下就完事了,但是重打包就相对麻烦一些。我们刚刚修改了squashfs文件系统,所以就需要重新打包squashfs文件系统,但mksquashfs在打包时,有很多细节的参数和配置,这些参数和配置将直接影响我们重打包的系统是否可以正常运行,此外,还有设备只能识别特定版本的mksquashfs打包出来的固件。最后,TRX头是个什么我们也还得弄弄清楚。

这里又得说一下,网件的开发者是相当的友好,不仅提供固件的下载,还提供了所有版本固件中的GPL部分代码以及编译环境。我们下个对应版本的包,参考下它自己是怎么打包的。

1
wget https://www.downloads.netgear.com/files/GPL/R6400v2-V1.0.4.120_10.0.91_src.zip

在下载的GPL代码中,tools 文件夹中存放着打包时用到的工具, src/router 下面是路由器相关的,我们看一下Makefile中的打包部分也就知道该怎么做了。在Makefile中搜索mksquashfs,成功定位打包部分代码:

netgear_mksquashfs

可以看到文件系统的制作部分很简单,直接就是用默认的squashfs-4.2编译之后直接制作:

1
mksquashfs xxx xxx -noappend -all-root

但是我们在之前使用binwalk看的时候明明发现用的是xz压缩方式,所以我们自己做的时候也还是用xz压缩吧。Makefile中制作完文件系统后还有一些其它操作,但是这里我们不需要,我们原封不动的将制作好的文件系统写回原来的位置即可。所以只需要关注下面制作chk部分:

1
2
3
4
5
6
7
8
###########################################
### Create .chk files for Web UI upgrade ##
cd $(PLATFORMDIR) && touch rootfs && \
../../../tools/packet -k linux.trx -f rootfs -b $(BOARDID_FILE) \
-ok kernel_image -oall kernel_rootfs_image -or rootfs_image \
-i $(fw_cfg_file) && \
rm -f rootfs && \
~~~~cp kernel_rootfs_image.chk $(FW_NAME)_`date +%m%d%H%M`.chk

这里用的是自己的packet工具来制作,我们看下对应的参数都是什么意思:

1
2
3
4
5
./packet --help
Version: 2.0
usage: packet -k [kernel file name] -f [rootfs file name] -b [board id file name] -ok [output kernel file name] -oall [output kernel and rootfs file name] -or [output rootfs file name] -i [configure file path/name]
Example:
packet -k linux.trx -f rootfs -b compatible.txt -ok kernel -oall kernel_rootfs -or rootfs -i ../../../project/acos/include/ambitCfg.h

-k 是kernel文件

-f 是文件系统的名字

-b 是设备id相关信息

-i 是配置文件

kernel我们不用动,文件系统已经打包好了,那我们这里只要关注一下设备id以及配置文件即可。这两个文件在提供的GPL压缩包中都有, find一下就好。由于网件自己的头会通过packet生成,所以我们只要关心TRX头中的crc32以及size字段即可。

所以最终的重打包步骤为:

  1. 准备好修改过的文件系统以及原始固件
  2. 将文件系统使用mksquashfs打包
  3. 从原视固件中提取TRX header+linux kernel, 将新的squashfs填充到后面
  4. 修改crc32字段以及filesize字段
  5. 使用packet工具生成网件自己的头,生成最终的chk文件

最终使用的打包脚本以及对应说明都放在github上了。

在完成这些工作后我又想起来一个问题,我手里不是有一个很好用的命令执行还没提吗?直接用它开启telnet不香嘛??!

最后,如果了解固件的启动流程,需要对bootloader做分析,但是我们又拿不到bootloader,该怎么办呢?

有了telnet就好办了,自己编个dd上去,然后查看分区信息之后将boot部分dump 出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# cat /proc/mtd 
dev: size erasesize name
mtd0: 00080000 00020000 "boot"
mtd1: 00180000 00020000 "nvram"
mtd2: 06b00000 00020000 "linux"
mtd3: 068f4268 00020000 "rootfs"
mtd4: 00080000 00020000 "board_data"
mtd5: 00100000 00020000 "POT1"
mtd6: 00100000 00020000 "POT2"
mtd7: 002c0000 00020000 "T_Meter1"
mtd8: 002c0000 00020000 "T_Meter2"
mtd9: 00080000 00020000 "ML1"
mtd10: 00080000 00020000 "ML2"
mtd11: 00080000 00020000 "ML3"
mtd12: 00080000 00020000 "ML4"
mtd13: 00080000 00020000 "ML5"
mtd14: 00080000 00020000 "ML6"
mtd15: 00080000 00020000 "ML7"
mtd16: 00080000 00020000 "QoSRule"
mtd17: 00100000 00020000 "DebugMsg"
mtd18: 03900000 00020000 "brcmnand"
mtd19: 00500000 00020000 "OpenVPN"
# dmesg |egrep '0x[a-z0-9]{12}'
[ 2.060000] 0x000000000000-0x000000080000 : "boot"
[ 2.070000] 0x000000080000-0x000000200000 : "nvram"
[ 2.070000] 0x000000200000-0x000006d00000 : "linux"
[ 2.080000] 0x00000040bd98-0x000006d00000 : "rootfs"
[ 2.090000] 0x000007200000-0x000007280000 : "board_data"
[ 2.090000] 0x000007280000-0x000007380000 : "POT1"
[ 2.100000] 0x000007380000-0x000007480000 : "POT2"
[ 2.100000] 0x000007480000-0x000007740000 : "T_Meter1"
[ 2.110000] 0x000007740000-0x000007a00000 : "T_Meter2"
[ 2.120000] 0x000007a00000-0x000007a80000 : "ML1"
[ 2.120000] 0x000007a80000-0x000007b00000 : "ML2"
[ 2.130000] 0x000007b00000-0x000007b80000 : "ML3"
[ 2.130000] 0x000007b80000-0x000007c00000 : "ML4"
[ 2.140000] 0x000007c00000-0x000007c80000 : "ML5"
[ 2.140000] 0x000007c80000-0x000007d00000 : "ML6"
[ 2.150000] 0x000007d00000-0x000007d80000 : "ML7"
[ 2.150000] 0x000007d80000-0x000007e00000 : "QoSRule"
[ 2.160000] 0x000007e00000-0x000007f00000 : "DebugMsg"
[ 2.360000] Bad eraseblock 105 at 0x000000d20000
[ 2.380000] Bad eraseblock 266 at 0x000002140000
[ 2.410000] Bad eraseblock 948 at 0x000007680000
[ 2.420000] 0x000003400000-0x000006d00000 : "brcmnand"
[ 2.430000] 0x000006d00000-0x000007200000 : "OpenVPN"
# dd if=/dev/mtd0 of=boot

传送门:重打包脚本

参考链接:

  1. Netgear 固件下载
  2. Netgear GPL 开源软件及工具链下载
  3. 救砖教程
作者

vlinkstone

发布于

2021-09-29

更新于

2021-09-29

许可协议

评论