Skip to content

Hiding Techniques

MC68 edited this page Sep 27, 2018 · 11 revisions

Table of Contents

  1. File Slack (FAT, NTFS, EXT4)
  2. MFT Slack (NTFS)
  3. Additional Cluster Allocation (FAT, NTFS)
  4. Bad Cluster Allocation (FAT, NTFS)
  5. Reserved GDT Blocks (EXT4)
  6. Superblock Slack (EXT4)
  7. OSD2 (EXT4)
  8. obso_faddr (EXT4)
  9. Additional Commands (fattools, metadata)

File Slack

The fileslack subcommand provides functionality to read, write and clean the file slack of files in a filesystem. Available for these filesystem types:

  • FAT
  • NTFS
  • EXT4

The smallest unit of a filesystem is called cluster or block (EXT4). The size of these units is determined during the creation of the filesystem. It can be calculated in the following way: sector size * sectors per cluster. If a file is smaller than the cluster size an empty space usually called file slack within that cluster is produced. This empty space can be used to hide data.

File slack is composed of two separate Slack components - RAM slack and Drive slack. RAM slack starts at the end of a file and ends at the end of the sector. Drive slack on the other hand encompasses the area at the end of the RAM slack and ends at the end of the cluster. Most FAT and NTFS filesystem implementations fill the RAM slack with zeroes - this has to be accounted for when trying to hide data using file slack.

EXT4 does not distinguish between RAM slack and Drive slack and fills up the entire potential slack area with zeroes. Therefore detection of File slack hiding is very likely.

Capacity: High - Reliant on block size, cluster size and file sizes. ((cluster size - block size) stored files.)

Detectability: Medium - Testing with fsck.fat, chkdsk(NTFS) and fsck.ext4 show no immediate clues. Manual detection or detection via specific tools is easiest in EXT4 due to the fact that EXT4's slack is usually filled with zeroes.

Stability: Low - If size of the original file changes the hidden data could be overwritten.

# write into slack space
$ echo "TOP SECRET" | fishy -d testfs-fat12.dd fileslack -d myfile.txt -m metadata.
˓→json -w
# read from slack space
$ fishy -d testfs-fat12.dd fileslack -m metadata.json -r
TOP SECRET
# wipe slack space
$ fishy -d testfs-fat12.dd fileslack -m metadata.json -c
# show info about slack space of a file
$ fishy -d testfs-fat12.dd fileslack -m metadata.json -d myfile.txt -i
File: myfile.txt
Occupied in last cluster: 4
Ram Slack: 508
File Slack: 1536

MFT-Slack

The mftslack subcommand provides functionality to read, write and clean the slack of mft entries in a filesystem. Available for these filesystem types:

  • NTFS

The Master File Table (MFT) contains all necessary metadata for every file and every folder of a NTFS partition. An entry in MFT doesn't necessary use all of its allocated space - the unused space could even still contain parts of previous entries, which makes the MFT Entry Slack an inconspicuous place to hide data.

NTFS uses Fixup to determine bad sectors and data structures. Whenever a MFT entry is written to a disk, its last two bytes are being used as a signature. It is important not to overwrite these two bytes when hiding data, else the MFT can become damaged. NTFS saves a copy of at least the first four MFT entries ($MFT, $MFTMirr, $LogFile, $Volume) in a file named $MFTMirr in case of needed recoveries. To stop detection of hidden data via chkdsk you have to hide a copy of the original hidden data at the corresponding entry in $MFTMirr.

Capacity: High - dependent on allocated MFT entry size and their actual size. (allocated size - actual size) - 2 can be saved per Fixup value.

Detectability: High - domirr protects you from chkdsk detection, there will still be an error detected in $MFTMirr.

Stability: Low - Hidden data could get overwritten when MFT entries change.

