Wi-Fi Range Extender (or repeater if you like the term). The reason why I’ve selected this exact little device is due to its, drumroll, cheapness.
Xiaomi Mi Wi-Fi Range Extender Pro

I’ve decided to continue with a technical blog post, which will be covering the Xiaomi Wi-Fi Range Extender (or repeater if you like the term). The reason why I’ve selected this exact little device is due to its, drumroll, cheapness. Buying secondhand devices is also a good alternative for playing with IoT stuff but due to the virus (and Turkey being a twilight zone where secondhand stuff costs MORE than the brand new version), I’ve put that thought away for now.

Hardware

Anyways, first of all, the hardware itself is in the spotlight. It’s rather simple as you might expect. Like flash memory, a Macronix MX25L1606E is present which can hold 2MB of data. The odd thing is during the boot phase, boot sequence logs say that MX25L1605D is present instead of the 1606E. Maybe they did an upgrade along the way but left the driver? Could be since both components are pretty similar.

The Hardware Photograph

The processor is MediaTek MT7628KN in 32 bit MIPS architecture. Upon inspection, an external RAM does not seem to be present as the processor has an embedded 8MB DRAM already. One difference that I’ve noticed is the worse build quality of the device I have than the photos on the internet. My version has antennas connected via a lousy solder job compared to the coaxial cable connectors. Also, mine has power plug pins directly “touching” to the board whereas the other version has proper wiring with an insulation layer.

The flash memory is an 8 pin SOP version and can be interacted with a SOIC 8 clip + SPI chip. This was my first choice during the recon phase however as with the majority of my SOIC clip readings, the repeater itself starts to draw power ????? and uses the flash memory itself. This makes reading/writing the flash directly not feasible. Desoldering the memory and then interacting with it could still be a choice if I did not have the agility of a senile donkey.

One of my magnificent attempts at desoldering

After that, at a glance, labeled serial (UART) pins are the first feature that draws attention. Thanks to my trusty FT232RL stick, I can connect to the serial pins and try to interact with the device from there. The USB stick I have actually let me select between 3.3V and 5V and the repeater happens to need 5V which is nice (no need to convert/adjust anything).

UART connection photo showing the pins, not suitable for the colorblind

After a few trial and error attempts, I found out that the baud rate for this board’s serial connection is 115200. Asking VMWare to pass USB to TTL device to my virtual machine makes me miss the start of the boot sequence but after that, I’ve reached the serial communication channel. Which is, unfortunately, made of a set of pre-defined commands. No direct shell access or anything like that, unfortunately.

Serial connection command options

UART Connection

I’ve tried to intercept the boot sequence (since U-Boot is present). In the beginning, I’ve seen that the firmware written on the flash memory is automatically selected as the boot candidate. Even though this was the case, I’ve played around with the given commands and quickly found out that boot parameters can be changed!

Boot parameters with additional stuff as a bonus

Experimenting with these values is a key to a deeper control of the device, so I thought and changed some of them. Changing the “bootdelay” parameter (which was 0 previously) and restarting the device allowed me to select different boot options. I’m sure other parameters would be useful in different tasks, such as “flag_ota_reboot” removing the write-protection maybe?

Stopping U-Boot from using the Xiaomi firmware image

Buffer Overflow

I wanted to find a vulnerability (even if I couldn’t utilize it somehow) to top the research off. The first place to look for is the UART commands that take parameters. Either I got very lucky or this has become a pattern but the “ping” utility has a buffer overflow. If it wasn’t the case I’m sure it would have command injection or something similar, it’s always the case with the ping command.

Exploiting the vulnerability triggers a crash dump with a lot of juicy information such as the current state of the registers. Debugging with this information and using “pattern_create.rb/pattern_offset.rb” showed that 4 bytes after the initial 20 bytes is being written over the PC register.

A nice crashdump, showing the current state of registers

The PC register controls the execution. Overwriting the value of it allows us to hijack the current process, similar to the EIP/RIP on x64 operating system architectures. I could not go further here as the vulnerability requires physical interaction (not worth the effort?) and I could not think of a reliable exploit that does something meaningful on the eCOS RTOS.

Firmware

One of the OS subcommands is SPI which when invoked, allows us to directly interact with the flash memory and retrieve chunks of it. Previously, I could not extract the contents of the flash however this command gave me the ability to do it. Naturally, it is not as straightforward as reading the memory with a SOIC clip. We need to somehow automatize the memory chunk collection and assembly process. Luckily, I did all the hard work and created a script which you can find below:

https://github.com/k4r4koyun/Xiaomi-Repeater-Firmware-Dumper

With that, we can dump the flash memory. The news is not good, the memory dump does not have an embedded filesystem with it. Binwalk only shows 2 LZMA compressed data segments and a U-Boot bootloader. So where are the configuration parameters? The answer is that this is an eCos RTOS firmware, which is a giant binary blob with a single entry point. It also has a mapped storage region inside the flash memory instead of a fully-fledged filesystem.

Binwalk can extract the LZMA data. Manually extracting data segments with dd and then unlzma’ing them does not work. Well, it works but there is junk at the end of the extracted data which requires trimming. After the extraction, 2 different files appear, and using the strings command made me believe that they are identical. Maybe a read-only segment for recovery exists on top of the actual executable firmware. Executing binwalk for the extracted files produces the output below:

Conclusion

Seeing other operating systems/architectures other than the classic mini-Linux installation surely threw me off the balance. I would have wanted to find a SquashFS and play with it like all the cool kids do but beggars can’t be choosers.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments