New Xiaomi router AC2100

would be also interested in this and how the injection would work - command wise ...

@dolfandringa, @thorsten97

Its going to be a bit harder to find injection weakpoints, as they use custom compiled lua code, instead of the old lua scripts. They seem to also use a custom luaL_loadfile implementation to load them and switch some bytes. Need to dig into it deeper.

But, it looks like if a ota firmware fails for some reason, console access can be enabled, with some button test points. Gotta dive into the binaries and look deeper - need to dig deeper!

/lib/preinit/31_restore_nvram
───────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: squashfs-root/lib/preinit/31_restore_nvram
───────┼────────────────────────────────────────────────────────
   1   │ #!/bin/sh
   2   │
   3   │ . /lib/functions.sh
   4   │
   5   │ xqdefaults="/usr/share/xiaoqiang/xiaoqiang-defaults.txt"
   6   │ hwv="`/sbin/hwversion`"
   7   │ do_xiaoqiang_defaults() {
   8   │     cat "${xqdefaults}" | while read line
   9   │     do
  10   │             nvram set "$line"
  11   │     done
  12   │ }
  13   │
  14   │
  15   │ do_nvram_corrupt() {
  16   │     cat "${xqdefaults}" | while read line
  17   │     do
  18   │         nvram set "$line"
  19   │     done
  20   │ }
  21   │
  22   │ do_flag_override() {
  23   │     local flag="$1"
  24   │     b_val=`bdata get $flag`
  25   │     n_val=`nvram get $flag`
  26   │     [ "$b_val" = "$n_val" ] && return 0
  27   │     [ "$b_val" = "1" ] && nvram set "$flag"=1
  28   │ }
  29   │
  30   │ flag_override() {
  31   │     do_flag_override uart_en
  32   │     do_flag_override ssh_en
  33   │     do_flag_override telnet_en
  34   │     do_flag_override boot_wait
  35   │ }
  36   │
  37   │ do_set_default_ssid() {
  38   │     num=`nvram get wl1_ssid | cut -b 7-10`
  39   │     temp=0x"$num"
  40   │     newnum="000"`printf "%x\n" $((0xffff-$temp))`
  41   │     pos=`expr length $newnum - 4`
  42   │     newnum=`echo ${newnum:$pos:4} | tr [a-z] [A-Z]`
  43   │     ssid2G=`nvram get wl1_ssid`
  44   │     result2G=`echo $ssid2G"_"$newnum`
  45   │     nvram set wl1_ssid=$result2G
  46   │
  47   │     has5G=`uci get misc.wireless.if_5G 2>/dev/null`
  48   │
  49   │     # D01 2/5G same ssid
  50   │     suf="_5G"
  51   │     model="`cat /proc/xiaoqiang/model`"
  52   │     [ "$model" = "D01" ] && {
  53   │         suf=""
  54   │     }
  55   │
  56   │     if [ -n "$has5G" ]; then
  57   │         ssid5G=`nvram get wl0_ssid | cut -b -10`
  58   │         result5G=`echo ${ssid5G}"_"${newnum}${suf}`
  59   │         nvram set wl0_ssid=$result5G
  60   │     fi
  61   │ }
  62   │
  63   │
  64   │ restore_nvram () {
  65   │     restore=`nvram get restore_defaults`
  66   │     if [ "$restore" = "1" ]; then
  67   │         flag_name=`uci get misc.mount_bind_etc.flag_name`
  68   │         nvram set $flag_name=1
  69   │         mtd erase overlay
  70   │         rec_mtd=$(find_mtd_part cfg_bak)
  71   │         [ -n "$rec_mtd" ] && mtd erase cfg_bak
  72   │     fi
  73   │
  74   │     ft_mode=`cat /proc/xiaoqiang/ft_mode`
  75   │     if [ "$ft_mode" != "1" ]; then
  76   │         sn=`nvram get SN`
  77   │         wl1_ssid=`nvram get wl1_ssid`
  78   │         countrycode=`nvram get CountryCode`
  79   │         if [ -z "$sn" -o -z "$wl1_ssid" -o -z "$countrycode" ]; then
  80   │             nvram_corrupt=1
  81   │         fi
  82   │     fi
  83   │
  84   │     # skip restore wifi radio flag from defaults if factory mode
  85   │     if [ "$ft_mode" = "1" ]; then
  86   │         wl1_val=`nvram get wl1_radio`
  87   │         wl0_val=`nvram get wl0_radio`
  88   │     fi
  89   │
  90   │     #restore: 1, 恢复出厂设置;2,ota升级
  91   │     #nvram_corrupt: 1, nvram被破坏
  92   │     if [ "$nvram_corrupt" = "1"  ]; then
  93   │         do_nvram_corrupt
  94   │         bdata sync
  95   │         nvram set nvram_corrupt=1
  96   │     fi
  97   │
  98   │     # restore to factory setting
  99   │     if [ "$restore" = "1" ]; then
 100   │         nvram unset nvram_corrupt
 101   │         nvram clear /usr/share/xiaoqiang/xiaoqiang-reserved.txt
 102   │         do_xiaoqiang_defaults
 103   │         bdata sync
 104   │         do_set_default_ssid
 105   │     fi
 106   │
 107   │     # OTA upgrade
 108   │     if [ "$restore" = "2" ]; then
 109   │         do_xiaoqiang_defaults
 110   │         flag_override
 111   │     fi
 112   │
 113   │     if [ "$ft_mode" = "1" ]; then
 114   │         [  "$wl1_val" != "" -a -n "$wl1_val" ] && nvram set wl1_radio=$wl1_val
 115   │         [  "$wl0_val" != "" -a -n "$wl0_val" ] && nvram set wl0_radio=$wl0_val
 116   │     fi
 117   │
 118   │     nvram commit
 119   │ }
 120   │
 121   │ boot_hook_add preinit_main restore_nvram