# write into slack space
$ echo "TOP SECRET" | fishy -d testfs-ntfs.dd mftslack -m metadata.json -w
# read from slack space
$ fishy -d testfs-ntfs.dd mftslack -m metadata.json -r
TOP SECRET
# wipe slack space
$ fishy -d testfs-ntfs.dd mftslack -m metadata.json -c

Additional Cluster Allocation

The addcluster subcommand provides methods to read, write and clean additional clusters for a file where data can be hidden. Available for these filesystem types:

  • FAT
  • NTFS

The additional clusters are either unallocated or assigned to a file. If you assign a cluster to file the filesystem will no longer try to use the cluster which gives you space to hide data.

An issue arises if the associated file grows. In that case the file might overwrite your hidden data.

Capacity: High - This technique uses entire clusters and is therefore only limited by count_of_clusters.

Detectability: Medium - chdsk in NTFS can be tricked into not noticing the hidden data if the file attributes are adjusted. fsck.fat for example will detect if cluster chains are bigger than the defined directory entries.

Stability: Low - Hidden data can be overwritten if associated files grow.

# Allocate additional clusters for a file and hide data in it
$ echo "TOP SECRET" | fishy -d testfs-fat12.dd addcluster -d myfile.txt -m metadata.
˓→json -w
# read hidden data from additionally allocated clusters
$ fishy -d testfs-fat12.dd addcluster -m metadata.json -r
TOP SECRET
# clean up additionally allocated clusters
$ fishy -d testfs-fat12.dd addcluster -m metadata.json -c

Bad Cluster Allocation

The badcluster subcommand provides methods to read, write and clean bad clusters, where data can be hidden into. Available for these filesystem types:

  • FAT
  • NTFS

If a sector or a cluster is damaged read and write operations lead to damaged data. To prevent this, these bad sectors or clusters are marked by the filesystem. The filesystem also saves a reference to the bad sectors or clusters an no longer uses them. To hide data using this technique, you have to mark free and undamaged clusters as bad clusters.

In NTFS filesystems the damaged are saved using the MFT attribute $BadClus. The areas mentioned here will be ignored by the filesystem. FAT filesystems save references to broken clusters in the file allocation table.

Capacity: High - This technique uses entire clusters and is therefore only limited by count_of_clusters.

Detectability: Medium - The flag is deprecated and fsck.fat will detect clusters marked as bad.

Stability: High - Bad clusters will no longer be regarded by the filesystem, the hidden data is therefore unlikely to be overwritten.

# Allocate bad clusters and hide data in it
$ echo "TOP SECRET" | fishy -d testfs-fat12.dd badcluster -m metadata.json -w
# read hidden data from bad clusters
$ fishy -d testfs-fat12.dd badcluster -m metadata.json -r
TOP SECRET
# clean up bad clusters
$ fishy -d testfs-fat12.dd badcluster -m metadata.json -c

Reserved GDT Blocks

The reserved_gdt_blocks subcommand provides methods to read, write and clean the space reserved for the expansion of the GDT. Available for these filesystem types:

  • EXT4

The Reserved GDT Blocks will only be used if the filesystem is expanded and additional Group Descriptors are added. The Reserved GDT Blocks are located behind the Group Descriptor Table and its backup copies. The amount of reserved blocks can be seen at offset 0xCE. This hiding technique can hide up to count_reserved_gdt_blocks * count_of_blockgroups_with_copies * block_size bytes. The amount of copies vary depending on the sparse_super flag which saves the copies of the Reserved GDT Blocks in all block groups with group numbers to the power of 3, 5 or 7.

In a 512 MB with a block size of 4096 bytes this technique can hide up to 64 * 2 * 4096 = 524288 bytes. This however would be very easy to detect during forensic analysis. For this reason, the primary reserved area and its first copies are being skipped and the data is only being hidden in the following Reserved GDT Blocks. This will also hide the data from the fsck tool.

