BTFS FAT extensions overview

Anyone who has to deal with filesystems probably agrees that the last thing the world needs is another mostly-but-not-quite compatible FAT variant. I mean, take a look at the Design of the FAT file system Wiki page. The amount of cruft accumulated over the decades of its existence is impressive. And a few years back, Samsung apparently decided to join in on the fun. Enter BTFS.

Don’t get me wrong, I’m not laying blame on anyone here. Sometimes these design solutions are barely avoidable. But I’d like to help people desperately googling this .btfs?xde* thing, like myself.

I ran into it while studying a moderately sized hex dump of a mobile phone. It had an ordinary FAT16 bootsector and BPB, and the root directory looked normal at a glance. Or did it?

BTFS rootdir entry

You may see three directory entries (DEs) on the screenshot:

  1. an ordinary LFN entry
  2. whaaat?
  3. double “whaaat?”

There’s not much to start an investigation with. The second entry upon careful inspection seems to be an ordinary DE; at least its creation/modification dates, first cluster offset and some flags look sane, but its filename and extension bytes are filled with what looks like garbage.

The third entry looks even more mysterious, but it gives out a hint: .btfs?xde*. Googling for btfs or xde does not prove useful at first, but there’s this obscure Github repo containing a file with some useful definitions. It seems to be the only source of information on the subject at the time of this writing. Also, many comments in it are written in Hangul, but Google Translate handles it just fine.

What is BTFS?

Apparently, BTFS stands for “Beyond the FAT filesystem”. From the source code one might infer that it is developed by Samsung. BTFS is somewhat compatible with FAT, but not really. It seems to have quite a few nice features:

  • DEC: directory entry cache
  • FCC: free cluster cache
  • HPA: hidden protected area
  • WAL: write-ahead log
  • symbolic links
  • extended file attributes
  • extended directory entries: more on these below

What does it all mean? Some of these might be valuable for computer forensics, but I won’t dig into them just yet. Let’s take a look at the basics first.

How to detect a BTFS FAT partition?

BTFS seems to use standard FAT12/16/32 bootsector and BPB structures. I was unable to find any additional flags indicating BTFS presence. However, BTFS contains an XDE (explained below) entry for the root directory a few bytes after the BPB. It is not obvious if this entry is mandatory, nor whether its offset is fixed.

BTFS BPB

The source code contains a macro definition for the XDE offset (ADDON_BPB_XDE_OFFSET), and also a range of its possible values (ADDON_BPB_START_OFFSET_LIMIT and ADDON_BPB_END_OFFSET_LIMIT). The fact that the offset is defined this way suggests that deviations are possible but unlikely (changing the offset would break compatibility).

For now it is probably safe to suppose that the root directory XDE record is always present on a BTFS partition, and its offset is 128 (0x80). The XDE signature (.btfs?xde*) at this offset must be a strong indicator of BTFS presence.

How to work with BTFS partitions?

It depends on what you need. Writing files or metadata will require a deeper understanding of this extension. However, parsing directories and extracting file data requires only a few modifications to the existing, standards-complying FAT code.

First, one must detect BTFS presence, as described above.

Second, one must be aware of BTFS entries in FAT directories. These are not really required to extract file data and may be skipped when detected.

How are BTFS directories structured?

In addition to SFN (FAT short filename) and LFN (VFAT long filename) entries, BTFS directories contain XDEs, extended directory entries:

    uint8_t  signature[10];
    uint8_t  checksum_1;
    uint8_t  attr;
    uint8_t  type;
    uint8_t  checksum_2;
    uint16_t perm;
    uint32_t UID;
    uint32_t GID;
    uint32_t reserved_1;
    uint32_t reserved_2;

I did not dig deeply into the meaning and values of these fields.

  • signature: contains predefined XDE signature, .btfs?xde*
  • checksum_1, checksum_2: these seem to contain LFN checksum (see below for explanation)
  • attr: ?
  • type: ?
  • perm, UID, GID: looks like access control information

Unlike the LFN entries, XDE comes after the SFN entry. Its presence seems to be indicated by the 0x40 (ADDON_SFNE_MARK_XDE) flag set in the SFN’s byte 0x0C. If this bit is not set, XDE should not be present. Another possible flag is 0x80 (ADDON_SFNE_MARK_XATTR) which likely hints at extended attributes’ presence, but I haven’t seen it in my data.

The regular SFN directory entries are not as regular as one might expect. The short filename itself may be not set. In this case the first character seems to always be 0x20 (space), the second one is 0x00, and the remaining 9 bytes are filled with some obscure values.

BTFS SFN

The LFN entries seem to have usual structure, so I won’t get into detail. However, LFN entries in VFAT implementation have the checksum field. The implementation is expected to compute the short file name’s checksum, and to compare it with the one stored in the LFN record. In the case of BTFS this seems to be impossible, since SFNs might be filled with something different. For what it’s worth, the LFN checksum seems to match the checksum_1 and checksum_2 fields of the XDE.

How to recover files from BTFS partitions?

To summarize, one might use a standard FAT implementation with the following tweaks in the directory reading routines:

  • skip over directory entries starting with the XDE signature;
  • beware of SFN entries without actual name data in them, use LFNs instead;
  • adjust or skip LFN checksum verification.

However, just like with other filesystems, the BTFS log might be an invaluable resource for the recovery of lost data. HPA and DEC might also be of interest.