Hide Data in Bad Blocks

Published on . Hide Data

When a sector on a disk gets damaged, it becomes unusable. Modern disks have spare sectors that are used to replace these bad sectors, so they’re handled and fixed automatically. If you’re young enough, you might never have witnessed these bad sectors, because modern hardware handles them transparently, but there’ still there. I’ll show you how to store data in “fake” bad blocks.

This is part 3 in a series on how to hide your data.

Warning: Don’t rely on this tutorial actually hiding your data. This is for academic and experimental purposes only. Always complement using encryption and plausible deniability methods like TrueCrypt.

When the disk runs out of spare sectors, or never had any in the first place (like 3.5” disks, or very old hard disks), the filesystem is the second line of defense. Inside the filesystem is a list of known bad blocks – blocks on bad sectors. The filesystem takes care not to use these blocks and just skips them.

We can’t force the disk to remap certain blocks to spare sectors, but we can tell the filesystem which blocks have (supposedly) gone bad. If the blocks aren’t really damaged, any data we put there will never be touched, because the filesystem thinks it’s garbage anyway. That, is exactly what we’re going to do.


To keep it simple and fast, we’ll hide a whole partition inside a burst of bad blocks. The partition we’ll create has to be small and reside somewhere in the middle of the disk. We can’t put the partition at the beginning or the end of the disk, because most likely the filesystem requires an intact header at the start and end of the partition.

Partition inside Bad Blocks

The partition has to be small enough to be able to fit inside the non-secret partition while not arousing suspicion. Some operating systems mark bad blocks as used blocks, which means if we put a 100MB partition inside bad blocks, the “parent” filesystem will always have at least 100MB in use. This could arouse suspicion when there aren’t any files on it.

I’ll be using my trusty 256MB Compactflash card for this, which is excellent for illustratory purposes.

Here’s what sfdisk has to say about it:

$ sudo sfdisk -l /dev/sde

Disk /dev/sde: 1009 cylinders, 9 heads, 56 sectors/track
Units = cylinders of 258048 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sde1          0       -       0          0    0  Empty
/dev/sde2          0       -       0          0    0  Empty
/dev/sde3          0       -       0          0    0  Empty
/dev/sde4          0       -       0          0    0  Empty

We can see the card is comprised of 1009 cylinders. I want to create a partition of about 20MB, which is about 82 cylinders on this disk (see the second line of sfdisk -l). Because we can’t create the partition at the start of the disk, let’s put it 214 cylinders in:

$ sudo sfdisk /dev/sde << EOF

Just like before, put FAT16 on it and transfer your secret data.

$ sudo mkfs.vfat -F16 /dev/sde1
mkfs.vfat 2.11 (12 Mar 2005)

If you want, you can copy the current partition table to the back of the disk for easy restoring, just like in the previous article.

Unmount it, and remove the partition:

$ sudo sfdisk /dev/sde << EOF

Now create the parent partition. This should at least encompass the whole secret partition. If you’ve copied the partition table to the back of the disk, make sure to leave at least the last cylinder free.

$ sudo sfdisk /dev/sde << EOF

Creating Bad Blocks

We need to calculate what blocks our secret partition resides on so we can mark them as bad. We know it starts at cylinder 214 and is 82 cylinders in size. Since on this disk, a cylinder is 258048 bytes big, the secret partition starts at byte 55222272. Divide this by the size of one block, which is 1024 bytes, and we get block 53928. Do the same for the size of the partition, and we find that 82 cylinders equal 20664 blocks. Now we know our partition starts at block 53928 and ends at block 74592. We’ll use a margin of 10 blocks on each side just in case our calculations aren’t precise.

Since we’re putting a FAT16 filesystem on it, we need to tell mkfs.vfat what blocks have supposedly gone bad. This is done by using a bad blocks file, which is a text-file with the address of each bad block on a new line. Let’s create our bad blocks file:

$ seq 53918 74602 > /tmp/badblocks

If you open /tmp/badblocks, you should see something like this:


To create the filesystem, we pass the bad blocks file using the -l parameter:

$ sudo mkfs.vfat -n "Camera" -l /tmp/badblocks /dev/sde1
mkdosfs 2.11 (12 Mar 2005)
20685 bad blocks

That’s it! You can now use your disk to your heart’s delight, nothing will touch your secret partition. One awesome way is to put the card in your camera and take some pictures with it. Your data will remain safe, and there’ll be nothing suspicious about a 4GB card “missing” some megabytes.


If you’ve smuggled your secret data across state borders, you’re ready to recover the secret partition. Just recreate the partition table to contain the secret partition:

$ sudo sfdisk /dev/sde << EOF

That’s it! You can even reuse the setup: by switching partition tables you’re effectively changing which partition is “active” on your card, and changing data in either partition won’t affect the other.


  • Pretty much undetectable
  • Infinitely reusable
  • Bad blocks are less suspicious than unallocated space


  • Quite complex to set up
  • Possibly suspicious size discrepancy in empty filesystems
David Verhasselt

Senior full-stack engineer with 5 years of experience building web applications for clients all over the world.

Interested in working together?

Find out what I can do for you or get in touch!

Like this? Sign up to get regular updates