WEBVTT

00:00.000 --> 00:01.280
Hello and welcome.

00:01.280 --> 00:02.700
My name is Mike Ryan.

00:02.700 --> 00:11.640
I'm the founder of Ice9 Consulting, and in this video, I'll cover a new tool I've developed for Bluetooth sniffing with software-defined radios, as well as some background and theory on how I built it.

00:11.780 --> 00:14.280
Before I get into that, I'll introduce my company.

00:14.300 --> 00:20.400
Ice9 Consulting is a boutique consulting firm that specializes in Bluetooth, IoT, and embedded security and development.

00:20.400 --> 00:27.180
For more info, you can email info at ice9.us, and full contact info will be available in a few slides.

00:27.200 --> 00:30.300
I'll open with a question I get asked a lot.

00:30.380 --> 00:31.940
How do I sniff Bluetooth?

00:32.280 --> 00:34.600
It seems like something that should be easy, right?

00:34.620 --> 00:38.240
Like, we've been sniffing Wi-Fi for as long as we've had Wi-Fi.

00:38.260 --> 00:39.940
So how about Wireshark?

00:39.940 --> 00:44.100
It's certainly my go-to for sniffing Wi-Fi and Ethernet, so what about Bluetooth?

00:44.680 --> 00:50.520
As many of you probably know, if you go into Wireshark today and look for Bluetooth, you won't find anything.

00:50.740 --> 00:55.940
At most, if you're on Linux, you might find the btmon interface, but that's not true Bluetooth sniffing.

00:55.940 --> 00:58.300
But that's all about to change.

00:58.320 --> 01:06.820
As of this talk, I'm releasing a new tool that integrates with Wireshark and works with most popular software-defined radios, and here's how it works.

01:06.920 --> 01:10.540
You open up Wireshark, scroll down your interface list.

01:10.700 --> 01:15.660
For each supported software-defined radio you have attached, you should see an entry for Ice9 Bluetooth.

01:16.080 --> 01:22.540
You can click the little gear icon to change some settings, then smash that start button, and voila, you've got Bluetooth packets.

01:22.540 --> 01:24.660
Yes, it really is that simple.

01:24.740 --> 01:33.940
And the best news yet, if you have a HackRF, a BladeRF, or a Usurp B200 or B210, you can finally use it in Wireshark to sniff some Bluetooth.

01:34.120 --> 01:40.760
I'm pleased to release the Ice9 Bluetooth sniffer, available immediately from the URL at the bottom of the slide.

01:40.760 --> 01:42.140
Here's what it can do.

01:42.140 --> 01:48.120
It can detect BLE advertising packets and decode BLE data packets on any channel promiscuously.

01:48.140 --> 01:53.200
It can identify classic Bluetooth laps, and I'm working on adding more features in this space.

01:53.560 --> 02:01.160
With the current hardware, you can listen on up to 56 channels simultaneously, though in practice your CPU will probably limit you to fewer.

02:01.360 --> 02:06.140
For a benchmark, my M1 Macs can listen to 36 channels in real time.

02:06.380 --> 02:09.300
Later in the talk, I'll cover how I'm trying to increase that.

02:09.300 --> 02:15.960
It's written in Portable C, its only dependency other than the SDR libraries is LiquidDSP, and it runs on Mac and Linux.

02:16.020 --> 02:19.900
In principle, it should build and run fine on Windows, but that's not really my bag.

02:19.900 --> 02:22.440
I will gladly accept contributions in this space.

02:22.440 --> 02:24.620
I've also included my contact info.

02:24.760 --> 02:25.680
And that's it!

02:25.680 --> 02:30.260
If you're just here to sniff Bluetooth, follow the instructions to install the software and away you go.

02:30.260 --> 02:40.620
For the rest of you who want to dig a little deeper, I will now take this opportunity to segue into the real title of this talk, Everything I Wish I Had Known About Software-Defined Radios Since 2013.

02:40.720 --> 02:45.820
I picked 2013 because that's when I got my first real SDR, a HackRF Jawbreaker.

02:46.380 --> 02:49.360
I fired up that bad boy and did all the usual things.

02:49.360 --> 02:56.420
More or less the Hello World of SDR applications, I fired up GQRX and tuned the SDR to the middle of the Broadcast FM band here in the states.

02:56.800 --> 02:58.400
Now, this is pretty nifty.

