Ph0wn is a CTF (Capture The Flag) competition focused on IoT and embedded devices happening in Sophia Antipolis, France. We were asked by the admins to create some challenges and went with what we thought would be a simple challenge but unfortunately, nobody was able to solve it during the CTF.
In this blog post, we will present the challenge solution in a tutorial form for beginners to understand how to handle such kind of challenges or handle embedded systems in general.
Let’s see what the task was about :
Like many IoT devices, your adventure starts with a small chip. Can you find the flag ?
Solving the challenge
Contestants had access to a simple chip in a SOIC-8 package :
After reading the serial number (FM25Q32), a quick google search finds the corresponding datasheet. From this, we can learn that this is a 32MBit EEPROM using the SPI protocol.
What is an EEPROM?
An EEPROM (Electrically Erasable Programmable Read-Only Memory) is a type of non-volatile memory (it keeps data written to it even if the module is unpowered). This kind of memory is often found in IoT devices where you can usually find the device firmware or user settings.
What is SPI?
SPI is a synchronous serial communication interface specification used for short distance communication, primarily in embedded systems. It uses four wires for signaling, plus two for powering the EEPROM.
- In SPI, the master drives the clock, and the slave synchronizes on this clock to communicate.
- There are two data lines: Master Out Slave In (MOSI) and Master In Slave Out (MISO). One bit of information is both sent and received on each clock cycle.
- Since multiple devices can share the same CLK, MISO and MOSI lines, each slave device on a SPI bus has a Slave/Chip Select (SS/CS) input used to select which chip to talk to. Only one slave should be selected at a time.
One of the things to look for is the voltage tolerance of the target chip. Using higher voltage levels might break the chip or worse. Once again, we can find this information in the datasheet on page 51:
The maximum value here is 4V, so we need a tool that can output less than 4V on the signal pins in order to prevent the device from being destroyed.
To communicate with this chip, we need a SPI interface that we can program using a computer. There are multiple tools for that (FT232H, Bus Pirate, Hydrabus, …). The pin assignment of each of these interfaces are indicated on their respective documentation. On the chip side, page 6 of the datasheet shows the use of each pin. If you look at the picture above, you can see a circle in the lower left corner of the chip: this is an indicator of the pin number 1, and is reported on the schema:
The wiring is the following :
|SCK (PB3)||CLK (6)|
|MISO (PB4)||DO (2)|
|MOSI (PB5)||DI (5)|
|CS (PA15)||/CS (1)|
|VCC (3.3V)||VCC (8)|
|GND (GND)||GND (4)|
Talking to the chip
An EEPROM is just a memory module, only basic operations are allowed on that kind of module: reading and writing memory at specific addresses. By looking at the datasheet, it is possible to know how to read data from the chip, using the read data command on page 23.
On that specific chip, it means sending the instruction (0x03) followed by the 24-bit address of the data we want to read. The EEPROM will then start to send data on the next clock cycle, as shown in figure 10 in the datasheet. The datasheet also specifies that The address is automatically incremented to the next higher address after byte of data is shifted out allowing for a continuous stream of data. This means that the entire memory can be accessed with a single instruction as long as the clock continues.
That simply means that once we have set the initial command, we can read as much data as we want. Using a Hydrabus, the following command can be used :
spi1> [ 0x03 0x00 0x00 0x00 hd:64 ]
68 73 71 73 18 00 00 00 51 8d 12 5c 00 00 02 00 | hsqs….Q..\….
06 00 00 00 04 00 11 00 c0 00 01 00 04 00 00 00 | …………….
Or, in more comprehensive terms :
Enable chip select, send 0x03, 0x00 0x00 0x00, read 64 bytes and display them in
hex and disable chip select
By using this command and reading more bytes, we are able to retrieve the 4 megabytes of data. To convert the hexdump to a file, simply copy it into a text file and run :
xxd -r -p file > image.bin
Note: Using a script like this one does the exact same thing.
Running the strings command does not give any meaningful result, so the data must be packed somehow. A common tool used to analyze data is binwalk. Running the tool on our image shows the following :
> binwalk image.bin
DECIMAL HEXADECIMAL DESCRIPTION
0 0x0 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 655738 bytes, 24 inodes, blocksize: 131072 bytes, created: 2018-12-13 16:48:17
Nice ! Squashfs is a file system usually used for flash memories. Sounds good. unsquashfs, present in the squashfs-tools package allows to dump all files :
> unsquashfs image.bin
Parallel unsquashfs: Using 8 processors
21 inodes (23 blocks) to write
[===============================================================|] 23/23 100%
created 21 files
created 3 directories
created 0 symlinks
created 0 devices
created 0 fifos
> ls squashfs-root
flag.pdf lst obj
Note: using the file command would have shown that this is a squashfs partition as well because it is stored at the beginning of the file. Binwalk is able to recognize such partition even if it is in the middle of the file.
Opening flag.pdf in a viewer shows the flag :
Flashrom supports all kind of programmers, as well as many kinds of EEPROMS and (fortunately) the W25Q32. Using flashrom would have given the image as well.
We really had a lot of fun playing this CTF and would like to thank again the organizers for their awesome work and the incredible venue. Congratulations to the Tipi’Hack team for winning the CTF and to every challenge authors for their time. We’ll make sure to be there next week.
For further information, you can check out these links :