First the reserved block IDs have to be calculated. This is being done by using the amount of blocks, amount of blocks per group and filesystem architecture as well as the amount of Reserved GDT Blocks with consideration of the sparse_super flag. This information is gathered from the Superblock. Following the calculation, the block groups can be used to hide data.

Capacity: High - reserved_gdt_blocks * block_groups * block size bytes can be hidden.

Detectability: High - Several analysis tools and checking the hex editor can quickly reveal the hidden data.

Stability: Medium - The hidden data is safe as long as the filesystem isn't expanded. If an expansion happens the hidden data will be overwritten.

# write int reserved GDT Blocks
$ echo "TOP SECRET" | fishy -d testfs-ext4.dd reserved_gdt_blocks -m metadata.json -w
# read hidden data from reserved GDT Blocks
$ fishy -d testfs-ext4.dd reserved_gdt_blocks -m metadata.json -r
TOP SECRET
# clean up reserved GDT Blocks
$ fishy -d testfs-ext4.dd reserved_gdt_blocks -m metadata.json -c

Superblock Slack

The superblock_slack subcommand provides methods to read, write and clean the slack of superblocks in an ext4 filesystem. Available for these filesystem types:

  • EXT4

Depending on the block size there can be a slack space after each copy of the superblock in every block group. If the block size in 1024 byte there will be no slack space as the superblock has a size of 1024 byte. The amount of copies of superblocks is dependent on the sparse_super flag. If the flag is set there will be significantly less potential hiding space.

The potential hiding space is usually multiple KB. Every copy of the superblock can hide block_size - 1024 Bytes of data. The primary superblock is an exception - due to the bootsector also being present, only block_size - 2048 Bytes is free.

This hiding technique first gathers all block IDs of copies of the superblock with consideration to the sparse_super flag. Afterwards, depending on the block size, the data is being hidden in the slack spaces. The hidden data benefits from characteristics of the superblock - it is virtually impossible for the data to be overwritten as there usually is no data written to the superblock slack. Though just like other slack space related hiding techniques it is easily discoverable to forensic analysis.

Capacity: Medium - block size - 2048 + superblock copies * (block size - 1024) Bytes can be hidden.

Detectability: High - Similar to the GDT Reserved Blocks method, some forensic tools and manual analysis can find this hidden data easily.

Stability: High - Data in superblock slack will not be overwritten

# write int Superblock Slack
$ echo "TOP SECRET" | fishy -d testfs-ext4.dd superblock_slack -m metadata.json -w
# read hidden data from Superblock Slack
$ fishy -d testfs-ext4.dd superblock_slack -m metadata.json -r
TOP SECRET
# clean up Superblock Slack
$ fishy -d testfs-ext4.dd superblock_slack -m metadata.json -c

OSD2

The osd2 subcommand provides methods to read, write and clean the unused last two bytes of the inode field osd2. Available for these filesystem types:

  • EXT4

The osd2 hiding technique uses the last two bytes of the 12 byte osd2 field, which is located at 0x74 in each inode. This field only uses 10 bytes at max, depending on the tag being whether linux2, hurd2 or masix2. This results in count_of_inodes * 2 bytes hiding space, which is not much, but might be enough for small amounts of valuable data, because it's not easy to find. ext4 introduced a lot of checksums for all kinds of metadata, which leads to invalid inode checksums. In an ~235Mb image with 60.000 inodes this technique could hide 120.000 bytes.

To hide data, the method writes data directly to the two bytes in the osd2 field in each inode, which address is taken from the inode table, until there is either no inode or no data left. The method is currently limited to 4Mb.

Capacity: Low - Every Inode can only hide 2 Bytes.

Detectability: Low/High - Analysis tools like fsck can recognize changed checksums so hidden data can be found. If the checksum is being calculated after the data is hidden, it highly unlikely to be found by fsck or similar tools.

Stability: High - The 2 bytes used to hide data are not used and will therefore not be overwritten.

