网友求助的 4G 工业路由

拆解

正面

背面

板上已经标注了 TTL 引脚定义, 但是 uboot 没有输出

硬件版本号 v40

硬件信息

  • SoC: MediaTek MT7628NN
  • Flash: 16 MB
  • RAM: 128 MB
  • 电源: DC 5V-36V 1.5A
  • 以太网: 1x WAN (需要自己焊), 1x LAN [10/100 Mbps]
  • 无线: 802.11n 2.4g-only (原厂固件没开 已测试能用 建议焊天线)
  • LED:
    System/Power (RUN): GPIO/37 active-low
    Modem: GPIO/3 active-low
    RF (Modem Signal): GPIO/2 active-low
  • 按钮:
    WPS / RESET: GPIO/11 active-low
  • UART: 1x UART on PCB - 115200 8N1
  • Serial / COM: 1X RS232/RS485 on board (GPIO/6 hi:RS485 lo:RS232)
  • GPIO 看门狗: GPIO/0 mode=toggle timeout=1s
  • Modem: 1x 内置板载模块 (Power: GPIO/4 active-high)
  • PCIe: 1x miniPCIe for modem (需要自己焊)
  • SIM Slots: 1x SIM Slots

固件分析

原厂 Web UI

Factory Web UI

颇有 DD-wrt 风味

原厂 Uboot Web UI

无 DHCP
静态IP 192.168.1.1

Uboot Web UI

根据 H8922 的经验, 铁定有校验, 根据提取的 uboot 来看, 算法一模一样...

OS 版本

内核版本 4.9.87 还挺新

root@router:/etc# cat openwrt_release
DISTRIB_ID='OpenWrt'
DISTRIB_RELEASE='SNAPSHOT'
DISTRIB_REVISION='r6489-d11aa1d4af'
DISTRIB_TARGET='ramips/mt76x8'
DISTRIB_ARCH='mipsel_24kc'
DISTRIB_DESCRIPTION='OpenWrt SNAPSHOT r6489-d11aa1d4af'
DISTRIB_TAINTS='no-all busybox'
root@router:/etc# cat openwrt_version
r6489-d11aa1d4af

内核命令行

root@router:/tmp/mtd# cat /proc/cmdline
console=ttyS2,115200 rootfstype=squashfs,jffs2 bootversion=7.2.3

分区布局

root@router:~# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00030000 00010000 "u-boot"
mtd1: 00010000 00010000 "u-boot-env"
mtd2: 00010000 00010000 "factory"
mtd3: 00a80000 00010000 "firmware"
mtd4: 001cf9bd 00010000 "kernel"
mtd5: 008b0643 00010000 "rootfs"
mtd6: 000b0000 00010000 "rootfs_data"
mtd7: 00080000 00010000 "config_partition"
mtd8: 00400000 00010000 "patch_partition"

虽然有 eeprom 的 factory 分区, 但是并没有使用, 网卡MAC 存储在 /etc/hdconfig/systeminfo/system.info/etc/system.info 文件内

GPIO

root@router:/# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/10000600.gpio, 10000600.gpio:
 gpio-0   (                    |wdt_rst             ) out hi
 gpio-1   (                    |hub_rst             ) out hi
 gpio-2   (                    |modem_signal1       ) out hi
 gpio-3   (                    |modem               ) out hi
 gpio-4   (                    |3g_pwr              ) out hi
 gpio-5   (                    |simcard_select      ) out lo
 gpio-6   (                    |serial_select       ) out hi
 gpio-11  (                    |rst_key             ) in  hi

gpiochip1: GPIOs 32-63, parent: platform/10000600.gpio, 10000600.gpio:
 gpio-36  (                    |gps_oe              ) out hi
 gpio-37  (                    |led_sys             ) out lo
 gpio-38  (                    |3g2_pwr             ) out hi
 gpio-44  (                    |led_wifi            ) out hi

gpiochip2: GPIOs 64-95, parent: platform/10000600.gpio, 10000600.gpio:
LED GPIO 为 ?, 上述结果已经过 dts 修正

使用 GPIO 看门狗而不是 MT7628 内置的看门狗

WIFI LED 无效, 板子 DTS 是 公版 evb/eval 修改的

端口监听状态

root@router:/tmp/mtd# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:5188            0.0.0.0:*               LISTEN      1648/telnetd
tcp        0      0 0.0.0.0:2601            0.0.0.0:*               LISTEN      1478/zebra
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1649/lighttpd
tcp        0      0 0.0.0.0:53              0.0.0.0:*               LISTEN      1957/dnsmasq
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      2024/dropbear
tcp        0      0 0.0.0.0:23              0.0.0.0:*               LISTEN      1641/cli
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      9870/dropbear

ROOT 密码 (OpenSSH/Telnet)

ROOT 密码是 superzxmn

OpenSSH 端口 TCP 22
Telnet 端口 TCP 5188

Telnet 23 端口被原厂定制的 CLI 程序吃了, 密码 super

CVE 链接, 同样适用于本设备

固件加密

  • 内层加密

XOR 配合 MD5 Salt 校验

package main

import (
    "crypto/md5"
    "os"
)

const (
    salt     = "hdm2mfreewifi"
    salt_len = len(salt)
)

func main() {
    data, err := os.ReadFile("input.bin")
    if err != nil {
        panic(err.Error())
    }

    encrypted := encrypt(data)
    output := addMD5(encrypted)

    os.WriteFile("encrypted.bin", output, 0644)
}

func addMD5(data []byte) []byte {
    hash := md5.New()

    hash.Write([]byte(salt))
    hash.Write(data)

    return hash.Sum(data)
}

func encrypt(data []byte) []byte {
    dataLen := len(data)
    fixedKey := dataLen / (salt_len + 1)
    encrypted := make([]byte, len(data))
    copy(encrypted, data)

    for i := range encrypted {
        key := (dataLen + i) - fixedKey
        encrypted[i] ^= byte(key)
    }

    return encrypted
}
使用 IDA 逆向原厂固件 /usr/sbin/encrypt 文件

刷写固件

OpenWRT PR地址
OpenWRT SNAPSHOT 预编译固件 - openwrt-ramips-mt76x8-hongdian_h7920-v40-squashfs-sysupgrade.bin

刷写 Breed

刷了就死循环重启, 必砖!
应该是 GPIO 看门狗没喂狗导致的

通过 UART 进入 UBoot 刷写

UBoot 没有使用 UART, 不知道是否重定向到 RS232/RS485 了

直接刷写镜像

通过 OpenSSH 22 / Telnet 5188 连接到设备 192.168.8.1, 密码为 superzxmn

把固件拉到设备的 /tmp 目录下

  • 使用 scp / sftp
  • 使用 python -m http.server 起个 http 服务器, 搭配 wget
mtd -r write openwrt-ramips-mt76x8-hongdian_h7920-v40-squashfs-sysupgrade.bin firmware

等待设备重启, 第一次比较慢

由于分区布局不一样, 建议刷完以后通过 LuCI 不保存设置再刷一次

原厂固件下载

H7920_v40.zip

最后修改:2025 年 02 月 11 日
如果觉得我的文章对你有用,请随意赞赏