02:58.400 --> 03:02.380
You can watch about 20 stations play on in real time and click on them to listen.

03:02.480 --> 03:08.340
Eagle-eyed viewers may even be able to spot some digital sidebands of the in-band on-channel HD radio stations.

03:08.400 --> 03:14.320
However, as cool as this is, I knew it was only scratching the surface of what software-defined radios are capable of.

03:14.360 --> 03:17.760
So, I took the next logical step and fired up GNU Radio.

03:17.760 --> 03:21.100
I made a handful of tame flow graphs similar to the one pictured.

03:21.220 --> 03:26.420
However, whenever I really tried to start decoding the signals, I kept running into the same issue.

03:26.420 --> 03:32.580
The flow graphs, blog posts, and YouTube tutorials always got a little... intense, I guess is the word I would use.

03:32.580 --> 03:38.680
They always started out comprehensible enough, but by the end, they'd always end up looking like this picture of Valent Sieber.

03:38.880 --> 03:41.540
Now, I don't mean to denigrate GNU Radio.

03:41.540 --> 03:43.760
It's an excellent tool in capable hands.

03:43.960 --> 03:50.840
This is almost certainly a me problem, but I find when I have problems, sometimes other people have the same problems.

03:50.840 --> 03:53.460
I didn't study digital signal processing in school.

03:53.460 --> 03:55.360
I'm not really a radio guy by training.

03:55.360 --> 03:58.160
I know enough math to be dangerous, and I can sling code.

03:58.160 --> 04:01.100
I was able to figure this stuff out, and I bet you can too.

04:01.120 --> 04:03.880
In order to do so, let's start from the very basics.

04:04.440 --> 04:07.120
What, exactly, is RF?

04:07.240 --> 04:09.640
Borderline philosophical question, right?

04:09.820 --> 04:11.340
Well, that's simple enough.

04:11.340 --> 04:13.700
It's a burst of energy at a given frequency.

04:13.700 --> 04:18.500
That's probably not the most useful definition, so what is it exactly?

04:18.500 --> 04:21.220
If you're watching this talk right now, you're looking at it.

04:21.220 --> 04:22.000
Literally.

04:22.000 --> 04:24.760
Visible light is extremely high frequency RF.

04:24.760 --> 04:26.780
We're talking hundreds of terahertz.

04:26.780 --> 04:31.580
When visible light hits our optic nerves, they emit signals that our brain uses to create images.

04:31.580 --> 04:34.700
We're interested in much lower frequency RF, though.

04:34.700 --> 04:40.020
Let's say about 50 megahertz to 6 gigahertz, which just so happens to be the range of our SDRs.

04:40.160 --> 04:44.440
Let's build a model of a simple broadcast RF system so we have something to talk about.

04:44.740 --> 04:47.740
It all starts with an audio source, like a microphone.

04:47.780 --> 04:52.720
That's wired into some kind of broadcast tower that emits tons of RF on a specific frequency.

04:52.940 --> 05:00.760
That RF travels through the air to the antenna on some kind of radio, like a boombox, where the signal is picked up, amplified, and converted back into sound.

05:00.760 --> 05:03.280
Now let's consider that RF flying through the air.

05:03.320 --> 05:07.500
What if, instead of a boombox, we attached our antenna to a software-defined radio?

05:07.500 --> 05:11.140
When we capture with the SDR, it spits out digital IQ.

05:11.340 --> 05:12.920
What is that exactly?

05:13.220 --> 05:17.860
Well, by way of analogy, let's consider another commonly digitized signal, sound.

05:17.860 --> 05:19.920
Sound is a compression wave through the air.

05:19.920 --> 05:23.100
Air molecules strike a membrane inside a microphone's transducer.

05:23.100 --> 05:29.440
The movement of that membrane is converted to a digital signal, sampled periodically, and we're left with a digital audio file.

05:29.500 --> 05:33.820
In this regard, you can think of a software-defined radio as a microphone for RF.

05:34.160 --> 05:36.740
Armed with that knowledge, how do we interpret the data?

05:37.060 --> 05:40.140
One simple way is to look at the signals in the frequency domain.

05:40.140 --> 05:43.580
This is a spectrogram of someone saying a few words into a microphone.

05:43.640 --> 05:47.160
Time is on the x-axis, and frequency in hertz is on the y-axis.

05:47.340 --> 05:53.500
Simply looking at this is enough for us to glean some patterns, such as the low-frequency voice sounds and the high-frequency fricatives.

