神刀安全网

Practical Reverse Engineering Part 4 – Dumping the Flash

08 Jun 2016

In Parts 1 to 3 we’ve been gathering data within its context. We could sniff the specific pieces of data we were interested in, or observe the resources used by each process. On the other hand, they had some serious limitations; we didn’t have access to ALL the data, and we had to deal with very minimal tools… And what if you had not been able to find a serial port on the PCB? What if we had but it didn’t use default credentials?

In this post we’re gonna get the data straight from the source, sacrificing context in favour of absolute access. We’re gonna dump the data from the Flash IC and decompress it so it’s usable. This method doesn’t require expensive equipment and is independent from everything we’ve done until now. An external Flash IC with a public datasheet is a reverser’s great ally.

Dumping the Memory Contents

As discussed in Part 3, we’ve got access to the datasheet for the Flash IC, so there’s no need to reverse its pinout:

Practical Reverse Engineering Part 4 - Dumping the Flash

We also have its instruction set, so we can communicate with the IC using almost any device capable of ‘speaking’ SPI.

We also know that powering up the router will cause the Ralink to start communicating with the Flash IC, which would interfere with our own attempts to read the data. We need to stop the communication between the Ralink and the Flash IC, but the best way to do that depends on the design of the circuit we’re working with.

Do We Need to Desolder The Flash IC? [Theory]

The perfect way to avoid interference would be to simply desolder the Flash IC so it’s completely isolated from the rest of the circuit. It gives us absolute control and removes all possible sources of interference. Unfortunately, it also requires additional equipment, experience and time, so let’s see if we can avoid it.

The second option would be to find a way of keeping the Ralink inactive while everything else around it stays in standby. Microcontrollers often have a Reset pin that will force them to shut down when pulled to 0 ; they’re commonly used to force IC reboots without interrupting power to the board. In this case we don’t have access to the Ralink’s full datasheet (it’s probably distributed only to customers and under NDA); the IC’s form factor and the complexity of the circuit around it make for a very hard pinout to reverse, so let’s keep thinking…

What about powering one IC up but not the other? We can try applying voltage directly to the power pins of the Flash IC instead of powering up the whole circuit. Injecting power into the PCB in a way it wasn’t designed for could blow something up; we could reverse engineer the power circuit, but that’s tedious work. This router is cheap and widely available, so I took the ‘fuck it’ approach. The voltage required, according to the datasheet , is 3V; I’m just gonna apply power directly to the Flash IC and see what happens. It may power up the Ralink too, but it’s worth a try.

Practical Reverse Engineering Part 4 - Dumping the Flash

We start supplying power while observing the board and waiting for data from the Ralink’s UART port. We can see some LEDs light up at the back of the PCB, but there’s no data coming out of the UART port; the Ralink must not be powered up. Success!

The LEDs and other static components can’t communicate with the Flash IC, so they won’t be an issue as long as we can supply enough current for all of them. I’m just gonna use a bench power supply, with plenty of current available for everything. If you don’t have one you can try using the Master ’s power lines, or some USB power adapter if you need some more current. They’ll probably do just fine.

Time to connect our SPI Master .

Connecting to the Flash IC

Now that we’ve confirmed there’s no need to desolder the Ralink we can connect any device that speaks SPI and start reading memory contents block by block. Any microcontroller will do, but a purpose-specific SPI-USB bridge will often be much faster. In this case I’m gonna be using a board based on the FT232H , which supports SPI among some other low level protocols.

We’ve got the pinout for both the Flash and my USB-SPI bridge , so let’s get everything connected.

Practical Reverse Engineering Part 4 - Dumping the Flash

Now that the hardware is ready it’s time to start pumping data out.

Dumping the Data

We need some software in our computer that can understand the USB-SPI bridge’s traffic and replicate the memory contents as a binary file. Writing our own wouldn’t be difficult, but there are programs out there that already support lots of common Masters and Flash ICs. Let’s try the widely known and open source flashrom .

flashrom is old and buggy, but it already supports both the FT232H as Master and the FL064PIF as Slave. It gave me lots of trouble in both OSX and an Ubuntu VM, but ended up working just fine on a Raspberry Pi (Raspbian):

