New Xiaomi router AC2100

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.

as soon as mine will arrive I can help testing things!

The settings backup is a tar.gz with two files, cfg_backup.mbu and cfg_backup.des. The des file contains a json string describing which info is in the backup. The mbu file is binary, seems encrypted and only applicable on device with the same serial i would guess.

The web interface doesn't leave much room for exploiting it, they've already patched the known holes. There're not many ways to interact with it, just some wifi and timezone settings. Lots of different json api endpoints you can get info from, but not post. I did just discover it has a different init.html page after a factory reset, to set it up if you don't use the app. I'm going to try poking at that next.

I've not been able to extract all contents of the factory firmware yet. Especially the ubifs is a problem. If someone can upload it somewhere (or point me to a working version of binwalk) that would be very much appreciated.

Ok, so I managed to access the console by changing the bootdelay and fixing the ECC data. I found the official tool to generate the ECC data in the Mediatek APSoC SDK. If your data is the same as mine you can just use my calculated ECC else you have to find the SDK on your own or contact me.

Modified bootdelay with matching ECC

I think this might help:

python Nand-dump-tool.py -i ac2100.bin -o ac2100_clean.bin -I C8D18095 #https://github.com/Hitsxx/NandTool to remove ECC data
binwalk -Me ac2100_clean.bin
cd _ac2100_clean.bin.extracted
ubireader_extract_images A00000.ubi #https://github.com/jrspruitt/ubi_reader to extract ubi image
binwalk -Me ubifs-root/A00000.ubi/img-1106443240_vol-ubi_rootfs.ubifs
2 Likes

Can you recommend a (cheap) Nand programmer?

What about the BOOTP, anyone tried it already?

Really depends. You could go the ultra cheap route and use a Teensy + TSOP48 socket for about 10€ together.

But its more of a DIY solution

If you have a bigger budget or think that you someday might need a programmer for something else you could go with a Tl866ii which supports a lot of different chips and has better software.

Thanks! I go the cheap way :smiley:
The router shipment will take longer anyway - so I will get the programmer parts from china.
Maybe you guys find a way how to bypass the manual programing before it arrives, if not I will give it a try.

Still waiting for my Tl866ii and teensy got delayed with the Year of the Rat..

Here is what I extracted (for the rm2100)

Would you mind sharing the the config files?

Config file:

I tried to upload initframs image from mir3g. It failed because router is checking uploaded image.

TRX MAGIC error!
Header check error!
Image verify failed!

Bootp failed log

#Reset_MT7530
set LAN/WAN WLLLL

NetTxPacket = 0x87FE4200

KSEG1ADDR(NetTxPacket) = 0xA7FE4200

NetLoop,call eth_halt !

NetLoop,call eth_init !
Trying Eth0 (10/100-M)

Waitting for RX_DMA_BUSY status Start... done

ETH_STATE_ACTIVE!!
BOOTP broadcast 1

NetOurIP

NetOurIP
BOOTP broadcast 2
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 3
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 3
DHCP: state=SELECTING bp_file: "miwifi.bin"
TRANSITIONING TO REQUESTING STATE
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: miwifi.bin
DhcpSendRequestPkt: Sending DHCPREQUEST
Transmitting DHCPREQUEST packet: len = 343
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 4
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 4
DHCP State: REQUESTING
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: miwifi.bin
DHCP client bound to address 192.168.1.50
TFTP from server 192.168.1.2; our IP address is 192.168.1.50
Filename 'miwifi.bin'.

TIMEOUT_COUNT=10,Load address: 0x82000000
Loading: Got ARP REPLY, set server/gtwy eth addr (00:27:13:69:06:04)
Got it
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
##########################################
done
Bytes transferred = 3540915 (3607b3 hex)
LoadAddr=82000000 NetBootFileXferSize= 003607b3
TRX MAGIC error!
Header check error!
Image verify failed!
========Upgrade fail!========