05:53.640 --> 05:58.440
You can immediately imagine approaches you might take to processing this data when presented this way.

05:58.600 --> 06:05.100
Let's look at the broadcast FM spectrum, that's 88 megahertz to 108 megahertz, in the frequency domain as well.

06:05.100 --> 06:09.900
Once again, time is on the x-axis, and frequency in megahertz, this time, is on the y.

06:09.900 --> 06:14.220
Aside from the range on the y-axis, it looks quite similar to the previous spectrogram.

06:14.240 --> 06:25.880
Each bright squiggly line is an FM radio station, and in fact, if we zoom in on a few of these, you can see that this frequency domain representation of the RF signal looks an awful lot like a time domain representation of an audio signal.

06:26.000 --> 06:29.560
Hmm, I wonder if this is what they meant by frequency modulation.

06:30.240 --> 06:32.320
Okay, okay, okay, enough background.

06:32.320 --> 06:34.440
This is a talk about sniffing Bluetooth, right?

06:34.440 --> 06:36.160
So let's sniff some Bluetooth.

06:36.260 --> 06:39.600
Step 0, not depicted here, is to find some software.

06:39.960 --> 06:43.420
GQRX or SDR-Sharp are good options depending on your platform.

06:43.520 --> 06:47.160
Step 1, tune your radio to somewhere around 2400 megahertz.

06:47.320 --> 06:49.220
2427 is a good choice.

06:49.360 --> 06:52.220
Step 2, set your sample rate as high as it'll go.

06:52.340 --> 06:55.160
A higher sample rate means you will capture more channels.

06:55.360 --> 06:57.980
Finally, smash that capture button and let her rip.

06:57.980 --> 07:00.140
Give it a few seconds and stop the capture.

07:00.280 --> 07:03.180
Open up your capture and InSpectrum, and there you go.

07:03.300 --> 07:06.040
Each one of these red blobs is a Bluetooth packet.

07:06.040 --> 07:09.480
What's more is that you can clearly see they're organized into channels.

07:09.480 --> 07:12.420
Remember, frequency is on the y-axis in this spectrogram.

07:12.500 --> 07:16.380
For the sake of keeping things manageable, let's target a single channel for sniffing.

07:16.380 --> 07:18.780
In order to do that, we must do two things.

07:18.800 --> 07:27.620
First, in this capture, this particular channel is centered at about 0.5 megahertz, and we need to move it down to 0 megahertz for the rest of our algorithms to work.

07:27.740 --> 07:32.960
Once we've moved it down to 0 megahertz, we have to filter out all the other channels that we're not interested in.

07:33.980 --> 07:36.240
Cool, so how do we do that?

07:36.400 --> 07:39.220
First, moving a radio signal around is very simple.

07:39.220 --> 07:42.200
Let's say your signal of interest is at x megahertz.

07:42.200 --> 07:48.000
In order to move it down to 0 megahertz, you simply multiply it by a sine wave at negative x megahertz.

07:48.000 --> 07:53.400
With that taken care of, we can filter out all the frequencies we're not interested in using a low -pass filter.

07:53.660 --> 07:59.220
Typically, at this point, we also decimate the signal to throw away redundant information and make it easier to work with.

07:59.220 --> 08:03.080
What we are left with is a single channel, filtered and ready for demodulation.

08:04.420 --> 08:06.740
Let's look at our filtered centered channel.

08:06.740 --> 08:12.920
Bluetooth is a bursty protocol, which means it doesn't broadcast continuously, but instead sends data in periodic packets.

08:12.940 --> 08:14.620
What does this mean for us?

08:14.620 --> 08:17.720
This means that we can't leave our demodulator running all the time.

08:17.720 --> 08:23.020
Otherwise, 99% of the time we'd be demodulating noise, and that could lead to false detections of packets.

08:23.300 --> 08:25.380
Let's zoom in on a single Bluetooth packet.

08:25.440 --> 08:29.080
We need a way to detect the presence of this packet against the background noise.

08:29.160 --> 08:33.100
One possible way of doing this is to plot the amplitude of the signal over time.

08:33.160 --> 08:37.320
What you'll notice is that when a packet is present, the amplitude goes up by a lot.

08:37.400 --> 08:40.760
One very simple way of approaching this is to then draw a line at some value.

08:40.760 --> 08:42.220
Let's call it squelch.

