📜 ⬆️ ⬇️

Investigating the obfuscation of the Linksys WRT120N firmware

Recently, my attention was drawn to the fact that in firmware updates for Linksys WRT120N they use some kind of obfuscation. It seemed to me that it would be interesting to rummage in it, and I decided to take a look.

The latest firmware version does not look like firmware, with which you can immediately work
image

As you can see, there is a small data block compressed with LZMA - these are just HTML files for the web interface of the router. Most of the firmware consists of some strange, random data. Since I couldn’t do anything with it anymore, and curiosity tried to overpower me more and more, I bought this model of the router myself (how much they screwed Amazon Prime cost!).
')
Iron analysis

At first glance, it became clear that the WRT120N runs on the Atheros AR7240 SoC, it has 2MB SPI flash, 32MB RAM and something similar to Serial and JTAG wiring:
image

In order to take a deeper look at the boot process, I decided to start with the serial port.
image

I have already talked about serial ports, so I will not focus on the methods for finding pins and speed in this article. It was easy to find the findings of the port using a multimeter and visual inspection of the board:
Pin 2 – RX Pin 3 – TX Pin 5 – Ground 

The port operates at a speed of 115200 baud and provides interesting boot information:
 $ sudo miniterm.py /dev/ttyUSB0 115200 --- Miniterm on /dev/ttyUSB0: 115200,8,N,1 --- --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- ======================================================================= Wireless Router WG7005G11-LF-88 Loader v0.03 build Feb 5 2009 15:59:08 Arcadyan Technology Corporation ======================================================================= flash MX25L1605D found. Copying boot params.....DONE Press Space Bar 3 times to enter command mode ... Flash Checking Passed. Unzipping firmware at 0x80002000 ... [ZIP 3] [ZIP 1] done In c_entry() function ... install_exception install exception handler ... install interrupt handler ... ulVal: 0x484fb Set GPIO #11 to OUTPUT Set GPIO #1 to OUTPUT Set GPIO #0 to OUTPUT Set GPIO #6 to INPUT Set GPIO #12 to INPUT Timer 0 is requested ##### _ftext = 0x80002000 ##### _fdata = 0x80447420 ##### __bss_start = 0x804D5B04 ##### end = 0x81869518 ##### Backup Data from 0x80447420 to 0x81871518~0x818FFBFC len 583396 ##### Backup Data completed ##### Backup Data verified [INIT] HardwareStartup .. [INIT] System Log Pool startup ... [INIT] MTinitialize .. CPU Clock 350000000 Hz init_US_counter : time1 = 270713 , time2 = 40272580, diff 40001867 US_counter = 70 cnt1 41254774 cnt2 41256561, diff 1787 Runtime code version: v1.0.04 System startup... [INIT] Memory COLOR 0, 1600000 bytes .. [INIT] Memory COLOR 1, 1048576 bytes .. [INIT] Memory COLOR 2, 2089200 bytes .. [INIT] tcpip_startup .. Data size: 1248266 e89754967e337d9f35e8290e231c9f92 Set flash memory layout to Boot Parameters found !!! Bootcode version: v0.03 Serial number: JUT00L602233 Hardware version: 01A ... 


It seems that the firmware was made by Arcadyan , the message “Unzipping firmware ...” was especially interesting, a quick google brought me to the post about the deobfuscation of Arcadyan firmware, but here, it seems, a slightly different method is used.

Through the serial port you can only use the bootloader menu. During the download, you can climb into it if you press the spacebar three times, and perform some actions, such as cleaning the flash and setting the board settings:
 Press Space Bar 3 times to enter command mode ...123 Yes, Enter command mode ... [WG7005G11-LF-88 Boot]:? ====================== [U] Upload to Flash [E] Erase Flash [G] Run Runtime Code [A] Set MAC Address [#] Set Serial Number [V] Set Board Version [H] Set Options [P] Print Boot Params [I] Load ART From TFTP [1] Set SKU Number [2] Set PIN Number ====================== 


Unfortunately, the bootloader did not allow dumping the contents of RAM or flash. Although there is JTAG wiring on the board, I decided to dump the flash directly, because The dump process through JTAG is usually not fast, and the SPI connection is very simple.

Probably any device that supports the SPI protocol can read flash. I used an FTDI C232HM cable and spiflash.py from libmpsse
 $ sudo spiflash --read=flash.bin --size=$((0x200000)) --verify FT232H Future Technology Devices International, Ltd initialized at 15000000 hertz Reading 2097152 bytes starting at address 0x0...saved to flash.bin. Verifying...success. 

A flash consists of three LZMA blocks and a small amount of MIPS code, but the firmware itself is still not good:
image

The first two LZMA blocks are part of the recovery image, and the MIPS code is the bootloader itself. The rest of the space is taken by the obfuscated firmware file, except for zeros and some data at the end.

Bootloader analysis

The loader, besides the fact that it decrypts the firmware and downloads it to the address in memory, contains some interesting things. I’ll skip boring things, sort of like I’ve looked for the boot loader address, manually determined the functions of the standard C library, found the offset table JUMPs, etc., and I’ll go straight to the interesting.

First, in the early boot phase, the bootloader checks if the reset button is pressed. If it is clicked, it downloads the image “Tiny_ETCPIP_Kernel” - a small recovery image, with a web interface.
image

It's a good news. Now we know that if something goes wrong during the firmware update process, you can click reset and revive the device.
And there is also a hidden administrator mode in the bootloader menu:
image

Pressing "!" will activate the administrator mode, which unlocks some options, including reading and writing to memory.

 [WG7005G11-LF-88 Boot]:! Enter Administrator Mode ! ====================== [U] Upload to Flash [E] Erase Flash [G] Run Runtime Code [M] Upload to Memory [R] Read from Memory [W] Write to Memory [Y] Go to Memory [A] Set MAC Address [#] Set Serial Number [V] Set Board Version [H] Set Options [P] Print Boot Params [I] Load ART From TFTP [1] Set SKU Number [2] Set PIN Number ====================== [WG7005G11-LF-88 Boot]: 

The most interesting part of the bootloader, of course, is the one that loads the obfuscated firmware into memory.

Obfuscation analysis


Deobfuscation is performed in the load_os function, which is passed a pointer to the obfuscated image and the address where the unpacked image should be placed:
image
The unpacking itself is not particularly difficult:
image

In general, if the firmware starts from 04 01 09 20 (and ours begins with these bytes), then the decryption algorithm is executed, which:

After all this, the data at 0 Ă— 04 contains the correct LZMA header, which is then decompressed.

Implementing the deobfuscation utility was easy, and the WRT120N firmware can now be unpacked and released.
 $ ./wrt120n ./firmware/FW_WRT120N_1.0.07.002_US.bin ./deobfuscated.bin Doing block swap... Doing nibble-swap... Doing byte-swap... Saving data to ./deobfuscated.bin... Done! 

image
Analysis of unpacked, but not decompressed firmware

If anyone is interested, you can download the utility for unpacking .

Source: https://habr.com/ru/post/213191/


All Articles