Practical Reverse Engineering Part 4 - Dumping the Flash

Success!We’ve got our memory dump, so we can ditch the hardware and start preparing the data for analysis.

Splitting the Binary

The file command has been able to identify some data about the binary, but that’s just because it starts with a header in a supported format. In a 0-knowledge scenario we’d use binwalk to take a first look at the binary file and find the data we’d like to extract.

Binwalk is a very useful tool for binary analysis created by the awesome hackers at /dev/ttyS0 ; you’ll certainly get to know them if you’re into hardware hacking.

Practical Reverse Engineering Part 4 - Dumping the Flash

In this case we’re not in a 0-knowledge scenario; we’ve been gathering data since day 1, and we obtained a complete memory map of the Flash IC in Part 2. I trust debug messages more than I do binary parsers, and it makes for much cleaner splitting of the binary, so let’s use it:

Practical Reverse Engineering Part 4 - Dumping the Flash

With the binary and the relevant addresses, it’s time to split the binary into its 4 basic segments. dd takes its parameters in terms of block size ( bs , bytes), offset ( skip , blocks) and size ( count , blocks); all of them in decimal. We could easily use a calculator, but I’d rather let python do the work:

$ dd if=spidump.bin of=bootloader.bin bs=1 count=`python -c "print 0x020000"`     131072+0 records in     131072+0 records out     131072 bytes transferred in 0.215768 secs (607467 bytes/sec) $ dd if=spidump.bin of=mainkernel.bin bs=1 count=`python -c "print 0x13D000-0x020000"` skip=`python -c "print 0x020000"`     1167360+0 records in     1167360+0 records out     1167360 bytes transferred in 1.900925 secs (614101 bytes/sec) $ dd if=spidump.bin of=mainrootfs.bin bs=1 count=`python -c "print 0x660000-0x13D000"` skip=`python -c "print 0x13D000"`     5386240+0 records in     5386240+0 records out     5386240 bytes transferred in 9.163635 secs (587784 bytes/sec) $ dd if=spidump.bin of=protect.bin bs=1 count=`python -c "print 0x800000-0x660000"` skip=`python -c "print 0x660000"`     1703936+0 records in     1703936+0 records out     1703936 bytes transferred in 2.743594 secs (621060 bytes/sec) 

We have created 4 different binary files:

  1. bootloader.bin : U-boot. The bootloader. It’s not compressed because the Ralink wouldn’t know how to decompress it.
  2. mainkernel.bin : eCOS. The basic firmware that coordinates everything in runtime. Compressed using lzma
  3. mainrootfs.bin : Filesystem. Contains all sorts of important binaries and configuration files. Compressed as squashfs using the lzma algorithm
  4. protect.bin : Miscellaneous data as explained in Part 3. Not compressed

Extracting the Data

Now that we’ve split the binary into its 4 basic segments, let’s take a closer look at each of them.

Bootloader

Practical Reverse Engineering Part 4 - Dumping the Flash

Binwalk found the uImage header and decoded it for us. U-Boot uses these headers to identify relevant memory areas. It’s the same info that the file command displayed when we fed it the whole memory dump because it’s the first header in the file.

We don’t care much for the bootloader’s contents in this case, so let’s ignore it.

Kernel

Practical Reverse Engineering Part 4 - Dumping the Flash

Compression is something we have to deal with before we can make any use of the data. binwalk has confirmed what we discovered in Part 2, the kernel is compressed using lzma , a very popular compression algorithm in embedded systems. A quick check with strings mainkernel.bin | less confirms there’s no human readable data in the binary, as expected.

There are multiple tools that can decompress lzma , such as 7z or xz . None of those liked mainkernel.bin :

$ xz --decompress mainkernel.bin xz: mainkernel.bin: File format not recognized 

The uImage header is probably messing with tools, so we’re gonna have to strip it out. We know the lzma data starts at byte 0x40 , so let’s copy everything but the first 64 bytes.

Practical Reverse Engineering Part 4 - Dumping the Flash

And when we try to decompress…

$ xz --decompress mainkernel_noheader.lzma xz: mainkernel_noheader.lzma: Compressed data is corrupt 

