Generally speaking, it's easy to unpack the firmware, but it's difficult to modify the firmware and brush it back to the device. This paper studies several methods of modifying firmware and swiping it back to the device.
Take the firmware of dcs921l as an example. First, use binwalk to analyze its structure:
The structure is very obvious, the kernel system of u-boot plus uimage header plus LZMA package. The simple structure is as follows:
OK, the structure analysis is finished. Now you can unpack the firmware and make some small changes before packaging. Unpack a command:
binwalk -Me dcs932l_v1.14.04.bin
Enter the file system directory, modify the file according to your own needs, and package it into CPIO compressed file:
find . | cpio -H newc -o > ../initrd.cpio
Use LZMA for compression. You can download the corresponding version of LZMA SDK here. Note that LZMA compression of the original firmware specifies the dictionary size. We need to use the same dictionary size as it. Use the - D parameter to specify the dictionary size:
-d
./lzma e initrd.cpio initrd.cpio.lzma -d20
Intercept the data before the kernel file system and splice it to our file system:
dd if=50040 of=kernelHead bs=1 count=4038656
cp ./kernelHead ./kernel
cat initrd.cpio.lzma >> kernel
Then compress the kernel:
./lzma e ./kernel ./kernel.lzma -d25
Before splicing the uimage header to the kernel compressed file:
dd if=dcs of=uImageHeader bs=1 count=64
cp uImageHeader uImage
cat kernel.lzma >> uImage
Note that the uimage header has CRC validation. We need to calculate the CRC checksum and modify the uimage header information ourselves. When WinHex is opened, the following circled bits are header CRC, image size and data CRC:
First calculate the data CRC, select the part after the uimage header, and select CRC32 in tools - > compute hash to calculate:
Change data CRC to the value we calculated, and fill in the value of image size at the same time:
After that, calculate the value of header CRC, overwrite the original value with 00, and then calculate:
Of course, there are also methods that do not need to manually change CRC. Install u-boot-tools under Ubuntu, and then use the mkimage command to automatically generate the uimage header:
sudo apt-get install u-boot-tools
mkimage -A MIPS -O linux -T kernel -C lzma -a 0x80000000 -e 0x803B8000 -n "Linux Kernel Image" -d kernel.lzma uImage
The parameters of mkimage are as follows:
-A ==> set architecture to 'arch' // 用于指定CPU类型
-O ==> set operating system to 'os' // 用于指定操作系统
-T ==> set image type to 'type' // 用于指定image类型
-C ==> set compression type 'comp' // 指定压缩类型
-a ==> set load address to 'addr' (hex) // 指定image的加载地址
-e ==> set entry point to 'ep' (hex) // 指定内核的入口地址
-n ==> set image name to 'name' // image在头结构中的命名
-d ==> use image data from 'datafile' // 无头信息的image文件名
-x ==> set XIP (execute in place) // 设置执行位置
If you can enter the device u-boot through TTL, the firmware package will go to this step. If you want to update the firmware through the web interface, you need to add the previous section of u-boot, which will not be covered here.
Starting the device, you can see the following information printed on the serial interface:
U-Boot 1.1.3
Board: Ralink APSoC DRAM: 32 MB
relocate_code Pointer at: 81fac000
config usb..
Set info->start[0]=BF000000
flash_protect ON: from 0xBF000000 to 0xBF021767
flash_protect ON: from 0xBF030000 to 0xBF030FFF
*** Warning - bad CRC, using default environment
============================================
Ralink UBoot Version: 3.5.2.0
--------------------------------------------
ASIC 3052_MP2 (Port5<->None)
DRAM component: 256 Mbits SDR
DRAM bus: 16 bit
Total memory: 32 MBytes
Flash component: NOR Flash
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:128, ways:4, linesz:32 ,total:16384
##### The CPU freq = 320 MHZ ####
estimate memory size =32 Mbytes
Signature: DCS-930 932L Release 1.11 (2011-05-31)
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
Here we choose 1. Write the system firmware to the memory through TFTP instead of flash, otherwise the wrong firmware will be cold. The process of building TFTP server is not described here.
1: System Load Linux to SDRAM via TFTP.
Please Input new ones /or Ctrl-C to discard
Input device IP (192.168.1.1) ==:192.168.0.100
Input server IP (192.168.1.100) ==:192.168.0.103
Input Linux Kernel filename () ==:uImage
After downloading the firmware from the TFTP server, the device will automatically start the system
To brush in the openwrt firmware to the device, you need to go to the openwrt official website to find out whether the device is supported. You can download the firmware supporting the device directly on the official website, or you can compile it by yourself. Download source package
git clone https://github.com/openwrt/openwrt
Install the corresponding dependencies:
sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip zip unrar p7zip p7zip-rar p7zip-full sharutils subversion libncurses5-dev ncurses-term zlib1g-dev gawk git-core libssl-dev
Upgrade and install the extension software:
./scripts/feeds update -a
./scripts/feeds install -a
make package/symlinks
Use the default compilation environment:
make defconfig
To configure:
make menuconfig
Select the corresponding target platform, device chip model and device specific model, etc
When compiling, openwrt will help you download and install the required package, and generate the corresponding firmware package, which usually takes 4-5 hours:
make V=99
After compiling, the compiled firmware file can be found in. / bin / targets / ramips / rt305x /. There is a configured file directory system in. / build ﹣ dir / target mipsel ﹣ 24kc ﹣ musl / root ramips directory.
Successfully swipe in the device through u-boot:
Dcs932l uses the main controller of Ralink rt3052. We can customize our firmware by compiling the Ralink SDK.
Ralink SDK development manual and source package download: https://pan.baidu.com/s/1venly-ym2f-stoy-alkjsw (y9u0)
Tool chain installation configuration
Copy the builderoot source package to the / opt directory, and extract it
cp RT288x_SDK/toolchain/buildroot-gcc342.tar.bz2 /opt
tar jxvf buildroot-gcc342.tar.bz2
Compile and install LZMA
tar xvfz RT288x_SDK/toolchain/lzma-4.32.7.tar.gz
cd RT288x_SDK/toolchain/lzma-4.32.7
./configure
make
make install
Compile and install mksquashfs
cd RT288x_SDK/toolchain/mksquash_lzma-3.2
make
make install
In addition, it's better to change the make version of this machine to a lower version, or make will fail to recognize the makefile statement of the old version of the kernel (of course, you can directly change makefiles one by one, which is just a few mistakes)
Source configuration compilation
make menuconfig
Select the product you wish to target -- > select the corresponding hardware chip model:
Kernel / library / defaults selection - > select whether to configure kernel, library, and busybox. You can select one-time settings for the first compilation:
Kernel configuration
Here are the options my device needs to be configured for reference only.
Machine selection --->
System type--> (选择板子型号)
DRAM Size (32M) ---> (选择内存大小)
Kernel NVRAM (启用NVRAM)
Compress ramdisk by lzma instead of gzip (用lzma打包镜像文件)
General setup --->
Kernel->user space relay support (formerly relayfs) (启用内核空间到用户空间的relay支持)
Block layer --->
Enable the block layer (启用通用块层)
IO Schedulers --->
Default I/O scheduler (No-op) ---> (默认I/O调度器为No-op *适合闪存设备和嵌入式系统的I/O调度器)
No-op
Networking --->
Networking options --->
Packet socket
Unix domain sockets(同一主机进程间通信)
TCP/IP networking
Generic IEEE 802.11 Networking Stack(无线网络支持)
IEEE 802.11 WEP encryption (802.1x)
Device Drivers --->
Network device support --->
Network device support (启用网络设备支持)
Character devices --->
Ralink GPIO Support
Ralink GPIO LED Support
USB support --->
Support for Host-side USB
USB device filesystem
File systems --->
Kernel automounter support (内核自动挂载支持)
Kernel automounter version 4 support (also supports v3)
Filesystem in Userspace support
Pseudo filesystems --->
/proc file system support
/proc/kcore support
Sysctl support (/proc/sys)
sysfs file system support
Library Configuration
Library Configuration ---> (选择需要的Lib库)
Network Applications ---> (选择需要的网络相关软件)
storage(enable chmod, fdisk in busybox)
proftpd (FTP Server)
iptables
openssl
pppd
l2tp client
pptp
uvc_stream
Miscellaneous Applications --->
busybox
mtd write
Proprietary Application --->
NVRAM
GPIO
Other configurations
Busybox Settings --->
Build Options --->
Build BusyBox as a static binary (no shared libs) (编译成静态文件)
Other choices are as needed. The basic choices of uclibc configuration and uclibc + + configuration are the default ones.
Compile
make dep
make
After compilation, you can find the root image image file in the source / images directory, and the file system exists in the source / romfs directory.
File system modification of Ralink SDK
Just compiling the firmware can not meet our requirements, but also can modify the startup script and add our own files. Open the makefile in the source / vendors / Ralink / rt3052 directory to see that it creates a file directory system and copies some required files into it:
Then we can edit our own file system by modifying the makefile and the files in the directory. The following files can be modified as needed:
rcS: 启动脚本
inittab: init进程配置文件
motd: Ralink图标
fstab:文件系统信息
RT2860_default_vlan:nvram默认配置文件
Add the directory after romfs? Dirs, and add the file after $(romfsinst) / etc? Ro / MOTD (note that the file here needs to be placed in the source / vendors / Ralink / rt3052 directory):
Check the makefile in the source / user / rt2880 "app / scripts directory to find that it has configured the executable and script files in the / SBIN Directory:
To add scripts, just copy them to the source / user / rt2880 "app / scripts directory.
Start script configuration
My startup script configuration is as follows and commented for reference only:
#!/bin/sh
mount -a #挂载所有的文件系统,在fstab文件中有配置
mkdir -p /var/run
cat /etc_ro/motd
# Linux 2.6 uses udev instead of devfs, we have to create static dev node by myself
# 创建静态dev节点
mounted=`mount | grep mdev | wc -l`
if [ $mounted -eq 0 ]; then
mount -t ramfs mdev /dev
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mdev -s
fi
# 创建设备文件
mknod /dev/spiS0 c 217 0
mknod /dev/i2cM0 c 218 0
mknod /dev/rdm0 c 254 0
mknod /dev/flash0 c 200 0
mknod /dev/swnat0 c 210 0
mknod /dev/hwnat0 c 220 0
mknod /dev/acl0 c 230 0
mknod /dev/ac0 c 240 0
mknod /dev/mtr0 c 250 0
mknod /dev/nvram c 251 0
mknod /dev/gpio c 252 0
mknod /dev/PCM c 233 0
mknod /dev/I2S c 234 0
echo "# <device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]" > /etc/mdev.conf
echo "# The special characters have the meaning:" >> /etc/mdev.conf
echo "# @ Run after creating the device." >> /etc/mdev.conf
echo "# $ Run before removing the device." >> /etc/mdev.conf
echo "# * Run both after creating and before removing the device." >> /etc/mdev.conf
echo "sd[a-z][1-9] 0:0 0660 */sbin/automount.sh \$MDEV" >> /etc/mdev.conf
#enable usb hot-plug feature
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
# 启动nvram_daemon进程
nvram_daemon&
# 从nvram配置文件中获取用户名和密码并设置系统用户
login=`nvram_get 2860 Login`
pass=`nvram_get 2860 Password`
echo "$login::0:0:Adminstrator:/:/bin/sh" > /etc/passwd
echo "$login:x:0:$login" > /etc/group
chpasswd.sh $login $pass
# audio
pcmcmd -s &
# video
uvc_stream -b &
sleep 2
# Set RT3050 to dump switch mode (restore to no VLAN partition)
switch reg w 14 5555
switch reg w 40 1001
switch reg w 44 1001
switch reg w 48 1001
switch reg w 4c 1
switch reg w 50 2001
switch reg w 70 ffffffff
switch reg w 98 7f7f
switch reg w e4 7f
lan_if="br0"
# lo interface up -- mydlink need it
ifconfig lo up
# setup bridge, lan and wlan interface, and fast forwarding time (setfd, setmaxage)
ifconfig eth2 0.0.0.0
ifconfig ra0 0.0.0.0
brctl addbr br0
brctl addif br0 ra0
brctl addif br0 eth2
brctl setfd br0 1
brctl setmaxage br0 1
# setup wlan enable/disable
gpio wlan 1
# 配置ip地址
ip=`nvram_get 2860 wan_ipaddr`
nm=`nvram_get 2860 wan_netmask`
gw=`nvram_get 2860 wan_gateway`
ifconfig $lan_if $ip netmask $nm
route del default
gpio gw 0.0.0.0
if [ "$gw" == "0.0.0.0" ]; then
gw=""
fi
if [ "$gw" != "" ]; then
route add default gw $gw
gpio gw $gw
else
route add default gw $ip
fi
# 后台启动alphapd服务
web.sh
sleep 3
# 后台运行调度器
killall -q schedule
schedule &
#for telnet debugging
telnetd
#for syslogd
mkdir -p /var/log