08:42.280 --> 08:47.860
When the amplitude is below the squelch, we know there's probably noise on the channel so we don't even attempt to demodulate.

08:48.040 --> 08:55.540
Once the amplitude goes above the squelch, or breaks squelch as the jargon goes, we know some burst of RF energy is present on our channel.

08:55.580 --> 09:01.780
Not only that, we can also detect when the amplitude goes below squelch, and after a short timeout we know the burst is over.

09:01.780 --> 09:06.560
This gives us bursts as well as burst lengths, which will be important later, so remember that.

09:06.840 --> 09:07.280
Neato!

09:07.280 --> 09:08.380
We have bursts.

09:08.380 --> 09:10.960
Let's dive a step deeper into demodulating them.

09:11.060 --> 09:12.840
In Spectrum makes this super easy.

09:12.940 --> 09:17.600
Just right click on the spectrogram, point to add derived plot, and click add frequency plot.

09:17.720 --> 09:21.440
This will add some lines to the spectrogram that you can move around to center on the burst.

09:21.440 --> 09:25.340
Be sure to adjust the bandwidth of the filter by making it taller or shorter as necessary.

09:25.340 --> 09:32.400
Once you've done that, in the frequency plot below you'll see what is obviously some kind of digital signal that you could probably decode by eyeball if necessary.

09:32.400 --> 09:35.920
But we don't need eyeballs for this, we have computers to do our bidding.

09:35.940 --> 09:38.180
Let's look at the raw demodulated data.

09:38.380 --> 09:43.020
In Spectrum you can right click on the frequency plot and click export samples to file.

09:43.020 --> 09:45.440
Load up the samples in your favorite graphing software.

09:45.440 --> 09:46.640
I'm using GNUplot.

09:46.640 --> 09:52.660
If you plot them as a time series you get something that, hey, looks exactly like that demodulated signal from in Spectrum.

09:52.800 --> 09:56.220
Now the y-axis on this chart is a value in some strange units.

09:56.220 --> 10:03.340
I think it might be radians per sample or something, but essentially it's proportional to the frequency offset used in the frequency shift keying modulation.

10:03.540 --> 10:10.040
First thing you might notice upon taking a closer look is that the symbols are not centered about zero, they're slightly below zero.

10:10.040 --> 10:19.280
This is called the carrier frequency offset, and it exists because there's some very slight offset between the center frequency of my radio and the center frequency of the transmitter's radio.

10:19.280 --> 10:21.940
Before demodulating we'll have to correct for that.

10:23.240 --> 10:28.460
Next you might notice that the values range from approximately negative 0.2 to 0.2.

10:28.460 --> 10:30.500
This is our FSK deviation.

10:30.560 --> 10:34.840
For our purposes it would be most convenient if the values range from negative 1 to 1.

10:34.840 --> 10:39.000
Let's look into how we correct for carrier frequency offset and frequency deviation.

10:39.200 --> 10:43.500
I searched the literature and honestly didn't come up with a lot of good options for how to approach this.

10:43.500 --> 10:48.760
Back in 2016 Michael Osman presented a really interesting talk on whole packet clock recovery.

10:48.800 --> 10:54.080
As part of this research he published what he calls the median method, and I have taken that and improved upon it.

10:54.380 --> 10:57.500
Thus I present to you the improved median method.

10:57.580 --> 11:01.340
You take the first n points and bucket them into positive and negative values.

11:01.340 --> 11:03.980
If either of those groups is empty reject the packet.

11:04.200 --> 11:09.380
We find the max as the median of the positive points and the min as the median of the negative points.

11:09.540 --> 11:12.220
Our midpoint is the average of the max and min values.

11:12.220 --> 11:14.060
This is our carrier frequency offset.

11:14.280 --> 11:19.580
What we call the scaling factor is half the distance from the midpoint to the max, or the half height of our signal.

11:19.600 --> 11:21.400
This is our FSK deviation.

11:21.700 --> 11:25.580
First we subtract the midpoint from all of the points, centering them about 0.

11:25.620 --> 11:30.280
Finally we divide all the points by our scaling factor, which scales them from negative 1 to 1.

11:30.280 --> 11:33.060
We are left with a normalized corrected packet.

11:33.060 --> 11:36.460
It's centered about 0 and the values swing from roughly negative 1 to 1.

11:36.460 --> 11:37.920
This we can work with.