───────┴────────────────────────────────────────────────────────                          
1 Like

I think if this script is run, and 5G SSID is set to

something123 ; telnetd ; something456

there is a chance that telnetd could be executed

1 Like

that seems pretty promising to me too. also more user-friendly than physically changing the bits on NAND.

i guess the question is "what is the default action?" to tftp-boot or to flash-from-tftp as in:

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.

if i were designing it, i'd probably have "option 1" be the default. (but then... who knows what sicks minds are out there).

given that this is a MT7621 with 128MB RAM and 128MB NAND, i'd probably try the initramfs.bin for the MIR3Gv2 for starters (it might keel over, it might not. i bet it will boot and get to the point where it starts probing for the SPI ;)). but porting this should be a real breeze. the real question is whether the "holding reset while booting" is going to work or not.

anyone feeling up to try this? (looks like we'll need to configure bootp+tftp server... not rocket science). i know at least some of you out there have openwrt routers :wink:

https://wiki.commotionwireless.net/doku.php/development_resources/router/tftp_bootp_server_setup

FWIW, here's (apparently) what worked for MIR3

  * http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/web/home#router
  
  * http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/xqnetwork/set_wifi_ap?ssid=Xiaomi&encryption=NONE&enctype=NONE&channel=1%3Bnvram%20set%20ssh%5Fen%3D1%3B%20nvram%20commit
  
  * http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/xqnetwork/set_wifi_ap?ssid=Xiaomi&encryption=NONE&enctype=NONE&channel=1%3Bsed%20%2Di%20%22%3Ax%3AN%3As%2Fif%20%5C%5B%2E%2A%5C%3B%20then%5Cn%2E%2Areturn%200%5Cn%2E%2Afi%2F%23tb%2F%3Bb%20x%22%20%2Fetc%2Finit.d%2Fdropbear
  
  * http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/xqnetwork/set_wifi_ap?ssid=Xiaomi&encryption=NONE&enctype=NONE&channel=1%3B%2Fetc%2Finit.d%2Fdropbear%20start
  
  * http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/xqsystem/set_name_password?oldPwd=<OLD_PASSWORD>&newPwd=<NEW_PASSWORD>

source: https://openwrt.org/toh/xiaomi/mir3

as a guy who discovered another xiaomi device a few days ago (miwifi mesh), i can say that probably no telnetd is available inside the stock firmware
telnetd busybox applet for my device never run, no matter which value telnet_en 0 or 1, it just start and exit, probably telnet code replaced with dummy {} to prevent any kind of enabling it.
also no dropbear included in "stable" firmware usually, so uart is a single way to access device from inside, but as transmit to router disabled by default, you need to force it into tftp recovery mode using reset buttons and interrupt first boot at u-boot, enable uart_en, boot to stock firmware and modify any startup script to set uart_en to 1 at every boot (for example you can use /etc/rc.local)
to get a working telnetd, you need standalone static busybox binary with telnetd compiled for your target arch

nice!

i was just looking at the "miwifi mesh" forum, and i saw that you had managed to tftp boot but it wasn't clear what you were doing... it looks like you tftp booted the official firmware (and that did a lot of stuff) but it also looked like you tftp booted random initramfs images?

i'm asking because if you were able to boot initramfs images (ie, not only xiaomi-signed/verified binaries) then this should be a breeze.

as i said before, tftp recovery mode was required to get uart trasmit access (it enabled only first time after recovery), so after ive got working serial, ive booted initramfs images using bootp/bootm commands, no image signing required

1 Like

I've managed to flash the factory firmware using tftp but still unable to do anything at the uboot prompt at first boot :frowning:

And you still cant access command prompt at first boot after recovery?

I "binwalked" through the firmwareupdate file for the router and there is at least a link from telnetd to busybox:

thorsten@vsdaads:~/MOD/_miwifi_r2100_firmware_64288_2.0.376.bin.extracted/_2E4.extracted/_594080.extracted/cpio-root/usr/sbin$ ls -lh
total 1.6M
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 brctl -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten 4.2K Jan 29 00:12 btnd
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 dnsd -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten 594K Jan 29 00:12 hexdump
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 httpd -> ../../bin/busybox
-rwxr-xr-x 1 thorsten thorsten 883K Jan 29 00:12 mkxqimage
-rwxrwxr-x 1 thorsten thorsten  11K Jan 29 00:12 mtd
-rwxrwxr-x 1 thorsten thorsten  35K Jan 29 00:12 nanddump
-rwxr-xr-x 1 thorsten thorsten 7.5K Jan 29 00:12 nvram
-rwxr-xr-x 1 thorsten thorsten 4.0K Jan 29 00:12 rd
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 telnetd -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten  16K Jan 29 00:12 ubiattach
-rwxrwxr-x 1 thorsten thorsten  47K Jan 29 00:12 ubiformat
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 udhcpd -> ../../bin/busybox
-rwxr-xr-x 1 thorsten thorsten  691 Jan 29 00:12 xqled

My device also had it, but it was dummy

maybe stupid question, but can we alter the firmware in a way and install it, how is this verification / signing working?

We need a private key to sign, but firmware contains only public

I see :frowning:

The update process finishes and when i reapply power it boots as normal with commandline uart_en=0 factory_mode=0

try to press enter very fast several times right after applying power after recovery
Upd, its an mt762x, so press 4 instead of enter

Tried a couple of times, it zooms past the uboot menu so no time to press anything, the delay must be disabled.

Maybe is it possible to backup and restore config in factory firmware?
If backup is not signed nor encrypted, we could try to play with it

1 Like

Anyone already succeeded in dumping the nand and modifying the bootdelay? I already tried it multiple times without luck. But I just realized that changing the bootdelay would mess up the ECC data of the nand. Anyone got experience how to calculate ECC data for MT7621 chips?
After every 512 bytes of data there are 16 bytes of ECC of which only 52 bits are changing. This plus the ECC requirement of 4bit/528Byte for the nand led me to believe it is a BCH code with m=13 and 4bit correction similar(but not compatible) to this: https://github.com/ak-hard/brcm-nand-bch.