Bootp factory fimware uploading is working.

Factory firmware bootp log

#Reset_MT7530
set LAN/WAN WLLLL

NetTxPacket = 0x87FE4200

KSEG1ADDR(NetTxPacket) = 0xA7FE4200

NetLoop,call eth_halt !

NetLoop,call eth_init !
Trying Eth0 (10/100-M)

Waitting for RX_DMA_BUSY status Start... done

ETH_STATE_ACTIVE!!
BOOTP broadcast 1

NetOurIP
BOOTP broadcast 2

NetOurIP

NetOurIP
BOOTP broadcast 3
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 3
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 3
DHCP: state=SELECTING bp_file: "miwifi.bin"
TRANSITIONING TO REQUESTING STATE
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: miwifi.bin
DhcpSendRequestPkt: Sending DHCPREQUEST
Transmitting DHCPREQUEST packet: len = 343
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 4
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 4
DHCP State: REQUESTING
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: miwifi.bin
DHCP client bound to address 192.168.1.50
TFTP from server 192.168.1.2; our IP address is 192.168.1.50
Filename 'miwifi.bin'.

TIMEOUT_COUNT=10,Load address: 0x82000000
Loading: Got ARP REPLY, set server/gtwy eth addr (00:27:13:69:06:04)
Got it
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
######################################################Got ARP REQUEST, return our IP
###########
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#############################################################
done
Bytes transferred = 17284660 (107be34 hex)
LoadAddr=82000000 NetBootFileXferSize= 0107be34
CRC verify success!
RSA signature verify success!
..ranand_erase: start:80000, len:20000
..Done!
done
Upgrade xiaoqiang_version...
Upgrade uImage.bin...
ranand_erase: start:200000, len:20000
..ranand_erase: start:220000, len:20000
..ranand_erase: start:240000, len:20000
..ranand_erase: start:260000, len:20000
..ranand_erase: start:280000, len:20000
..ranand_erase: start:2a0000, len:20000
..ranand_erase: start:2c0000, len:20000
..ranand_erase: start:2e0000, len:20000
..ranand_erase: start:300000, len:20000
..ranand_erase: start:320000, len:20000
..ranand_erase: start:340000, len:20000
..ranand_erase: start:360000, len:20000
..ranand_erase: start:380000, len:20000
..ranand_erase: start:3a0000, len:20000
..ranand_erase: start:3c0000, len:20000
..ranand_erase: start:3e0000, len:20000
..ranand_erase: start:400000, len:20000
..ranand_erase: start:420000, len:20000
..ranand_erase: start:440000, len:20000
..ranand_erase: start:460000, len:20000
..ranand_erase: start:480000, len:20000
..ranand_erase: start:4a0000, len:20000
..ranand_erase: start:4c0000, len:20000
..ranand_erase: start:4e0000, len:20000
..ranand_erase: start:500000, len:20000
....ranand_erase: start:520000, len:20000
.(5192)offs=5373952 piece=0 piece_size=113231 rc=0
Done!
ranand_erase: start:600000, len:20000
..ranand_erase: start:620000, len:20000
..ranand_erase: start:640000, len:20000
..ranand_erase: start:660000, len:20000
..ranand_erase: start:680000, len:20000
..ranand_erase: start:6a0000, len:20000
..ranand_erase: start:6c0000, len:20000
..ranand_erase: start:6e0000, len:20000
..ranand_erase: start:700000, len:20000
..ranand_erase: start:720000, len:20000
..ranand_erase: start:740000, len:20000
..ranand_erase: start:760000, len:20000
..ranand_erase: start:780000, len:20000
..ranand_erase: start:7a0000, len:20000
..ranand_erase: start:7c0000, len:20000
..ranand_erase: start:7e0000, len:20000
..ranand_erase: start:800000, len:20000
..ranand_erase: start:820000, len:20000
..ranand_erase: start:840000, len:20000
..ranand_erase: start:860000, len:20000
..ranand_erase: start:880000, len:20000
..ranand_erase: start:8a0000, len:20000
..ranand_erase: start:8c0000, len:20000
..ranand_erase: start:8e0000, len:20000
..ranand_erase: start:900000, len:20000
....ranand_erase: start:920000, len:20000
.(5192)offs=9568256 piece=0 piece_size=113231 rc=0
Done!
proc_xqimage.c xqimage_upgrade 526 start:0x820002a4,subh->flash_addr:0xffffffff,len:0x33ba4f
Upgrade root.ubi...
ranand_erase: start:a00000, len:3400000
................................................................................................................................................................................................................................................................................................................................................................................................................................ranand_erase: start:a00000, len:20000
..ranand_erase: start:a20000, len:20000
..ranand_erase: start:a40000, len:20000
..ranand_erase: start:a60000, len:20000
..ranand_erase: start:a80000, len:20000
..ranand_erase: start:aa0000, len:20000
..ranand_erase: start:ac0000, len:20000
..ranand_erase: start:ae0000, len:20000
..ranand_erase: start:b00000, len:20000
..ranand_erase: start:b20000, len:20000
..ranand_erase: start:b40000, len:20000
..ranand_erase: start:b60000, len:20000
..ranand_erase: start:b80000, len:20000
..ranand_erase: start:ba0000, len:20000
..ranand_erase: start:bc0000, len:20000
..ranand_erase: start:be0000, len:20000
..ranand_erase: start:c00000, len:20000
..ranand_erase: start:c20000, len:20000
..ranand_erase: start:c40000, len:20000
..ranand_erase: start:c60000, len:20000
..ranand_erase: start:c80000, len:20000
..ranand_erase: start:ca0000, len:20000
..ranand_erase: start:cc0000, len:20000
..ranand_erase: start:ce0000, len:20000
..ranand_erase: start:d00000, len:20000
..ranand_erase: start:d20000, len:20000
..ranand_erase: start:d40000, len:20000
..ranand_erase: start:d60000, len:20000
..ranand_erase: start:d80000, len:20000
..ranand_erase: start:da0000, len:20000
..ranand_erase: start:dc0000, len:20000
..ranand_erase: start:de0000, len:20000
..ranand_erase: start:e00000, len:20000
..ranand_erase: start:e20000, len:20000
..ranand_erase: start:e40000, len:20000
..ranand_erase: start:e60000, len:20000
..ranand_erase: start:e80000, len:20000
..ranand_erase: start:ea0000, len:20000
..ranand_erase: start:ec0000, len:20000
..ranand_erase: start:ee0000, len:20000
..ranand_erase: start:f00000, len:20000
..ranand_erase: start:f20000, len:20000
..ranand_erase: start:f40000, len:20000
..ranand_erase: start:f60000, len:20000
..ranand_erase: start:f80000, len:20000
..ranand_erase: start:fa0000, len:20000
..ranand_erase: start:fc0000, len:20000
..ranand_erase: start:fe0000, len:20000
..ranand_erase: start:1000000, len:20000
..ranand_erase: start:1020000, len:20000
..ranand_erase: start:1040000, len:20000
..ranand_erase: start:1060000, len:20000
..ranand_erase: start:1080000, len:20000
..ranand_erase: start:10a0000, len:20000
..ranand_erase: start:10c0000, len:20000
..ranand_erase: start:10e0000, len:20000
..ranand_erase: start:1100000, len:20000
..ranand_erase: start:1120000, len:20000
..ranand_erase: start:1140000, len:20000
..ranand_erase: start:1160000, len:20000
..ranand_erase: start:1180000, len:20000
..ranand_erase: start:11a0000, len:20000
..ranand_erase: start:11c0000, len:20000
..ranand_erase: start:11e0000, len:20000
..ranand_erase: start:1200000, len:20000
..ranand_erase: start:1220000, len:20000
..ranand_erase: start:1240000, len:20000
..ranand_erase: start:1260000, len:20000
..ranand_erase: start:1280000, len:20000
..ranand_erase: start:12a0000, len:20000
..ranand_erase: start:12c0000, len:20000
..ranand_erase: start:12e0000, len:20000
..ranand_erase: start:1300000, len:20000
..ranand_erase: start:1320000, len:20000
..ranand_erase: start:1340000, len:20000
..ranand_erase: start:1360000, len:20000
..ranand_erase: start:1380000, len:20000
..ranand_erase: start:13a0000, len:20000
..ranand_erase: start:13c0000, len:20000
..ranand_erase: start:13e0000, len:20000
..ranand_erase: start:1400000, len:20000
..ranand_erase: start:1420000, len:20000
..ranand_erase: start:1440000, len:20000
..ranand_erase: start:1460000, len:20000
..ranand_erase: start:1480000, len:20000
..ranand_erase: start:14a0000, len:20000
..ranand_erase: start:14c0000, len:20000
..ranand_erase: start:14e0000, len:20000
..ranand_erase: start:1500000, len:20000
..ranand_erase: start:1520000, len:20000
..ranand_erase: start:1540000, len:20000
..ranand_erase: start:1560000, len:20000
..ranand_erase: start:1580000, len:20000
..ranand_erase: start:15a0000, len:20000
..ranand_erase: start:15c0000, len:20000
..ranand_erase: start:15e0000, len:20000
..ranand_erase: start:1600000, len:20000
..ranand_erase: start:1620000, len:20000
..ranand_erase: start:1640000, len:20000
..ranand_erase: start:1660000, len:20000
..ranand_erase: start:1680000, len:20000
..ranand_erase: start:16a0000, len:20000
..ranand_erase: start:16c0000, len:20000
..ranand_erase: start:16e0000, len:20000
..ranand_erase: start:1700000, len:20000
..ranand_erase: start:1720000, len:20000
..Done!
ranand_erase: start:2400000, len:20000
..ranand_erase: start:2420000, len:20000
..ranand_erase: start:2440000, len:20000
..ranand_erase: start:2460000, len:20000
..ranand_erase: start:2480000, len:20000
..ranand_erase: start:24a0000, len:20000
..ranand_erase: start:24c0000, len:20000
..ranand_erase: start:24e0000, len:20000
..ranand_erase: start:2500000, len:20000
..ranand_erase: start:2520000, len:20000
..ranand_erase: start:2540000, len:20000
..ranand_erase: start:2560000, len:20000
..ranand_erase: start:2580000, len:20000
..ranand_erase: start:25a0000, len:20000
..ranand_erase: start:25c0000, len:20000
..ranand_erase: start:25e0000, len:20000
..ranand_erase: start:2600000, len:20000
..ranand_erase: start:2620000, len:20000
..ranand_erase: start:2640000, len:20000
..ranand_erase: start:2660000, len:20000
..ranand_erase: start:2680000, len:20000
..ranand_erase: start:26a0000, len:20000
..ranand_erase: start:26c0000, len:20000
..ranand_erase: start:26e0000, len:20000
..ranand_erase: start:2700000, len:20000
..ranand_erase: start:2720000, len:20000
..ranand_erase: start:2740000, len:20000
..ranand_erase: start:2760000, len:20000
..ranand_erase: start:2780000, len:20000
..ranand_erase: start:27a0000, len:20000
..ranand_erase: start:27c0000, len:20000
..ranand_erase: start:27e0000, len:20000
..ranand_erase: start:2800000, len:20000
..ranand_erase: start:2820000, len:20000
..ranand_erase: start:2840000, len:20000
..ranand_erase: start:2860000, len:20000
..ranand_erase: start:2880000, len:20000
..ranand_erase: start:28a0000, len:20000
..ranand_erase: start:28c0000, len:20000
..ranand_erase: start:28e0000, len:20000
..ranand_erase: start:2900000, len:20000
..ranand_erase: start:2920000, len:20000
..ranand_erase: start:2940000, len:20000
..ranand_erase: start:2960000, len:20000
..ranand_erase: start:2980000, len:20000
..ranand_erase: start:29a0000, len:20000
..ranand_erase: start:29c0000, len:20000
..ranand_erase: start:29e0000, len:20000
..ranand_erase: start:2a00000, len:20000
..ranand_erase: start:2a20000, len:20000
..ranand_erase: start:2a40000, len:20000
..ranand_erase: start:2a60000, len:20000
..ranand_erase: start:2a80000, len:20000
..ranand_erase: start:2aa0000, len:20000
..ranand_erase: start:2ac0000, len:20000
..ranand_erase: start:2ae0000, len:20000
..ranand_erase: start:2b00000, len:20000
..ranand_erase: start:2b20000, len:20000
..ranand_erase: start:2b40000, len:20000
..ranand_erase: start:2b60000, len:20000
..ranand_erase: start:2b80000, len:20000
..ranand_erase: start:2ba0000, len:20000
..ranand_erase: start:2bc0000, len:20000
..ranand_erase: start:2be0000, len:20000
..ranand_erase: start:2c00000, len:20000
..ranand_erase: start:2c20000, len:20000
..ranand_erase: start:2c40000, len:20000
..ranand_erase: start:2c60000, len:20000
..ranand_erase: start:2c80000, len:20000
..ranand_erase: start:2ca0000, len:20000
..ranand_erase: start:2cc0000, len:20000
..ranand_erase: start:2ce0000, len:20000
..ranand_erase: start:2d00000, len:20000
..ranand_erase: start:2d20000, len:20000
..ranand_erase: start:2d40000, len:20000
..ranand_erase: start:2d60000, len:20000
..ranand_erase: start:2d80000, len:20000
..ranand_erase: start:2da0000, len:20000
..ranand_erase: start:2dc0000, len:20000
..ranand_erase: start:2de0000, len:20000
..ranand_erase: start:2e00000, len:20000
..ranand_erase: start:2e20000, len:20000
..ranand_erase: start:2e40000, len:20000
..ranand_erase: start:2e60000, len:20000
..ranand_erase: start:2e80000, len:20000
..ranand_erase: start:2ea0000, len:20000
..ranand_erase: start:2ec0000, len:20000
..ranand_erase: start:2ee0000, len:20000
..ranand_erase: start:2f00000, len:20000
..ranand_erase: start:2f20000, len:20000
..ranand_erase: start:2f40000, len:20000
..ranand_erase: start:2f60000, len:20000
..ranand_erase: start:2f80000, len:20000
..ranand_erase: start:2fa0000, len:20000
..ranand_erase: start:2fc0000, len:20000
..ranand_erase: start:2fe0000, len:20000
..ranand_erase: start:3000000, len:20000
..ranand_erase: start:3020000, len:20000
..ranand_erase: start:3040000, len:20000
..ranand_erase: start:3060000, len:20000
..ranand_erase: start:3080000, len:20000
..ranand_erase: start:30a0000, len:20000
..ranand_erase: start:30c0000, len:20000
..ranand_erase: start:30e0000, len:20000
..ranand_erase: start:3100000, len:20000
..ranand_erase: start:3120000, len:20000
..Done!
proc_xqimage.c xqimage_upgrade 526 start:0x8233bd24,subh->flash_addr:0xffffffff,len:0xd40000
..ranand_erase: start:80000, len:20000
..Done!
done
========Upgrade success!========
..ranand_erase: start:80000, len:20000
..Done!
done

1 Like

would be interesting to see what happens if you exchange the header of the 3g with the one for the ac2100.

It doesn't work. Even one bit change in factory firmware stops upgrade. After downloading image from bootp router checks CRC and RSA signature of the image.

1 Like