11:38.260 --> 11:42.060
Any signal processing textbook will tell you that the next step is clock recovery.

11:42.060 --> 11:49.180
This is the process for recovering the original signal clock and phase so that you know exactly when to sample the data so it's in the exact middle of a symbol.

11:49.180 --> 11:53.800
There are a bunch of approaches to do this, including the aforementioned talk by Michael Osman.

11:54.060 --> 11:56.860
Myself, I decided to completely punt.

11:56.920 --> 12:01.200
I finagled things so that the data we process is 2 samples per symbol at this point.

12:01.200 --> 12:04.980
This means we can use every other sample as our symbol or bit value.

12:05.040 --> 12:09.000
The packets are short enough and the clocks are close enough that this works fine for our use case.

12:09.060 --> 12:13.560
That said, if you have a bigger brain than I do, check out the polyphase symbol synchronization method.

12:13.700 --> 12:19.360
Okay, bada bing bada boom, we've turned our digitized analog signal into a pile of bits.

12:19.400 --> 12:22.640
Here's our real Bluetooth packet turned into 1s and 0s.

12:22.640 --> 12:24.340
There's only one slight problem.

12:24.340 --> 12:26.540
We don't know exactly where it begins.

12:26.540 --> 12:28.060
How do we even interpret this data?

12:28.060 --> 12:29.760
For that, we turn to the spec.

12:29.760 --> 12:33.760
The Bluetooth core spec gives us this table as the format of a BLE packet.

12:33.920 --> 12:40.240
You can see they always begin with an 8-bit preamble, which is 010101 or 101010.

12:40.600 --> 12:43.000
Following that is a 32-bit access address.

12:43.000 --> 12:49.580
This value is fixed for advertising packets, and for connections, it's a random value shared by the two parties when they establish the connection.

12:50.000 --> 12:54.600
Following that is a short header, a data field, and a 24-bit CRC for error protection.

12:54.860 --> 12:59.720
If we were building a regular Bluetooth transceiver instead of trying to sniff Bluetooth, our job would be easy.

12:59.720 --> 13:04.900
We would know the value of the access address either because we were part of a connection or we were on an advertising channel.

13:04.900 --> 13:12.040
This means we could search the bitstream for that 32-bit value and know with high fidelity that the remainder of a packet destined for us would follow.

13:12.600 --> 13:14.980
But we're making a promiscuous sniffer.

13:14.980 --> 13:22.080
We want to be able to capture all packets even if we don't have a priori knowledge of their access addresses, so this approach won't work for us.

13:22.080 --> 13:26.520
You might be looking at the preamble and thinking, why not just search for those 2-bit patterns?

13:26.700 --> 13:28.860
Again, this won't work.

13:28.860 --> 13:31.660
Those values are very short and susceptible to noise.

13:31.660 --> 13:34.920
You'd get a ton of false positives and false negatives with this approach.

13:35.040 --> 13:37.100
Instead, I took a novel approach.

13:37.160 --> 13:38.660
Let's zoom in on the header.

13:38.660 --> 13:41.040
The second half of it is a length field.

13:41.220 --> 13:46.660
What if we compare this header field to the length of the burst, since that's a value we know from earlier in the processing chain?

13:46.660 --> 13:48.840
Here's an illustration of the approach.

13:48.840 --> 13:52.500
Pictured is our packet, and let's say the burst length is 78 bits.

13:52.660 --> 13:55.560
First, we assume the packet starts at the beginning of the burst.

13:55.560 --> 14:01.360
You can see the 101010 preamble, followed by our candidate 32-bit access address.

14:01.600 --> 14:04.480
After this is the header, with an 8-bit candidate length.

14:04.720 --> 14:07.600
Let's say our first candidate length is 138 bits.

14:07.600 --> 14:09.360
And note that these values are bogus.

14:09.360 --> 14:12.720
Don't try to compare them to the packet above, because I just made them up.

14:12.800 --> 14:15.140
So our first candidate length is 138 bits.

14:15.140 --> 14:17.120
How does that compare to our burst length?

14:17.200 --> 14:20.160
It's much longer, so that's probably not correct.

14:20.160 --> 14:22.640
This is unlikely to be the start of the packet.

14:23.700 --> 14:27.080
Now we move the start of our packet forward one bit.

14:27.100 --> 14:34.380
Here again we have our preamble, our candidate 32-bit access address shifted over by one bit, and our candidate length shifted over by one bit.

