- Hello, and welcome to my talk
on hacking the DEFCON 27 Badge.
My name is Seth Kintigh.
My background is hardware and computer security.
So this project was a lot of fun for me.
I just wanted to give a little background
on some of the terminology we'll be using
in this presentation.
NFMI, near field magnetic inductions.
It's basically using magnetic waves
and fields to communicate instead of radio.
And magnetic fields decay much faster rate
than a radio does,
passes us through body tissues better.
So it's better for short distances,
for body area networks.
The short distance supposedly it makes it more secure.
It's more efficient and hasn't been used too much.
Basically it uses two coils to communicate with each other,
sort of like electromagnets
or half of the transformer talking to each other
instead of using antennas.
And it's used in proximity cars
as part of the NFC protocol.
And it's using some hearing aids and I think some earbuds,
but not too many other locations.
And maybe they had dreams of putting it in Apple earbuds
because I read that somewhere in a blog,
but the company was extremely cagey
about any sort of information on these chips.
There was no data sheet at all, which is bizarre.
No info on the protocol, no dev kits, no samples.
If you wanted to order anything
you had to order tens or hundreds of thousands
and sign an NDA
Just couldn't find any real official info on these chips.
Software defined radio,
basically taking all the hardware guts
and making them virtual and putting them into software
that makes designing new radios
and mixing and matching parts much easier
and more fun.
I used a new radio to do that sort of thing and modulate
demodulate signals.
Some other tools with that too.
I used HackRF to receive and transmit my signals
and tune them.
There's no antennas,
but I made a bunch of coils just wrapping
electromagnet electromagnet wire.
And I should probably have some pictures of those
online at some point.
And used Python for everything else.
A few other terms you should know,
buffer overflow, TAG,
just how that works.
I'm sure most of you familiar with that.
Basically just blow everything on the stack
and keep on writing until you overwrite
the return address and take control of a program.
SWD or J-TAG,
those are different low level hardware,
debug interfaces, or like GDB, but super low level,
control the clock one cycle a time.
Fun stuff.
And then a convolution code,
basically error correction code
spreads out bits over multiple symbols
to make them more resistant to noise.
So the badge was part of a game.
They communicated the badges,
communicate with each other
and they'd make little beeping noises
and blink lights when they paired with each other.
And then if you paired with a magic badge,
it would advance the stage of the game you were in
and there were six stages.
And you advanced once for each of these
different magic versions of these flavors of badge.
And then once you got all of them,
you won by getting a piezoelectric rick-roll.
The badges are actually cut from pieces of stone.
And there was a great presentation on that,
should check out.
The badge hardware has an MCU that does most of the work,
controls the lights and speakers and whatnot,
and talks to the NFMI chip over UART.
When the MCU boots up,
it loads firmware.
And in that firmware,
there's a little patch of firmware for the NFMI chip,
and it sends that over UART
and patches that on boot up.
The debug hardware, debug interfaces,
are labeled on this picture.
You can connect by serial and talk to a console
that's running on the MCU,
or you can connect to a SWD
and do some really low level debugging.
There's no connectors on there.
In that picture,
there's a connector soldered onto the serial port,
but they're unpopulated connectors for now.
And you can either solder on a connector
or solder wires on directly,
or use a pressure fitting.
The badges communicate in a sort of bizarre way.
When the badge MCU wants to transmit eight bytes,
first, it adds a 'D' to the beginning,
then pads every single four bits, every nibble,
with a 'D' and then ends it with an ASCII 'E',
sends out over UART,
the NFMI chip receives that,
immediately strips all of that padding off and transmits it.
And the receiving badge receives that,
puts all that padding back on again,
sends it over UART,
And then the badge strips it all off again.
Early on in the game,
I decided to reverse engineer the code
that someone had pulled the firmware off the badge.
So I reverse engineered it and looking through,
and after a few hours of that, someone,
I think it was Joe Grant, actually,
released the source code.
So there was sort of wasted time.
But on the other hand,
I'd never actually seen all the correct answers
when reverse engineering code before,
but it was a new experience.
I tried plugging into Ghidra.
It didn't work very well back then.
I don't know if it still does.
I ended up using an old version of IDA Pro
and it worked a lot better.
While poking through with IDA
I found a buffer overflow and it seemed so obvious.
I sure was sure it had to be part of the game.
As you can possibly tell from the code,
it's basically reading bytes into a buffer
until it finds a letter 'E',
and it will read that buffer is 18 bytes total,
but there's no limit at all.
Just read and read and read and read and read
until it finds that 'E'.
I made a proof of concept early on.
I wanted to make sure this buffer overflow
was actually exploitable.
So in note pad, I wrote up some arm code
and just used an online assembler
to convert that into machine code.
And I wrote this little script here
to use a J-Link over SWD, not J-TAG.
I connected to the badge,
loaded my payload into the ring buffer.
I set the transmit index and the receive index values,
and this told the batch to run.
It thought it had a giant packet,
and we'll see what happens.
This is the serial console for the badge.
I'm telling it to receive a packet.
Now I'm going to send it one,
a regular valid packet.
And that's what it displays.
Now I run my hack through J-Link.
So now there is a oversized packet
sitting in the ring buffer.
Next time I tell the batch to receive it,
my code takes over,
prints "hack the planet" on the screen.
Well, that worked.
So now I just need to figure out how to send
a gigantic custom crafted packet.
So I dug around online for specs on this chip
used on this badge, the FNMI chip.
Found a few details,
some good guesses on frequencies and bandwidths.
A pretty good guess on the modulation
from a lot of random sources.
Started looking at the signal in analog.
First, on the top row you see 16 bursts
over about 10 seconds.
Middle row, I magnified one of those bursts,
so you can kind of see where the different sections are.
In the bottom row,
lets you see the four distinct sections of each burst.
Section one seems to be timing pulses,
sends the carrier frequency,
and then one that's 150 megahertz higher
and then one 150 megahertz lower.
It doesn't seem to be transmitting any data,
but it may be doing this just to establish
a range of frequency and amplitude of the signal,
as well as timing.
Quick note on down conversion,
if you're familiar with the subject.
You're not demodulating the signal,
you're not changing at all,
other than lowering the frequency
by multiplying it with another signal.
Had to think of it like a beat frequency in music.
So you're just shifting the signal down from,
say, 10.569 megahertz.
You're shifting that down to zero megahertz.
So now all the energy is circling around that
plus or minus 200,000 kilohertz.
And you can see how the signals that were
at the carrier frequency are now basically
flat lines because they're at zero
or almost zero.
And what whole bunch of squiggles
that want to look much different from each other
are now much more clearly data.
You can see those repeating patterns in them.
So section two has these patterns
that plays them twice,
sometimes exact copies.
Sometimes they're inverted.
Sometimes they swap places between I/Q
and there's only, I think,
eight different patterns it shows.
I ended up calling these preambles
based on them showing up later in the other packet.
Section three just seems to be more timing.
Tried my best to get it exactly zero hertz
and never quite could.
And then the frequency would drift,
I think with temperature, I don't really know.
And then section four was data.
271 copies of the same data packet.
Each one starts with eight variations.
Of those preamble you saw in section two
are almost exactly that preamble.
it's slightly different
and then followed by data and then
a brief null or pause.
And sometimes they are exact copies of each other
and sometimes they're inverted.
Sometimes the I/Q swap just like with the preambles
in section two.
The modulation used is D8PSK.
PSK is phase shift keying.
It's basically modulating a signal.
So when you plot it,
it shows up as, the bursts show up as,
one of those eight dots on that constellation.
It will actually form that on a plot,
as long as your timing is right.
The eight refers to there being
eight points in that constellation
and then 'D' means differential.
So it's the difference between each point,
is where your actual data is transmitted.
And each of those points is called a symbol.
The center frequency seems to move a little bit.
In the beginning I had one frequency
that I just narrowed down
to a very precise frequency.
It was working very well until I broke the badge
and then it switched to 1.4
and then later on I fixed another badge
that had broken earlier and it was using 1.569 megahertz.
So I don't under quite understand why the frequency
bounces around so much.
It was initially using a sample rate of
2 million samples per second,
but the timing didn't work out and I said,
"Oh, well obviously if it's 596 kilohertz bandwidth,
then I need to use a multiple of that for the sample rates."
So I use the 1.192, but that didn't work out either.
And I ended up using this 1.19055,
and that worked out perfectly for 440 samples per packet,
or four samples per symbol.
Why that number, I don't know.
Using HackRF to receive the signal,
it does the down conversion and resampling.
So I can use an easier to use frequency.
And it was just a much lower sampling rate
because your sampling rate must be at least
twice your highest frequency than your signal.
And then I use GNURadio to write my demodulator.
Now, there were some examples online of some lower order,
like some 4PSK demodulators and modulators.
And I figured it would be easy enough to
modify one of those into 8PSK,
but it ended up being a nightmare.
And the examples used components that don't exist,
or never worked or were broken for other reasons,
and not documented and no one could help,
and the docs were a mess.
And it was kind of a nightmare.
So I made a bunch of working examples
of different flavors of my PSK modulators and demodulators,
and I put them all on GitHub to help other people out.
Now I had to deal with noise and nulls.
There's 271 copies of the same packet,
but they varied a bunch.
But only some of that was the noise.
It turns out that because of those null symbols
at the beginning,
normal D8PSK demodulator doesn't understand
what those are and tries to put them
into one of those eight quadrants.
So it kind of interprets them as eight
for three random symbols.
And then after those nulls,
there seemed to be an actual random symbol,
which is why there was eight different variations
of both the preamble and of the packet.
The nulls were new to me all together,
and you could maybe even call it
sort of a ninth symbol in that constellation.
I Googled around trying to find out other examples of it
and NXP, the maker of this NFMI chip,
they also make this Coolflux BSP audio chip,
and it also uses a similar modulation scheme with nulls.
And those nulls are used for finding the timing of a signal.
So my demodulator spits out a stream of symbols,
which I then I've manually parsed here
just to make them more readable.
So you can see section one is 21 copies
of just blast of that signal,
basically junk in those symbols.
Section two, we see that preamble copied twice,
followed by a little bit of noise,
and I think mostly nulls.
Section three is just more timing blasts.
And then section four is where our actual data lives.
These are the symbols for our packets,
271 copies of them.
They should be identical.
They're not because of some noise.
So I had to write a Python program
to basically ignore the first few bytes or few symbols,
then count up all the different patterns of packet set.
Each flavor of packet are in there.
And then whichever one has the most copies
is judged to be the correct copy.
And the one copy of that one is output.
The preambles consists of 20 fixed symbols,
and then 12 that can be in one of three patterns.
The section two seems to flip randomly
between two different sequences
of those 12 preamble symbols.
I don't know what they meant.
I assumed that the one with mostly zeros
could be like the mask for all zeros,
but it doesn't quite seem to be right.
It could be, I don't know,
never really figured that out.
And then section four,
every single packet always starts with the same preamble,
which is different than the other two.
And here we see the structure of the entire packet.
We've got the header that has those nulls
and that little random byte or random symbol
I'm referring to as the primer.
And then the preamble.
Then we have the packet data,
which is 64 symbols corresponding to 16 bytes.
The first four bytes appear to be a counter.
Then there's one byte that is used as
the length field for the user data.
And then there's 11 bytes available for user data.
But the badge only uses the first eight,
the last three are just left unused.
And then the footer has what all 10 symbols
that change with every single packet
as the counter increments.
So I assumed it was a checksum or CRC of some sort.
Now I need to find the mask,
the zero mask for all of the data,
because if you fill a packet with zeros in the data fields,
you don't get a packet full of zero symbols.
You get a random looking pattern of symbols.
This is the mask that they've used to either
obfuscate what's being transmitted,
or maybe it's used for spread spectrum
or noise or resistance or something,
not entirely sure.
But basically when you send an empty packet,
you don't send all zeros, you send a pattern.
So I was able to able to easily change
the first eight bytes to zeros
and confirmed that there's this crazy mask.
Later on I modified the firmware
to allow the MCU badge firmware
to allow me to send 11 bytes in a packet.
So all those to zeros,
and that's what the pattern you see
on the bottom of the screen.
Though I don't actually see any sort of pattern
in this pattern.
Finding the mass for the other data bytes
was a little more difficult.
I was basically able to confirm
that the counter was counting.
It was counting by binary values,
except it was counting by twos.
And I didn't know if it was starting off odd or even,
I basically had to guess.
And because of the tail that it has
in a chain of symbols
that was covering up some of the other symbols.
So I needed a way to figure out something.
I observed the counter incrementing in that binary fashion
decided, well, I'll just record it for a week.
Eventually it found that after about a week,
it finally flipped the 10th symbol.
So I was able to get 10 of the mask symbols,
and then the tail change afterwards.
I have no idea what those bits are.
So I don't know if there ones are zeroes.
So only the green is what I'm positive
or so I thought were zeros
based on my guess of what was odd or even at the beginning.
And I realized that it took 19.1 hours to get the ninth,
almost a week to get the 10th symbol.
It was going to take decades to get 16 symbols
and over 9,000 years to get all 20.
And I tried to brute force them,
but I just didn't know enough about the math
of what was going on with these symbols and the values.
So I couldn't brute force them
and I needed a smarter way.
Then I got lucky by becoming unlucky.
I murdered a badge.
It got really angry.
It started transmitting a weird pattern.
Instead of 110 symbol packets,
it was doing 108 symbols and 108 nulls.
Transmitted a different frequency
and even weirder,
the counter slid over by four bytes.
So now instead of counting at byte zero through three,
it was counting at four through seven.
And I assumed initially that it set those
first four bytes to all zero,
but by watching it count the upper bytes
that let me figure out, well,
let me confirm the mask for the length byte
and helped me to do some other bytes as well.
So I finally got the mask of the first five bytes.
Though, at least assuming my 0/1 guess was correct,
it was odd or even that it was starting with.
So sometimes it's better to be lucky than smart.
So I finished this up.
We'll kind of fast forward to the future a little bit.
But I later on discovered that whenever you update
the transmission badge or the packet
that the badge transmits to other badges,
it makes the counter count whatever it's counting
count super fast, almost 250,000.
So I wrote a script to count over and over and over,
and that advanced all the bytes of the counter,
which let me confirm more mask bits.
It also let me confirm that my initial guess was zero.
Well that, and the some erratic counting later on
in the future when I was decoding the sequential count.
What should be sequential,
wasn't always sequential.
It was bouncing around by eight or 32 and here and there.
And I realized cause my initial guess was wrong.
So what I found above as a mask
was actually the mask for the value of one.
It was really a mask of zero,
but that also means that when I broke that badge,
instead of all the bytes being zero,
it was also started at one, which is weird.
I don't know what that means.
Next I need to find the checksum mask,
but really there's no way I could figure that out right now.
All I can do is, at least until I figure out the algorithm,
and then figure out the data
and then figure out which part of the packet
that the algorithm actually protects.
Like, does it predict the preamble or not?
You know, so basically I just guessed
by picking symbols that are already seen in the packet
called that zero, or just whatever, and moved on.
So one thing that the counter indicated
was a convolution code is being used.
So for every odd bit that's changed,
whereas we're defining an odd bit as
a bit one with LSB being bit zero.
So if that one, that three, that five,
if any of those change
only a single symbol is changed.
But if an even bit has changed,
then six of the next seven bits are changed
or symbols are changed.
Now that pattern looked suspiciously like
the one used by the Voyager space probe.
I don't know if that's coincidence
or if that's somehow they've been adapted to use this
into the the badge transmission.
I haven't figured that part out yet.
It's also that only half of the bits are being protected
because normally you'd want to
protect all the bits from noise
only having half doesn't do you much good.
So to reverse engineer this,
I started by changing just one bit at a time.
Whenever you change one odd bit,
that would just change one symbol.
And it always adds four to the symbol.
If you change one even bit,
then six of the next seven symbols change,
and in a pattern that depended on how far away
that symbol was from the bit that was changed,
and based on the zero mask
that was used at that location.
So I figured out the pattern
through just a lot of making examples
and taking lots of notes
and making crazy Excel sheets,
and finally figured out the math
of how a mask changes each bit at each position.
I've listed it by the symbol positions
and then also listed it twice in two ways.
One, is the code,
basically Python code of where the mask is,
like what values the mask is.
And then if that mask exists in that position,
like say mask is in one, two, five, or six.
So if it isn't, that's a one times four plus two.
And as a more lower-level electrical engineer
sort of way to think about it,
I also put it as an array of bits.
So you can look at the bitmap
and possibly that could be related
to the Voyager probe,
but we'll worry about that later.
So that figured out for a single bit,
but once you start using two bits
or changing two bits at a time,
then the math gets really ugly again.
And it just goes crazy.
I tried coming up with really complicated algorithms
to figure it all out,
but I eventually realized, well,
why instead of doing that,
let me just treat everything as just a mask.
Every sum of every step is the mask of the next step.
And made seven different steps like that,
and it all worked out.
So here it is stepping through that.
You start off with the mask
and then you follow those rules from an earlier to change.
If a bit changes, then you add, say, six.
Compute the sum.
That sum becomes the mask for the next little row
or the next, the next, the next.
So that rule of course doesn't make any difference
if you're only changing one bit,
but when you're changing two bits,
say, the mask is three, position zero,
you add three plus two,
you get the sum of five.
Now you use five as the mask
for the next bit down, on and on.
And it actually worked.
Except when I started decoding the counter,
it didn't always count sequentially.
It did most of the time,
but every now and then it would freak out
and then go back to working again.
And I realized that sometimes odd bits are involved
when it's multiple odd bits that have been flipped,
but there wasn't much rhyme or reason to it.
I just started looking for patterns.
And any time I found a pattern that worked
for a lot of the problems,
I would code that pattern up.
That would solve most of them.
But then a few more would slip through.
Just did that a few times
and ended up with these four rules.
All of the rules are interesting
in that they don't care what the current bit is.
They only look at previous bits.
Two of the rules care if previous bits were zero,
instead of one, all those X's are the "don't cares",
and you can see the rules are mostly "don't cares",
but now we know the answer that
all the bits have some sort of
convolution code of protecting them.
The first convolution code that we saw earlier,
it could be that Voyager code,
could be a trials code modulation.
I don't know if that's actually possible,
but I won't go into that.
And then the other compilation code is I have no idea.
I made that little circuit diagram for how I think it works,
but other than that, I didn't recognize it
in anything I looked up online.
So now I need to reverse engineer the CRC.
And early on, I noticed that each packet,
or the CRC has a possibility to contain
basically 20 bits of data in those 10 symbols.
But when I count it up,
the number of patterns that actually showed up,
it was only two of the 12 or 4096 patterns.
So that was telling me it was storing 12 bits in 20 bits,
which was strange.
And then there was also the issue
that when you change a bit,
you can have a tail of up to six changes behind it.
And won't that tail of changes overwrite
the nulls and primers completely destroy the packets?
So something, something odd was going on here.
I also confirmed that all of those symbols had to be used
because if you try changing any of them,
then the packet was rejected.
So clearly all those symbols were being checked.
So they all were important in one way or the other.
And so I need to reverse engineer the CRC
if I ever wanted to send my own custom packets.
I tried this tool called CRC Reveng,
and it just didn't seem to work at all
on the values I was pulling out.
So I said, fine, screw it.
I'll just write a Python program
and brute force every possible CRC algorithm.
And that didn't work either.
So something really odd was going on.
While looking through the CRC values
of a bunch of packets in sequential order,
I noticed that the check sum was changing
by a predictable amount.
Like every time, just the lowest bit changed,
it was XORing the checksum value by the same amount.
Which told me that the checksum
was being built up by XOR probably from a table,
just like a CRC.
And I poked through that some more,
eventually found a pattern to it.
But in the beginning,
what I did was I used all the counter values
to find where it just a single bit
changed between two packets,
XORed those packets,
or XORed the CRCs from those.
And that gave me the XOR value
for that single bit change.
Did that for all the counter bits.
Did that for a few of the length a byte.
Couldn't really do it for all the counter
because even the high counter values
would take months to flip through.
But since I had realized that when you update a packet,
it fast forwards it by some 350,000 clicks.
So I wrote a program to speed it through
a whole lot of those bits.
And then I wrote another program to do a bit walk,
basically change one bit in every data byte
and walk that back and forth through all the data bytes.
And then I wrote a cute little program
to adjust all of those and build up the CRC table.
Now that I had most of the CRC table values for each bit,
I was looking through the changes in them
and noticed a couple of patterns.
And the first was a pattern in how the actual data bits
are stored into those symbols.
And it's kind of ingenious the way they're spread out.
So the first four symbols holds,
or first two symbols holds four bits.
And the next symbol after that holds two bits.
So basically the way that it spread them out,
where the even bits are used
in only the first three symbols,
those even bits, since they have a tail
that can be six long,
that tail doesn't extend the past the end of the CRC.
So it doesn't overwrite the nulls
or anything like that.
So basically it used mostly the odd bits
to store bits from the CRC
and just a few of those even bits.
And it all fit.
And then for just extra fun I guess,
they shuffled the order of those bits all around.
And that shuffling is what made the CRC Reveng fail,
what made my brute force tools fail.
Once I removed the dead bits
and rearranged the bits that actually had
useful info in them,
then suddenly CRC Reveng worked perfectly.
So now I can compute the CRC table for all 16 bytes.
I also noticed a pattern between the values
for every single bit in my table,
and used that pattern to fill up
the rest of the symbols.
But CRC Reveng also showed me the exact name
and algorithm used for the CRC.
So that was nice.
So now my original guess for the mask,
I knew it was wrong in the beginning
for the CRC zero mask,
but it worked anyway.
Cause basically since a CRC is built up by XORs
and it was basically XORing my bad mask,
which had my bad base value,
and all those XORs were canceling out.
And it worked most of the time,
but it was flaky.
Probably because of those three bits
that had tails that weren't quite XORs,
the way the tails change.
So once I figured out the new mask,
everything worked like rock solid.
It was beautiful.
I think the CRC doesn't protect the preamble.
I think it's only covering the data.
I tried coming up with counterexamples.
I tried making a ton of different packets
with using different preambles
and testing all possible CRC values,
and couldn't make any other preambles work.
So that's just an unknown.
Also, I basically went with the assumption
that the CRC of those 16 bytes,
if they were all zero,
that the end result would be zero.
Cause that's how CRCs work,
and based my mask off that,
and it worked.
So with that, I can finally craft my own packets.
So those will be released on GitHub
If they haven't been already.
I can now basically make any 16-byte packet that I want,
except I need a 36-byte packet
in order to overflow the badge
and possibly even more to do any cool attack.
I knew this from the start.
I just assumed that would fall into place along the way,
but it didn't happen.
Never found a field in the packet
that actually let me set a longer packet length.
Skirting around the preamble didn't work.
So it was time to try and reverse engineering
the NFMI firmware.
To extract the NFMI firmware,
I needed to run SWD,
and to do that,
I needed to be able to access the reset line,
which unfortunately was buried in the middle layer
of the board.
The ball on the ball grid array
on the bottom of the chip
also was not accessible.
So I had to pick through slides
and other info from the presentation.
I figured out which ball on the grid it was,
and then zoomed in really close on some of the slides
that didn't have the,
so that middle image it's from the slide.
That's the circuit board
before it has the white paint on it.
So you can kind of see the middle traces faintly
in the middle of the board.
Also with one of my badges,
I scraped all the white paint off
and I cut through the bottom layer of the badge
to remove the metal ground plane
and was able to shine light through it.
And then eventually Joe Grant actually was nice enough
to send me some schematics that showed exactly
where the resets lines were just to confirm,
but that helped me find the reset line.
Now I need to connect to it.
So as you can see the top,
I had to scrape the paint off and the top layer of the board
to get down to that middle layer of the board.
Kind of made like a little C of flux on it,
based on a video I watched of repairing iPhones.
So we'll see a flux
and it was after a few tries
I was able to solder a wire onto this trace
that was smaller than a human hair.
I think this didn't actually work though.
I think I had to go back and actually cut the trace
and then do it again because the MCU
was still connected to the reset
and was like changing the reset
while I was trying to change it
with the SWD commands.
So I think, I don't know.
I think that second uglier image
onto the right of the soldering
is the second time I did it.
And so I was able to connect to it,
but when I hooked the J-Link up to it,
the SWD could not communicate with it.
Cause I didn't know what kind of chip it was.
I was guessing different cortex chips and nothing worked.
I thought, well, maybe you need pull ups,
maybe you need pull downs, maybe there's noise.
Maybe I need to go slower.
I tried everything.
I tried going at like one kilohertz
and nothing was working.
So finally out of desperation
I just started randomly trying the default settings
for a whole bunch of different chips
that were related or even kind of unrelated.
And then one of them just worked.
So I quickly downloaded
the entire memory space I could,
which was a zero to 18000.
and realized at that point, because I guess,
I don't know,
either screwing around earlier
with the reset line being connected to two things
or maybe cutting it,
or maybe just based on the way it boots up,
but whatever little snippet that the MCU firmware
sends over to the NFMI chip, wasn't there.
So the protocol was missing,
but at least I got all of the other hidden stuff.
Because the protocol only makes up like a few hundred,
maybe thousand bytes.
And I got a whole lot more than that
in all those hidden functions and stuff.
So that was very helpful.
So I pulled the NFMI protocol bit out of the MC firmware,
figured out the base address
of the different pieces of it,
and plopped that into the binary I just pulled out,
that 18,000 binary.
And stuck that into IDA Pro.
Once again, I couldn't find anything indicating
a packet length field or anything like that.
And I also confirmed there's code that actually checks
to make sure you're not claiming
to send more than 11 bytes.
And fast forward to the future,
I was able to remove that at one point,
but it doesn't do me any good
cause I can't send more than actually 11 bytes.
So if I fake it,
it'll try outputting it.
But it's outputting like zeroes
and uninitialized garbage
and it wasn't helpful.
But I had seen oversize packets happen before.
I'd even logged them,
as you can see in that log down there.
I'd hacked a badge firmware to spit out
every byte it received and the length.
And after a bazillion length 22s,
I got a length 52 and then it crashed.
It said "Welcome to DefCon" again.
So obviously it's happened spontaneously in the wild.
Why, how, how, why, how do I make that happen?
Well, I was saved by some more bugs in the badge firmware.
So when the NFMI chip sends a packet
over the UART and it's all padded out,
the badge receives it.
But instead of trying to copy the entire packet off of UART,
it just copies one at a time.
So that alone allows a partial packet to be copied
if it runs out of space.
And then there was also this off by one error
where it seemed to make sure there was always
one more spot free.
So basically it's checking for two bytes free
before copying one byte.
And that allowed an odd number or odd-sized packet,
which was nice because it would just chop off
just the 'E' at the end and leave my 'B'
followed by however many bytes of data I had on there.
So then later on,
when the badge actually tries to use that packet data,
it starts with the reading at the 'B',
and it keeps on reading until finds an 'E'.
So with these errors,
I was able to send a 'B'
and then 16 bytes of padded data
and then no 'E'.
I can completely fill up the ring buffer
by just sending a whole bunch of these.
And then I tell the batch to read.
And the moment it reads the first one,
now it's freed up 18 more bytes.
So as long as I'm still blasting these packets,
it will now write a second packet into that hole.
And then the badge will keep on reading everything.
And when it gets to that last packet, it sees a 'B',
and then 16 bytes of these like,
16 of these padded nibbles,
and then another 'B', and then another 16, and then an 'E'.
So as far as it's concerned, it just saw a 33 byte packet.
But wait, there's more.
So if you keep hammering that even more,
it's possible to say on even like the max size 11 bytes,
which ends up being 22 of these padded nibbles.
So I can sound like a B22,
and then it's that off by one error
and chops off the 'E'.
And then when a packet gets read,
frees up enough space that if I'm still writing fast enough
or transmitting fast enough, it can stick another B22
in there was no room for the 'E'.
And then since the badge is reading faster
than I can actually transmit,
by the time I send a third one,
it'll be more than enough space for that 'E'
to fit in there too.
But basically I have now made up a 68-byte packet.
And then I haven't actually played with this,
but I could probably even fill the buffer first
with like super tiny packets,
like two byte packets,
to make reading take much longer.
And maybe you can stack even more than three
of these B22s, B22Es.
So now I can crash a badge at will,
a stock badge.
This takes a long while with a 2048-byte buffer,
and it makes like a pretty boring demo.
So I cheated and I made a badge
that just has a 72-byte buffer.
What I do is I basically fill up the buffer
and then I drain the buffer.
So now that I'm like at a known state,
then I fill the buffer again
and keep on transmitting while that read happens.
And it should crash the badge.
Here, the buffer is full.
I'm gonna empty the buffer.
I switched over to GNURadio
and start playing the packets
as fast as I possibly can.
A little faster than display can keep up with,
and completely fill the buffer.
And the video glitches up for no apparent reason.
And then we go over here,
see the packets,
and it crashes.
The crash is neat,
but could we do something more interesting than that?
Well, unfortunately that padding gets added
to every single packet
and it's going to ruin any sort of attack
that we try to send to something more interesting
than just crash.
So we need to cheat.
I found or deducted the firmware for the NFMI chip
and found where it pads data,
and removed that.
And found that 'B' and 'E' stuff also,
and removed that.
And we can still fake that if we want the badges
to talk to each other like normal,
but now it's optional.
I just found all that code and replaced it with no ops.
But to install that code into the chip,
I had to figure out their crazy format first,
which was just proprietary
and weird and slowed me down for a while.
But once I finally got that in there,
I was able to do a lot more fun attacks.
Here's a freshly reboot badge.
I switched over to GNURadio and I play my attack.
It takes up four packets to fit
the entire buffer overflow attack.
Let's get loaded into the buffer,
switchback to the badge.
I tell the batch to read the packets
and it executes my code.
I'll end with a few oddities and mysteries that remain.
Never quite understood what that initial packet
that it sends out with that 0403E045.
At one point I convinced myself it was a buffer address.
I don't quite remember why anymore.
Sometimes when it's in error, it sends a different code.
I don't know what those mean.
There's also a rev strain and another value next to it.
And I was wondering,
is that supposed to be a frequency or something else?
I was never quite sure about
if it was truly a differential signal
or a double differential signal,
because the preamble suggested it might be double.
Never quite figured out what the rest of the preamble meant.
Not sure if the CRC protects it.
Tried poking out a lot, didn't help.
And where the heck does that mask come from?
I spent a lot of while working on that,
trying to figure out its source,
couldn't figure that out.
And there's gotta be an easy way to stream
or send longer packets.
That would be fun to play with
if I could figure that out
or someone else could.
And what is up with that convolution?
Anyway, that's all.
Thank you very much for watching my presentation.