# write int osd2 inode field
$ echo "TOP SECRET" | fishy -d testfs-ext4.dd osd2 -m metadata.json -w
# read hidden data from osd2 inode field
$ fishy -d testfs-ext4.dd osd2 -m metadata.json -r
TOP SECRET
# clean up osd2 inode field
$ fishy -d testfs-ext4.dd osd2 -m metadata.json -c

obso_faddr

The obso_faddr subcommand provides methods to read, write and clean the unused inode field obso_faddr. Available for these filesystem types:

  • EXT4

The obso_faddr field in each inode at 0x70 is an obsolete fragment address field of 32bit length. This technique works accordingly to the osd2 technique, but can hide twice the data. Taking the 235Mb example from above, this method could hide 240.000 bytes. Besides that it has the same flaws and advantages.

Capacity: Low - count_of_inodes * 4 bytes can be hidden

Detectability: Low/High - Analysis tools like fsck can recognize changed checksums so hidden data can be found. If the checksum is being calculated after the data is hidden, it highly unlikely to be found by fsck or similar tools.

Stability: High - These inode fields are not being used and the data will therefore not be overwritten.

# write int obso_faddr inode field
$ echo "TOP SECRET" | fishy -d testfs-ext4.dd obso_faddr -m metadata.json -w
# read hidden data from obso_faddr inode field
$ fishy -d testfs-ext4.dd obso_faddr -m metadata.json -r
TOP SECRET
# clean up obso_faddr inode field
$ fishy -d testfs-ext4.dd obso_faddr -m metadata.json -c

Additional Commands

In addition to creating a test image (to see how that's done visit this page) and the hiding techniques, there are two more commands to help you use this toolkit.

FATtools

To get information about a FAT filesystem you can use the fattools subcommand:

# Get some meta information about the FAT filesystem
$ fishy -d testfs-fat32.dd fattools -i
FAT Type: FAT32
Sector Size: 512
Sectors per Cluster: 8
Sectors per FAT: 3904
FAT Count: 2
Dataregion Start Byte: 4014080
Free Data Clusters (FS Info): 499075
Recently Allocated Data Cluster (FS Info): 8
Root Directory Cluster: 2
FAT Mirrored: False
Active FAT: 0
Sector of Bootsector Copy: 6
# List entries of the file allocation table
$ fishy -d testfs-fat12.dd fattools -f
0 last_cluster
1 last_cluster
2 free_cluster
3 last_cluster
4 5
5 6
6 7
7 last_cluster
[...]
# List files in a directory (use cluster_id from second column to list subdirectories)
$ fishy -d testfs-fat12.dd fattools -l 0
f 3 4 another
f 0 0 areallylongfilenamethatiwanttoreadcorrectly.txt
f 4 8001 long_file.txt
d 8 0 onedirectory
f 10 5 testfile.txt

Metadata

Metadata files will be created while writing information into the filesystem. They are required to restore those information or to wipe them from filesystem. To display information, that are stored in those metadata files, you can use the metadata subcommand.

# Show metadata information from a metadata file
$ fishy metadata -m metadata.json
Version: 2
Module Identifier: fat-file-slack
Stored Files:
File_ID: 0
Filename: 0
Associated File Metadata:
{'clusters': [[3, 512, 11]]}

Encryption and Checksumming

Currently, fishy does not provide on the fly encryption and does not apply any data integrity methods to the hidden data. Thus its left to the user, to add those extra functionality before hiding the data. The following listing gives two examples, on how to use pipes to easily get these features. To encrypt data with a password, one can use gnupg:

$ echo "TOP SECRET" | gpg2 --symmetric - | fishy -d testfs-fat12.dd badcluster -m metadata.json -w

To detect corruption of the hidden data, there exist many possibilities and tools. The following code listing gives an easy example on how to use zip for this purpose.

$ echo "TOP SECRET" | gzip | fishy -d testfs-fat12.dd badcluster -m metadata.json -w
Clone this wiki locally