14:34.640 --> 14:39.480
In this case, the candidate length is 74 bits, pretty close to our 78 bits.

14:39.480 --> 14:40.920
Let's remember this one.

14:40.980 --> 14:45.540
For the sake of completeness, let's move forward one more bit and see what the candidate length is.

14:45.540 --> 14:48.380
If we do that, our length comes up as 15.

14:48.520 --> 14:53.160
Compared to 78, that's way too short, so this is not the correct offset for our packet.

14:53.180 --> 14:56.100
That only leaves us with a second case we considered.

14:56.280 --> 15:01.280
This means we know the start of the packet, and our candidate access address is probably valid.

15:01.500 --> 15:04.940
We can decode the rest of the packet and stuff it into PCAP.

15:04.940 --> 15:07.120
Boom, open that up in Wireshark.

15:07.180 --> 15:10.360
Well hold your dang horses, that's not what I showed at the beginning of the talk.

15:10.360 --> 15:12.720
I promised interface lists and buttons.

15:13.260 --> 15:14.740
Enter extcap.

15:14.740 --> 15:20.220
This is a little-known feature of Wireshark that was introduced in 2013 by these two clowns.

15:20.220 --> 15:26.240
Mike Kershaw, who you may know as Dragorn of Kismet fame, as well as yours truly, Mike Ryan, the Bluetooth expert.

15:26.280 --> 15:28.740
These pictures are what we looked like in 2013.

15:29.020 --> 15:30.740
This is what we look like today.

15:31.140 --> 15:41.320
In the intervening, oh my god, nine years, the code has been made a core part of Wireshark and has been available for quite some time for anyone who wants to implement custom interfaces.

15:41.480 --> 15:42.940
It's extremely simple.

15:42.940 --> 15:50.880
You just follow the specification for implementing a handful of command line flags, output PCAP into a pipe, and you get Wireshark support for free.

15:50.880 --> 15:54.500
This feature is really well documented, so I won't go into details here.

15:54.680 --> 15:59.060
If you have something that produces PCAP that you want to add to Wireshark, give this a look.

15:59.360 --> 16:00.920
Anyway, that's that.

16:00.920 --> 16:02.140
Bluetooth and Wireshark.

16:02.140 --> 16:03.500
Talk over, right?

16:03.760 --> 16:05.200
Well, kinda.

16:05.200 --> 16:10.280
That's the hardest part done with, but remember earlier, I said we were only going to look at one channel.

16:10.280 --> 16:12.220
I promised up to 56.

16:12.840 --> 16:14.160
Remember this?

16:14.160 --> 16:16.800
We could just do this 56 times in a row, right?

16:16.800 --> 16:18.140
Once for each channel.

16:18.440 --> 16:21.540
Well, yes we could, but it would be incredibly slow.

16:21.540 --> 16:24.860
I hate to break it to you, but this image is a bunch of lies.

16:24.880 --> 16:28.300
Very few modern digital communication systems work this way.

16:28.640 --> 16:37.040
Let's go back to our image of the Bluetooth spectrum and let me be possibly the first to introduce you to an amazing and incredible tool, the polyphase channelizer.

16:37.180 --> 16:43.440
At its most basic level, it splits the spectrum into equally sized channels and allows you to process them in parallel.

16:43.440 --> 16:48.920
It's built out of polyphase filters, as the name might suggest, and those are completely bonkers.

16:48.960 --> 16:53.380
I can only barely wrap my head around how they work, and they're totally worth looking into further.

16:53.440 --> 16:58.460
Check out Fred Harris's lectures and his book on multi-rate signal processing to have your mind blown.

16:59.180 --> 17:03.940
This finally allows us to get to the overall architecture of the Ice9 Bluetooth sniffer.

17:04.460 --> 17:09.840
It begins with nMHz of RF, where n can be anywhere from 4 to 56.

17:10.040 --> 17:16.240
This gets fed into a polyphase channelizer, which I've configured to spit out n streams that are 2MHz wide.

17:16.660 --> 17:19.620
Remember how I mentioned two samples per symbol earlier?

17:19.660 --> 17:21.420
This is where it comes from.

17:21.420 --> 17:29.000
These streams are fed into n burst catchers, each running in its own thread, that watch the signal amplitude and mark the beginning and end of bursts.

17:29.100 --> 17:33.360
Those bursts are fed into a queue that is serviced by a single burst processor thread.