xz has been able to recognize the file as lzma , but now it doesn’t like the data itself. We’re trying to decompress the whole mainkernel Flash area, but the stored data is extremely unlikely to be occupying 100% of the memory segment. Let’s remove any unused memory from the tail of the binary and try again:

Practical Reverse Engineering Part 4 - Dumping the Flash

xz seems to have decompressed the data successfully. We can easily verify that using the strings command, which finds ASCII strings in binary files. Since we’re at it, we may as well look for something useful…

Practical Reverse Engineering Part 4 - Dumping the Flash

The Wi-Fi Easy and Secure Key Derivation strings looks promising, but as it turns out it’s just a hardcoded string defined by the Wi-Fi Protected Setup spec . Nothing to do with the password generation algorithm we’re interested in.

We’ve proven the data has been properly decompressed, so let’s keep moving.

Filesystem

Practical Reverse Engineering Part 4 - Dumping the Flash

The mainrootfs memory segment does not have a uImage header because it’s relevant to the kernel but not to U-Boot.

SquashFS is a very common filesystem in embedded systems. There are multiple versions and variations, and manufacturers sometimes use custom signatures to make the data harder to locate inside the binary. We may have to fiddle with multiple versions of unsquashfs and/or modify the signatures, so let me show you what the signature looks like in this case:

Practical Reverse Engineering Part 4 - Dumping the Flash

Since SquashFS does use signatures to delimite the where the compressed data beings and ends, we probably won’t have to trim the binary like we did with the kernel.

Since the filesystem is very common and the work to find the right configuration is tedious, let’s see if anybody has already written a script for this. I came accross this OSX-specific fork of the Firmware Modification Kit , which compiles multiple different versions unsquashfs and includes a neat script called unsquashfs_all.sh that tries all of them. Let’s give it a try:

Practical Reverse Engineering Part 4 - Dumping the Flash

Wasn’t that easy? We got lucky with the SquashFS version and supported signature, and unsquashfs_all.sh managed to decompress the filesystem. Now we’ve got every binary in the filesystem, every symlink and configuration file, and everything is nice and tidy:

Practical Reverse Engineering Part 4 - Dumping the Flash

In the complete file tree you can see we’ve got every file in the system, (other than runtime files like those in /var/ , of course).

Using the intel we have been gathering on the firmware since day 1 we can start looking for potentially interesting binaries:

Practical Reverse Engineering Part 4 - Dumping the Flash

If you’re looking for network/application vulnerabilities in the router, having every binary and config file in the system will be massively useful.

Protected

Practical Reverse Engineering Part 4 - Dumping the Flash

As we discussed in Part 3, this memory area is not compressed and contains all pieces of data that need to survive across reboots but be different accross devices. strings seems like an appropriate tool for a quick overview of the data:

Practical Reverse Engineering Part 4 - Dumping the Flash

Everything in there seems to be just the curcfg.xml contents, some logs and those few isolated strings in the picture. We already sniffed and analysed all of that data in Part 3, so there’s nothing else to discuss here.

Next Steps

At this point all hardware reversing for the Ralink is complete and we’ve collected everything there was to collect in ROM. Just think of what you may be interested in and there has to be a way to find it. Imagine we wanted to control the router through the UART debug port we found in Part 1, but when we try to access the ATP CLI we can’t figure out the credentials. After dumping the external Flash we’d be able to find the XML file in the protect area, and discover the credentials just like we did in Part 2 ( The Rambo Approach to Intel Gathering , admin:admin ).

If you couldn’t dump the memory IC for any reason, the firmware upgrade files provided by the manufacturers will sometimes be complete memory segments; the device simply overwrites the relevant flash areas using code previously loaded to RAM. Downloading the file from the manufacturer would be the equivalent of dumping those segments from flash, so we just need to decompress them. They won’t have all the data, but it be enough for your purposes.

Now that we’ve got the firmware we just need to think of anything we may be interested in and start looking for it through the data. In the next post we’ll dig a bit into different binaries and try to find more potentially useful data.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Practical Reverse Engineering Part 4 – Dumping the Flash

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址