My end goal is to dump the contents of NAND and successfully extract its contents.
This is a learning process for me, so if any information is wrong please let me know and I will correct my post. Additionally if you have any tips or tricks please comment below.
High-level key points on NAND memory:
- NAND technical specs are quite often vendor specific. You may have to resort to datasheet.
- Bad Blocks are blocks that contain one or more invalid bits whose reliability is not guaranteed.
- NAND can ship with Bad Blocks from the manufacturer. Manufacturers generally mark Bad Blocks.
- The smallest writable unit in NAND is a Page (aka Chunk).
- Pages are organised into larger units called a Block.
- The number of Pages per Block is vendor specific.
- Error Correcting Code (ECC) is used to detect (and sometimes correct) errors.
- ECC uses 2 common algorithms: Hamming and BCH
- The Out Of Band (OOB) (aka Spare Area) is a reserved area for ECC and sometimes metadata.
- The OOB area is stored after each Page.
Physically Accessing the NAND:
I am using a cheap Chinese hot air reflow station to remove NANDs from boards. I have not yet attempted to reattach a NAND.
I intend to add further detail at a later date, but essentially the process is to mask the surrounding area with Kapton tape to protect it from heat, then gradually heat up the NAND until the solder flows and you able remove the NAND using tweezers.
Whilst I do have some Bus Pirates/Blasters I have not yet attempted to dump the NAND using SPI/JTAG/etc, this will come in a later blog post.
Dumping Hardware:
I am using a "TSOP 48 to DIP 48 Pin IC Test Socket Programmer Adapter Converter" with a "Dangerous Prototypes FT2232H Breakout Board 1.0", based on the design by Jeong Wook (https://github.com/ohjeongwook/DumpFlash) to query and dump NAND.
The intention of using this is so you do not need to detach the NAND from the board. I have tested this with both attached and unattached NAND chips, I can only assume the pin out is wrong?
Dumping Software:
I am using DumpFlash.py also by Jeong Wook on Ubuntu 14.04.4 64bit. DumpFlash requires an older version of pyftdi to work.
Target Device:
This main components of this device are:
- ATMEL AT91SAM9610 ARM processor.
- 2 x Pointec PT483208FHG DRAM.
- Toshiba TC58NVG0S3ETA00 NAND.
- ATMEL ATMLH322 EEPROM.
It is useful to have an understanding of the target device components as this may hint at what you will expect to find on the NAND. In this case a ARM based architecture rather than the traditional x86.
Dumping the NAND:
First I query the NAND to confirm it is working:
As you can see DumpFlash successfully queried the NAND and pulled back information about the Page sizes, etc.
Next to Dump the NAND:
Dependent on the size of your NAND this process can take several minutes to complete.
With the NAND successfully dumped the first observation is the size discrepancy between the dump and the NAND information. This is because the dump includes both the Main memory and the OOB memory.
Exploring the dump:
Running Binwalk against the dump reveals some promising information, namely the U-Boot Header, Linux Kernel, and JFFS2 file-systems. This indicates the device is Linux based. Unfortunately there are several hundred entries for JFFS2 and Zlib which suggests the data is broken up:
Looking at the dump in a hex editor indicates the OOB areas are likely causing the problem.
To remove the OOB data I use a script by Jean-Michel Picod (https://bitbucket.org/jmichel/tools/src):
For the ID I supply the first 4 bytes of the Full ID we extracted earlier with DumpFlash.py.
Dumping the NAND:
First I query the NAND to confirm it is working:
As you can see DumpFlash successfully queried the NAND and pulled back information about the Page sizes, etc.
Next to Dump the NAND:
Dependent on the size of your NAND this process can take several minutes to complete.
With the NAND successfully dumped the first observation is the size discrepancy between the dump and the NAND information. This is because the dump includes both the Main memory and the OOB memory.
Exploring the dump:
Running Binwalk against the dump reveals some promising information, namely the U-Boot Header, Linux Kernel, and JFFS2 file-systems. This indicates the device is Linux based. Unfortunately there are several hundred entries for JFFS2 and Zlib which suggests the data is broken up:
Looking at the dump in a hex editor indicates the OOB areas are likely causing the problem.
To remove the OOB data I use a script by Jean-Michel Picod (https://bitbucket.org/jmichel/tools/src):
For the ID I supply the first 4 bytes of the Full ID we extracted earlier with DumpFlash.py.
Next I tried using Binwalks automatic extract parameter but it was unable to extract anything meaningful. So instead I decided to manually carve the JFFS2 file-system from the dump:
I used a block size of 1 and skipped to the beginning of the JFFS2 area as listed in the previous Binwalk output.
From here I tried various tools (Binwalk, jffs2dump, etc) to extract the contents of the JFFS2 file-system without success, so instead I resorted to mounting it directly:
I used nandsim to create a virtual device, and supplied it the first 4 bytes from the ID I previously discovered.
I used a block size of 1 and skipped to the beginning of the JFFS2 area as listed in the previous Binwalk output.
From here I tried various tools (Binwalk, jffs2dump, etc) to extract the contents of the JFFS2 file-system without success, so instead I resorted to mounting it directly:
I used nandsim to create a virtual device, and supplied it the first 4 bytes from the ID I previously discovered.
From here the file-system was successfully mounted: