How to fix a corrupted file by brute force

The Challenge

I recently competed in CSAW with a few friends. For those that don't know, CSAW (Cyber Security Awareness Week) is an online CTF where a group at NYU Poly puts up challenges related to computer security.

One of our favorite challenges was called "sharpturn" and hinted about SATA controller failure.
It contained a link to a git repo.

It contained no source files but it still had the git objects tree (typically located in .git/objects/). We downloaded the repo and quickly checked the integrity of the files.

$ git fsck -v

Git complained about 3 corrupted objects.

error: sha1 mismatch 354ebf392533dce06174f9c8c093036c138935f3
error: 354ebf392533dce06174f9c8c093036c138935f3: object corrupt or missing

error: sha1 mismatch d961f81a588fcfd5e57bbea7e17ddae8a5e61333
error: d961f81a588fcfd5e57bbea7e17ddae8a5e61333: object corrupt or missing

error: sha1 mismatch f8d0839dd728cb9a723e32058dcc386070d5e3b5
error: f8d0839dd728cb9a723e32058dcc386070d5e3b5: object corrupt or missing

What we did

For those that don't know, a git object is just a zlib compressed version of a file that is being tracked. It could inflate to be any file. So we uncompressed all of the corrupted git objects to find that they were 3 different revisions of a C++ source file. The f8/* file looked like the latest revision so we looked at that.

zlib-flate -uncompress < objects/f8/d0839dd728cb9a723e32058dcc386070d5e3b5 > source.cpp

Looking at source.cpp, we can see that it asks the user 5 questions:

std::string part1;
cout << "Part1: Enter flag:" << endl;
cin >> part1;

int64_t part2;
cout << "Part2: Input 51337:" << endl;
cin >> part2;

std::string part3;
cout << "Part3: Watch this: https://www.youtube.com/watch?v=PBwAxmrE194" << endl;
cin >> part3;

std::string part4;
cout << "Part4: C.R.E.A.M. Get da _____: " << endl;
cin >> part4;

uint64_t first, second;
cout << "Part5: Input the two prime factors of the number 270031727027." << endl;
cin >> first;
cin >> second;

All of which are pretty simple:

  1. flag
  2. 51337
  3. ok
  4. money
  5. 29, 271, 1103, 31151

Except the 5th question is clearly wrong. There are 4 prime factors to 270031727027, not 2. So this is where challenge starts to become clear: SATA controller failure is hinted at, one of the files is corrupt, and it asks a mathematically impossible question. There must have been bit flips in the file.

We think this even more when we try to compile the file and run into an error:

std::string flag = calculate_flag(part1, part2, part4, factor1, factor2);
cout << "flag{";
cout << &lag;
cout << "}" << endl;

Clearly &lag was meant to be flag. If we look at the ASCII values for '&' and 'f', we see they are 0x26 and 0x66, respectively. If you flip the 7th most significant bit in 0x66, you would get 0x26.

To solve this challenge, my friend Jean-Philippe decided it would be fun to write a program that would combinatorially flip bits on a file in the most efficient way he could come up with. The program loaded the corrupt file into memory and incrementally flipped bits and recalculated the SHA1 hash each time to see if it matched.

If there's more than one bit flipped, this approach could take a very long time. First it would have to check all combinations of flipping 2 bits, then all combinations of flipping 3 bits, and so on. The file we're looking at is 15,120 bits long. So if there are 3 bit flips, this approach would take 15,120 choose 3 operations in the worst case (5.76e+11). Since that would probably take longer then the competition lasted, we had to try it on versions of the file where we fixed the bit flips we already thought were errors.

So we changed the &lag error from before and also changed one question to ask for "31337" because that's leetspeak for "eleet".

cout << "Part2: Input 31337:" << endl;

Running Jean-Philippe's program instantly yielded the correct file after this. Turns out there was only one bit flip left and it was in the "270031727027" string.

Now the program asks:

Part1: Enter flag:
flag
Part2: Input 31337:
31337
Part3: Watch this: https://www.youtube.com/watch?v=PBwAxmrE194
ok
Part4: C.R.E.A.M. Get da _____:
money
Part5: Input the two prime factors of the number 272031727027.
31357
8675311
flag{omitted}

We got the flag and got 400 points in the competition. Most of the challenges rewarded 100-500 points.

You should try it out

I went ahead and made some modifications to the program so we could share it. I probably made the code a little uglier but more user friendly. You can try it out here.

/

Stay updated and subscribe.

Proxying Bluetooth devices for security analysis using btproxy

btproxy

I've recently been interested in investigating the security of new technologies. New devices, especially in the "IoT" realm, use Bluetooth to communicate. I got interested finding a good way to get insight to Bluetooth connections. I wanted to be able to see traffic in clear text and modify it actively, similar to many existing tools for internet traffic. However, there isn't really any cheap and easy methods for doing so.

I wrote a tool that will leverage 1 or 2 regular Bluetooth adapters to act as a proxy for two other devices connecting to each other. Proxying the connection allows insight into clear text traffic and the ability to modify it in real time.

Installation

The code currently lives on Github and currently only works on Linux or OS X. It relies on BlueZ.

Install the dependencies:

sudo apt-get install bluez bluez-utils bluez-tools libbluetooth-dev python-dev

Install btproxy:

git clone https://github.com/conorpp/btproxy
cd btproxy
sudo python setup.py install

Running it on the Pebble Watch

To run it, you will need two Bluetooth devices to proxy (Bluetooth low energy doesn't work yet).

I choose to use my Phone (Nexus 6) and Pebble Steel watch.

So I went ahead and made each device Bluetooth discoverable. For the Nexus 6 running Android L, this just means opening Bluetooth in the settings. For the Pebble watch, you just open Bluetooth in the settings as well.

Now that they are visible, the Proxy can run.

I use hcitool to scan for the devices so I know their Bluetooth MAC addresses.

$ hcitool scan
Scanning ...
        77:88:99:AA:BB:CC   Pebble 9FAA
        11:22:33:44:55:66   conorpp's Nexus 6

Now to run the Bluetooth proxy.

sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC

Notice I put the phone's MAC address first. This is important because the phone is the master device in the connection and the watch is the slave. This master/slave setup is part of the Bluetooth protocol. Slave devices are typically the ones to sit and advertise until a master device requests for a connection. A master can connect to multiple devices while a slave can only have one connection.

credit: sparkfun.com

Now let's follow the output of the proxy.

$ sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC
Running proxy on master  11:22:33:44:55:66  and slave  77:88:99:AA:BB:CC
Using shared adapter
Slave adapter:  hci0
Master adapter:  hci0
Looking up info on slave (77:88:99:AA:BB:CC)
Looking up info on master (11:22:33:44:55:66)
Spoofing master name as  Pebble 9FAA_btproxy
Running inquiry scan
paired
Spoofing master name as  Pebble 9FAA_btproxy
Proxy listening for connections for "Serial Port Server Port 1"
Proxy listening for connections for "Audio/Video Remote Control"
Attempting connections with 2 services on slave
Connected to service "Audio/Video Remote Control"
Connected to service "Serial Port Server Port 1"
Now you're free to connect to "Pebble 9FAA_btproxy" from master device.

The Proxy will look up the name and class of the devices about to be proxied so it can copy the name and class to the Bluetooth adapters being used. In this case only one adapter is being used so it will only copy the slave's properties.

Halfway through this it makes a pairing request to my Pebble watch, to which I accept. The proxy then opens Bluetooth sockets for each service that the watch device hosts, which will be what the phone connects to. The proxy connects to the services on the watch. Once this is done, I connect the master device (my phone) to the proxy device (Pebble 9FAA_btproxy).

Connect on Phone and Pebble app Connect on Phone and Pebble app

btproxy output:

Accepted connection from  ('11:22:33:44:55:66', 1)
>>  b'\x00\x1e\x001\x01\x1b\x07\xe0\xd9\xcb\x89WK\xf7\x9dB5\xbfG\xca\xad\xfe\x01\x01\x00\x00\x00\x02\x04\x00\x01\x00\x00\x00\x00\x01\x00\x11\x00'
<<  b'\x00\x11\x00\x11\x01\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x02\x02\x02\x04\x00'
<<  b'\x00\x01\x00\x10\x00'
>>  b'\x00\x96\x00\x10\x01U\t\xb4\xfbv2.9.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0054664bd\x00\x00\x06\x01R"T_v1.5.5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001c16275\x00\x01\x06\x01R\xe2\xf82102V1\x00\x00\x00\x00Q206134E01L3\xaa\x9f\xa6\xe9\x17\x00&e\x8a\x03U\t\xb4\xfben_US\x00\x00\x01XXXXXXX\x00'
<<  b'\x00\x0b\x13\x89\x00\tmfg_color'
>>  b'\x00\x06\x13\x89\x01\x04\x00\x00\x00\x07'
<<  b'\x00\x01\x17p\x01'
>>  b'\x00\t\x17p\x01\x00\x00\x00\x08\x00\x00\x00\x00'
<<  b'\x00\x05\x00\x0b\x02U\xec^4'

There are two protocols getting dumped here: SPP and Pebble. They are binary protocols which is why it's unreadable. But sending a notification should come up as clear text. Here is what gets logged after I sent myself a text message:

<<  b'\x00F\x0b\xc2\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K_\xecU\x01\x02\x03\x01\x0e\x00(123) 456-6789\x03\x0c\x00Hello Pebble\xff\x05\x00\xfe\x05\x00\x01\x03\x01\x01\x05\x00Reply'

You can see the phone number and the contents of the text message, "Hello Pebble".

Here's the packet sent after I sent myself a Google Hangouts message:

<<  b'\x00b\x0b\xc2\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xf2_\xecU\x01\x02\x02\x01\r\x00Conor Patrick\x03\x1a\x00Sent a message on Hangouts\x01\x02\x01\x01\r\x00Open on phone\x02\x04\x01\x01\x07\x00Dismiss'

You can see it sent two options: "Open on phone" and "Dismiss".

Anything in the packets can be altered in real time using an inline Python script.

For example:

# replace.py
# This replaces the options in a Pebble notification packet

def master_cb(req):

    req = req.replace(b'Open on phone', b'Hi welcome to')
    req = req.replace(b'Dismiss', b'Btproxy')

    print( '<< ', repr(req))
    return req

def slave_cb(res):
    print('>> ', repr(res))
    return res

master_cb is called when the master device (phone) is sending a packet to the slave (watch). And vice versa with slave_cb.

Restart btproxy:

sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC -s replace.py

Then send a notification:

Active packet manipulation

Concluding Thoughts

I've intended this tool to be used for analysis, and can be used for getting security insights for the increasing amount of "IoT" devices out there.

So far I've used it to pull apps, firmware updates, certificates/credentials, and change identifiers.

It's not ideal for an actual attack, unless there was some clever way for forcing already paired devices to unpair and then hope they reconnect to the proxy. Forcing unpairing has been done using an Ubertooth but it's not something that I have looked into yet.

/

Stay updated and subscribe.

Class Prerequisite Graphs for VT

Here are the class prerequisite graphs for all of the departments at Virginia Tech (Fall 2015).

It was made by scraping this page

and passing the results to a graph function in Wolfram Language. Source code (sorry it’s messy).

/

Stay updated and subscribe.