Crypto-Erasing BitLocker Drives

These days with larger and larger drive capacities, erasing stored data takes longer and longer. Another problem is also the inability to do so when the time comes, due to bad sectors or hardware failures. Just because the data is not accessible by you does not mean that it is also inaccessible to someone else with the know-how.

Cryptographic erasure to the rescue!

Crypto erase simply erases the encryption key that is used to encrypt the data on your drive. This is the primary reason why I encrypt my drives.

Oddly, I have not found anyone talking about BitLocker crypto erasure or doing it. The closest I have seen is manage-bde -forcerecovery, which removes all TPM-related key protectors. This is briefly described in a TechNet article titled BitLockerâ„¢ Drive Encryption and Disk Sanitation.

But what if we are not running Windows? What if the disk is not a Windows boot drive that is protected by a TPM key protector?

In order to erase the (key) data, we first need to know how the data is stored on disk. For open-source FDE implementations, this is easy because the disk format is well-documented, but BitLocker is not exactly open.

BitLocker Disk Format

BitLocker was first introduced in Windows Vista and has gone through changes since then. Some changes were made to the format in Windows 7, but has largely remained unchanged through Windows 8 till 10.

For LUKS, it is simple – there is a LUKS header at the start of the disk, followed by the encrypted volume data. For BitLocker, it is slightly more involved, probably due to backward-compatible design considerations.

The header at the start of the partition is a valid boot sector (or boot block), so not all BitLocker information can be stored within. Instead, this volume header points to the FVE metadata block where most of the data is kept. In fact, there are 3 of these for redundancy. This metadata block is what holds all the key material.

The metadata blocks are spaced (almost) evenly apart, located near the start of the volume.

# blwipe -offset 0x2010000 bitlocker-2gb.vhd
metadata offset 0: 0x02100000
metadata offset 1: 0x100c8000
metadata offset 2: 0x1e08f000
metadata block 0 (size 65536): parsed OK
metadata block 1 (size 65536): parsed OK
metadata block 2 (size 65536): parsed OK

The first metadata block usually begins at 0x02100000. This illustration depicts the locations for a 2 GB volume:

Diagram of disk layout with FVE metadata blocks marked out

If there are 3 of these blocks, how do we know know which ones contain valid data?

Continue reading

Advertisements

Writing Code for the ATtiny10

I previously wrote about the hardware aspects of getting your code into an ATtiny10 some 7 years ago (wow that was realllyy a long time ago!).

Now, avrdude is at version 6.3 and the TPI bitbang implementation has already been integrated in. The upstream avr-gcc (and avr-libc) also have proper support for ATtiny10s now. These software components are bundled with most distributions, including the Arduino IDE, making it easily accessible for anyone. Previously a fully integrated and working toolchain only came from Atmel and it was behind a registration page.

The price of the ATtiny10 has also dropped by a lot. When I first bought this microcontroller in 2010, element14 carried it for $1.85 in single quantities. Now, they are only $0.56 each.

I thought I’d write up a short post about writing and compiling code for it.

ATtiny10 on a prototyping board

Continue reading

Framework for Writing Flexible Bruteforcers

When writing a bruteforcer, it’s easiest to think of it as mapping some kind of output to a monotonically-increasing number.

Like for one of the solved PlaidCTF question, the answer string was composed from the eight letters “plaidctf”, which conveniently is a power of 2, meaning each output character can be represented with 3 bits. To write a bruteforcer for a string composed of these characters, you might imagine generating a 3-bit number (i.e. from 0 to 7) then mapping it to the character set for one output character, or a 30-bit number if the output string was 10 characters. Unsurprisingly, this was exactly what I did for my solver script. The output string was generated from a BitVector of 171 * 3 bits.

But what if the output was composed of several different pieces that cannot be represented uniformly as a set of bits?

One solution might be to emulate such a behaviour using an array of integers, like how I modified my solver script in version 2 to handle a character set of arbitrary length.

In this post, I will walk-through writing a basic, but flexible, bruteforcer with accompanying code snippets in Go.

Keeping State

Continuing on the CTF puzzle, the BitVector was replaced with an array of Ints. Each Int will represent one character of the output string. We can thus represent the state like so (for simplicity, let’s limit the output string to 2 characters):

type state struct {
    digit [2]int
}

In order to increment each digit, we can write a function that increments state.digit until a certain number, then resets it to zero.

To make it generic, we will write a function that returns another function that manipulates a digit position, so we don’t have to copy & paste the code for each digit position:

// returns a function that manipulates the digit at given pos
func digitManipulator(pos int) func(*state) bool {
    return func(s *state) bool {
        s.digit[pos]++
        if s.digit[pos] == MAX_NUMBER {
            s.digit[pos] = 0
            return true
        }
        return false
    }
}

We will talk more about the boolean return value later.

Continue reading

X-CTF 2016 Badge Firmware

As promised, we are releasing the source code for the X-CTF badge, about 1 month after the event to give interested participants the chance to take a crack at it. If you are interested in the badge design process, check out my previous post on the hardware aspects.

Jeremias and Jeremy gave a talk at one of the Null Security meetups. Check out the slides if you haven’t already. In one part, Jeremy talks about the custom firmware he wrote for his badge and the additional challenges he set up for partipants to get more points. The 2nd part of the talk covers the electronic badge and challenges.

The Challenges

The challenges try to exploit the nature of being a self-contained electronic device. Rather than trying to replicate more CTF puzzles and simply placing them into the badge, we specially designed them for the badge.

You can find the answers to the badge puzzles (and the main CTF puzzles) in the X-CTF GitHub repo, which was released shortly after the event.

Since there’s only a single entry point into the set of challenges (meaning you must solve each puzzle before getting to the next), the puzzles must be designed with increasing levels of difficulty; too difficult and the participants will totally give up.

Stage 1: Catch Me If You Can

animation of challenge 1

I particularly like this one. Unlike a program running on the computer, you can’t easily snapshot the state of the program, nor try to influence (slow down) its execution.

Continue reading

Unpacking Xiaoyi Firmware Images

Xiaoyi camera

I recently decided to buy new toys to monitor my home — the Xiaoyi IP Camera (I bought more than one). The device itself is round, rather small (as pictured here) and fits into a plastic stand to prop it up. It accepts a microSD card for local recording, and it is only accessible via their iOS/Android app after pairing. The camera is only 720P and goes for 149 RMB (less than US$25).

Since these devices can see a live stream of my house at any time, I would prefer them to be completely within my control. This can be done either via an audit of the firmware or by replacing the firmware with your own (both options are equally tedious). After the “B” firmware version, they also removed RTSP streaming support. You could downgrade to the “B” version, but you won’t benefit from newer changes they have added since then. Let’s get to it.

You can find the firmware images of the Xiaoyi camera online, typically in a ZIP file. I have provided links to this at the end. Unpacking the ZIP file gives you a single file called home. Running the file command reveals that this is a U-Boot image with the file system image tacked on:

home: u-boot legacy uImage, 7518-hi3518-home, Linux/ARM, Filesystem Image (any type) (Not compressed), 7974512 bytes, Wed Jan 21 16:14:18 2015, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0x2F0FAD85, Data CRC: 0x4B21D5F9

To get to the file system image, a StackExchange answer recommended using U-Boot’s mkimage and a bit of file manipulation to carve out the data. This made me almost want to write my own tool in Python but fortunately someone had already done this before. Use uImage.py from that site to extract the file system image from this home. The file system image is a JFFS2 image named 7518-hi3518-home, and our next mission is to mount it.

Continue reading