17:33.400 --> 17:38.020
This is where the FSK demodulation, Bluetooth detection, and PCAP stuffing happen.

17:38.020 --> 17:39.840
From there, we got Bluetooth.

17:40.280 --> 17:42.520
Now, some comments on this architecture.

17:42.660 --> 17:47.500
First, you may be looking at this single burst processor and thinking, why not have a few more of those?

17:47.640 --> 17:53.080
I kept an eye on that queue, and even under very heavy load, it never fills up, so that's not our bottleneck.

17:53.080 --> 17:58.860
Instead, the issue is over here in the polyphase channelizer, and specifically in there, the FFT.

17:59.020 --> 18:05.140
This is not something that trivially paralyzes over threads, so your single core performance will be the limiting factor.

18:05.200 --> 18:11.660
The good news is that this is something that is extremely amenable to GPU acceleration, and that's something I've been actively looking into.

18:12.060 --> 18:14.360
I'll leave you with some parting thoughts.

18:14.420 --> 18:18.720
Remember the carrier frequency offset and FSK deviation that we corrected for?

18:18.760 --> 18:23.020
These are physical properties of the transmitter that can be considered a leakage channel.

18:23.020 --> 18:26.520
If you plot them on a scatter plot, a few things become obvious.

18:26.560 --> 18:35.080
First, if you look at just the purple crosses, the classic Bluetooth packets, you can see near the top there's one cluster, as well as another cluster much lower.

18:35.240 --> 18:40.720
This implies that there were at least two distinct classic Bluetooth devices transmitting when this data was collected.

18:41.100 --> 18:48.060
Similarly, looking at the BLE packets, you can see one cluster here, another here, and a longer potential cluster over here.

18:48.300 --> 18:52.820
There are obvious privacy implications in this, and I'm not the first person to make this observation.

18:53.280 --> 18:58.920
A very interesting paper just came out in the IEEE Symposium on Security and Privacy covering this very topic.

18:59.120 --> 19:03.480
It's not plumbed out for general use, but if you want to experiment with this, the code is available.

19:03.740 --> 19:06.260
Finally, a few pieces of related work.

19:06.260 --> 19:09.220
First is Jiaoxian Jun's BLE Sniffer.

19:09.240 --> 19:13.580
This one is a single-channel sniffer more akin to an Ubertooth or NRF sniffer.

19:13.860 --> 19:19.580
That said, it's very capable and totally worth a look if you have BLE sniffing needs and a HackRF or BladeRF.

19:19.680 --> 19:24.020
Next up is the original GR Bluetooth, which isn't very good and I don't recommend.

19:24.160 --> 19:29.700
However , it's the first open-source Bluetooth sniffer for SDR that I'm aware of, so it at least deserves a shout.

19:30.020 --> 19:37.820
Last up is a paper by Cominelli et al that uses a sniffer architecture very similar to mine and makes use of GPU acceleration in the channelizer.

19:38.020 --> 19:43.200
As I said, this is something I really want to do, and if you're interested, contributions are extremely welcome.

19:43.380 --> 19:57.080
No work is done in a vacuum, and this work in particular could not have been done without the RFHackers Sanctuary and DEFCON, who put on this event, as well as Michael Ostman, Rob Gilduta, Jared Boone, Tal, and The Liquid DSP Project.

19:57.080 --> 20:04.240
Greets, of course, to their eBay Red team, Cousin Nico and all the other cousins, Sammy, Dragorn, Dominic Stupid, and all the other flat ducks.

20:04.240 --> 20:07.240
And, of course, thank you, the viewer.

20:07.340 --> 20:11.060
Here's the info once again, I'll just recap the features quickly.

20:11.240 --> 20:17.780
IceDyne Bluetooth Sniffer can sniff BLE advertising and data packets promiscuously, but it does not yet follow connections.

20:17.980 --> 20:23.500
It can recover laps from classic Bluetooth packets and sniff up to 56 channels simultaneously.

20:23.660 --> 20:26.960
It's written in Portable C and runs on Linux and macOS.

20:27.180 --> 20:31.280
Currently, it supports HackerRF, BladerRF, and Usurp B200 series.

20:31.340 --> 20:35.420
If your favorite SDR is not on that list, let me borrow the hardware and we'll make it happen.

20:35.520 --> 20:41.040
Find me on Twitter at mpeg4codec, email me at info at ice9.us, and thanks for watching.

