D-Link DGS-1250 series
Overview
Devices
Th D-Link DGS-1250 series are Realtek RTL93xx based switches and consist of the following models
- DGS-1250-28X : 24xGBit, 4x SFP+ 10GBit
- DGS-1250-52X : 48xGBit, 4x SFP+ 10GBit
- DGS-1250-28XMP : 24xGBit, 4x SFP+ 10GBit, 370W POE
- DGS-1250-52XMP : 48xGBit, 4x SFP+ 10GBit, 370W POE
Console
The devices have a Cisco style RJ45 serial console with 115200 baud and coding 8N1.
U-Boot
The U-Boot on these switches is quite hidden. The configuration is hardcoded into the bootloader and the U-boot environment partition is empty (all 0xff). The devices normally boot directly into the Switchlinux operating system. No sign of U-Boot is given. To open up the U-Boot proceed as follows.
- Press “&” during boot to enter U-Boot
- Delete silent mode flag with “setenv silent”
- Store hardcoded environment into partiton with “saveenv”
From now on one will see the U-Boot logs during startup. To get the hardcoded U-Boot settings dump the loader partition.
# strings /dev/mtd0 | grep -i boot ... U-Boot 2011.12.(3.3.0.31-13) (Oct 16 2019 - 17:11:31) bootargs=console=ttyS0,115200 boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 bootcmd=mtdparts default; ubi part fs; ubifsmount fs;ubifsload 0x87000000 uImage;bootm 0x87000000; bootdelay=1 ...
root access
By spamming CTRL+C during the boot of the vendor firmware one gets root access to the embedded Linux distro.
Please wait for loading... ^C^C^C^C^C^C # # # dmesg Linux version 3.18.24-18 (mouan_liao@lanbuild02) (gcc version 4.9.4 (switchlinux-1.0-4) ) #3 Mon Mar 25 22:31:47 CST 2019 MIPS: machine is RTL9300 bootconsole [early0] enabled CPU0 revision is: 00019555 (MIPS 34Kc) [cpu0, rtl9300_auto_probe_memsize:274]: AUTO byte_size = 0x10000000 Byte ... /mnt/flash # df Filesystem 1K-blocks Used Available Use% Mounted on devtmpfs 118288 4 118284 0% /dev tmpfs 121632 4 121628 0% /dev/shm tmpfs 121632 0 121632 0% /tmp /dev/ubi0_0 45220 24948 20272 55% /mnt/flash
Flash layout
The 64MB NOR flash chip has the following layout.
root@OpenWrt:~# cat /proc/mtd dev: size erasesize name mtd0: 00100000 00004000 "u-boot" mtd1: 00080000 00004000 "u-boot-env" mtd2: 00080000 00004000 "u-boot-env2" mtd3: 03e00000 00004000 "ubi"
Important! The vendor firmware uses a erasesize of 16K. That is different from OpenWrt 64K.
UBI contents
The last partition contains an UBIFS with the following structure.
+ uImage (initial Linux Linux-3.18.24-18 uImage)
+ switchfs
+ Image1 (encrypted image)
+ Image2 (encrypted image)
+ Config1 (ASCII configuration)
+ Config2 (ASCII configuration)
+ system
+ <several langague files>.lang
+ self-signed.crt
+ self-signed.pem
+ image.ini
+ sys_lang.cfg
+ cfg.ini
+ syslog
Access from within U-Boot
Get mtdparts default and set it as U-boot environment variable.
RTL9300# # mtdparts mtdparts variable not set, see 'help mtdparts' no partitions defined defaults: mtdids : nor0=nor0 mtdparts: mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) RTL9300# # setenv mtdparts mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs)
Look around.
RTL9300# # mtdparts device nor0 <nor0>, # parts = 4 #: name size offset mask_flags 0: uboot 0x00100000 0x00000000 0 1: env 0x00080000 0x00100000 0 2: sys 0x00080000 0x00180000 0 3: fs 0x03e00000 0x00200000 0 active partition: nor0,0 - (uboot) 0x00100000 @ 0x00000000 defaults: mtdids : nor0=nor0 mtdparts: mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) RTL9300# # ubi part fs Creating 1 MTD partitions on "nor0": 0x000000200000-0x000004000000 : "mtd=3" UBI: attaching mtd1 to ubi0 UBI: physical eraseblock size: 16384 bytes (16 KiB) UBI: logical eraseblock size: 16256 bytes UBI: smallest flash I/O unit: 1 UBI: VID header offset: 64 (aligned 64) UBI: data offset: 128 UBI: attached mtd1 to ubi0 UBI: MTD device name: "mtd=3" UBI: MTD device size: 62 MiB UBI: number of good PEBs: 3968 UBI: number of bad PEBs: 0 UBI: max. allowed volumes: 94 UBI: wear-leveling threshold: 4096 UBI: number of internal volumes: 1 UBI: number of user volumes: 1 UBI: available PEBs: 0 UBI: total number of reserved PEBs: 3968 UBI: number of PEBs reserved for bad PEB handling: 0 UBI: max/mean erase counter: 3/1
Access on foreign system
Dump /dev/mtd3 and copy the image to some linux machine. Mount it with
# load modules modprobe -r block2mtd nandsim mtdram ubi ubifs 2>/dev/null modprobe mtdram total_size=65536 erase_size=16 modprobe ubi modprobe ubifs # write image dd if=dgs-1250-mtd3.dd of=/dev/mtd0 # attach image ubiattach /dev/ubi_ctrl -m 0 -O 64 # mount mkdir -p /mnt/ubifs mount -t ubifs ubi0:fs /mnt/ubifs
Boot sequence
Vendor
The switch runs a dual image configuration. The boot sequence basically runs as follows.
- U-Boot starts
- U-Boot mounts ubifs
- U-Boot reads Linux kernel from file uImage inside ubifs
- Linux starts
- Linux mounts ubifs
- Kernel calls loader binary
- depending on current configuration first (Image1) or second firmware image (Image2) is loaded and decrypted
- Inside the decrpyted firmware image there is a executable named “switch”
- This is run and the switch comes alive
OpenWrt
During installation of OpenWrt the boot sequence is adapted so U-Boot can directly boot the kernel from the flash.
- The first 12 MB of flash partition /dev/mtd3 are copied to memory address 0x84000000 (should be sufficient for kernels of any size)
- uImage is started from address 0x84000000
bootcmd 'cp.l 0xb4200000 0x84000000 0x300000; bootm 0x84000000'
Firmware images
DGS-1250 firmware images are encrypted. They have a 512 byte header and multiple OpenSSL encrypted files.
$ binwalk 01_DGS-1250_Run_2_00_013_middle.had DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 512 0x200 OpenSSL encryption, salted, salt: 0x341AA3E4AB8CA371 5134656 0x4E5940 OpenSSL encryption, salted, salt: 0x5511393F1C318CB6 8739408 0x855A50 OpenSSL encryption, salted, salt: 0x378FCCAC861B6BE9 ...
The key to such a firmware archive can be extracted with the following python script.
Inside the archive there are some fields around the encrypted data that describe the content (e.g. data length of each chunk). The length field (big endian) of the first chunk is at offset 12 (0xc) in the header. After carving out the salted files these can be decrypted with
openssl enc -d -aes-256-cbc -md md5 -pass pass:"<key_from_above>" -in salted.data -out decrypted.data
The loader binary and two sample images are stored at https://github.com/plappermaul/realtek-doc/tree/main/DGS-1250
Miscellaneous
Pictures DGS-1250-28X
Vendor bootlog
Linux version 3.18.24-18 (mouan_liao@lanbuild02) (gcc version 4.9.4 (switchlinux-1.0-4) ) #3 Mon Mar 25 22:31:47 CST 2019 MIPS: machine is RTL9300 bootconsole [early0] enabled CPU0 revision is: 00019555 (MIPS 34Kc) [cpu0, rtl9300_auto_probe_memsize:274]: AUTO byte_size = 0x10000000 Byte [cpu0, prom_memory_size_get:378]: Get total memory size by auto probe result [cpu0, prom_memory_size_get:381]: Get dma size from kernel commnad line [cpu0, prom_meminit:429]: DMA size=0xc00000(B) [cpu0, prom_meminit:457]: mem zone0: Base=0x0, size=0xf400000(B) Determined physical RAM map: memory: 0f400000 @ 00000000 (usable) [cpu0, plat_remove_mem_parameter:248]: cmdline=console= boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 console=ttyS0,115200 mem=256M rtk_dma_size=12M, 80436160, 804361de [cpu0, plat_remove_mem_parameter:253]: cmdline=console= boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 console=ttyS0,115200 rtk_dma_size=12M [cpu0, plat_remove_mem_parameter:248]: cmdline=console= boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 console=ttyS0,115200 mem=256M rtk_dma_size=12M, 80431f94, 80432012 [cpu0, plat_remove_mem_parameter:253]: cmdline=console= boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 console=ttyS0,115200 rtk_dma_size=12M Initrd not found or empty - disabling initrd Zone ranges: Normal [mem 0x00000000-0x0f3fffff] HighMem empty Movable zone start for each node Early memory node ranges node 0: [mem 0x00000000-0x0f3fffff] Initmem setup node 0 [mem 0x00000000-0x0f3fffff] On node 0 totalpages: 62464 free_area_init_node: node 0, pgdat 80416940, node_mem_map 81000000 Normal zone: 488 pages used for memmap Normal zone: 0 pages reserved Normal zone: 62464 pages, LIFO batch:15 Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes. Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 pcpu-alloc: [0] 0 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 61976 Kernel command line: console= boardmodel=28 mtdparts=nor0:1M(uboot),512K(env),512K(sys),-(fs) loglevel=1 bootldr=3.3.0.31-13 console=ttyS0,115200 rtk_dma_size=12M PID hash table entries: 1024 (order: 0, 4096 bytes) Dentry cache hash table entries: 32768 (order: 5, 131072 bytes) Inode-cache hash table entries: 16384 (order: 4, 65536 bytes) Writing ErrCtl register=0003aef1 Readback ErrCtl register=0003aef1 Memory: 236580K/249856K available (2994K kernel code, 154K rwdata, 1032K rodata, 6688K init, 167K bss, 13276K reserved, 0K highmem) NR_IRQS:128 console [ttyS0] enabled bootconsole [early0] disabled Calibrating delay loop... 530.43 BogoMIPS (lpj=265216) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) devtmpfs: initialized NET: Registered protocol family 16 SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb NET: Registered protocol family 2 TCP established hash table entries: 2048 (order: 1, 8192 bytes) TCP bind hash table entries: 2048 (order: 3, 40960 bytes) TCP: Hash tables configured (established 2048 bind 2048) TCP: reno registered UDP hash table entries: 256 (order: 1, 12288 bytes) UDP-Lite hash table entries: 256 (order: 1, 12288 bytes) NET: Registered protocol family 1 futex hash table entries: 256 (order: 0, 7168 bytes) msgmni has been set to 462 io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) start plist test end plist test Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled serial8250: ttyS0 at MMIO 0x0 (irq = 39, base_baud = 10764700) is a 16550A serial8250: ttyS1 at MMIO 0x0 (irq = 38, base_baud = 10908700) is a 16550A RTK_SPI_FLASH_MIO driver is bypassed RTK_NORSFG3 driver is used ================================================================= init_luna_nor_spi_map: flash map at 0xb4000000 SPI NOR driver probe... MXIC/C2201A/MMIO32-4/ModeC 4 cmdlinepart partitions found on MTD device nor0 add SPI NOR partition MTD partitions obtained from kernel command line Creating 4 MTD partitions on "nor0": 0x000000000000-0x000000100000 : "uboot" 0x000000100000-0x000000180000 : "env" 0x000000180000-0x000000200000 : "sys" 0x000000200000-0x000004000000 : "fs" ================================================================= ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver rtk_gen1_hcd_cs_init: rtk_gen1_hcd_cs_init()! rtk_gen1_hcd_cs_init: register rtk_gen1_ehci ok! usb_phy_configure_process: usb_phy_configure_process()! rtk_gen1-ehci rtk_gen1-ehci: Realtek On-Chip EHCI Host Controller rtk_gen1-ehci rtk_gen1-ehci: new USB bus registered, assigned bus number 1 rtk_gen1-ehci rtk_gen1-ehci: irq 25, io mem 0x18021000 rtk_gen1-ehci rtk_gen1-ehci: USB 2.0 started, EHCI 1.00 hub 1-0:1.0: USB hub found hub 1-0:1.0: 1 port detected usbcore: registered new interface driver usbtmc usbcore: registered new interface driver usb-storage TCP: cubic registered NET: Registered protocol family 17 Freeing unused kernel memory: 6688K (80418000 - 80aa0000) UBI: attaching mtd3 to ubi0 UBI: scanning is finished UBI: attached mtd3 (name "fs", size 62 MiB) to ubi0 UBI: PEB size: 16384 bytes (16 KiB), LEB size: 16256 bytes UBI: min./max. I/O unit sizes: 1/1, sub-page size 1 UBI: VID header offset: 64 (aligned 64), data offset: 128 UBI: good PEBs: 3968, bad PEBs: 0, corrupted PEBs: 0 UBI: user volume: 1, internal volumes: 1, max. volumes count: 94 UBI: max/mean erase counter: 3/1, WL threshold: 4096, image sequence number: 1654326921 UBI: available PEBs: 0, total reserved PEBs: 3968, PEBs reserved for bad PEB handling: 0 UBI: background thread "ubi_bgt0d" started, PID 698 UBIFS: background thread "ubifs_bgt0_0" started, PID 702 UBIFS: mounted UBI device 0, volume 0, name "fs" UBIFS: LEB size: 16256 bytes (15 KiB), min./max. I/O unit sizes: 8 bytes/8 bytes UBIFS: FS size: 64194944 bytes (61 MiB, 3949 LEBs), journal size 8111744 bytes (7 MiB, 499 LEBs) UBIFS: reserved for root: 0 bytes (0 KiB) UBIFS: media format: w4/r0 (latest is w4/r0), UUID 7FEA79B7-56E5-49B5-893F-03E4342DBF03, big LPT model syslogd started: BusyBox v1.24.1 init: starting pid 730, tty '': '/sbin/mdev -s' NET: Registered protocol family 10 init: starting pid 733, tty '/dev/ttyS0': '/bin/login -f root' login[733]: root login on 'ttyS0' random: nonblocking pool is initialized










