DEF CON 29 - Seth Kintigh - OTA remote code execution on the DEF CON 27 badge via NFMI

Aug 5, 2021 17:35 · 7887 words · 38 minute read

- Hello, and welcome to my talk on hacking the DEFCON 27 Badge.

00:06 - My name is Seth Kintigh. My background is hardware and computer security.

00:10 - 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.

00:19 - NFMI, near field magnetic inductions. It’s basically using magnetic waves and fields to communicate instead of radio.

00:29 - And magnetic fields decay much faster rate than a radio does, passes us through body tissues better.

00:37 - So it’s better for short distances, for body area networks.

00:43 - The short distance supposedly it makes it more secure.

00:46 - It’s more efficient and hasn’t been used too much.

00:52 - 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.

01:02 - And it’s used in proximity cars as part of the NFC protocol.

01:06 - And it’s using some hearing aids and I think some earbuds, but not too many other locations.

01:14 - 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.

01:27 - There was no data sheet at all, which is bizarre.

01:30 - No info on the protocol, no dev kits, no samples.

01:34 - 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.

01:47 - 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.

02:02 - I used a new radio to do that sort of thing and modulate demodulate signals.

02:08 - Some other tools with that too. I used HackRF to receive and transmit my signals and tune them.

02:15 - There’s no antennas, but I made a bunch of coils just wrapping electromagnet electromagnet wire.

02:23 - And I should probably have some pictures of those online at some point.

02:27 - And used Python for everything else. A few other terms you should know, buffer overflow, TAG, just how that works.

02:35 - 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.

02:44 - 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.

02:56 - Fun stuff. And then a convolution code, basically error correction code spreads out bits over multiple symbols to make them more resistant to noise.

03:11 - 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.

03:23 - 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.

03:31 - And you advanced once for each of these different magic versions of these flavors of badge.

03:37 - And then once you got all of them, you won by getting a piezoelectric rick-roll.

03:42 - The badges are actually cut from pieces of stone.

03:45 - And there was a great presentation on that, should check out.

03:50 - 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.

04:02 - When the MCU boots up, it loads firmware.

04:05 - 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.

04:17 - The debug hardware, debug interfaces, are labeled on this picture.

04:23 - 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.

04:34 - 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.

04:43 - And you can either solder on a connector or solder wires on directly, or use a pressure fitting.

04:56 - The badges communicate in a sort of bizarre way.

05:03 - 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.

05:23 - 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.

05:32 - Early on in the game, I decided to reverse engineer the code that someone had pulled the firmware off the badge.

05:39 - 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.

05:47 - 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.

05:59 - I tried plugging into Ghidra. It didn’t work very well back then.

06:02 - I don’t know if it still does. I ended up using an old version of IDA Pro and it worked a lot better.

06:08 - While poking through with IDA I found a buffer overflow and it seemed so obvious.

06:12 - I sure was sure it had to be part of the game.

06:16 - 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.

06:30 - Just read and read and read and read and read until it finds that ‘E’.

06:36 - I made a proof of concept early on. I wanted to make sure this buffer overflow was actually exploitable.

06:43 - So in note pad, I wrote up some arm code and just used an online assembler to convert that into machine code.

06:50 - And I wrote this little script here to use a J-Link over SWD, not J-TAG.

06:57 - I connected to the badge, loaded my payload into the ring buffer.

07:02 - I set the transmit index and the receive index values, and this told the batch to run.

07:09 - It thought it had a giant packet, and we’ll see what happens.

07:14 - This is the serial console for the badge. I’m telling it to receive a packet.

07:19 - Now I’m going to send it one, a regular valid packet.

07:23 - And that’s what it displays. Now I run my hack through J-Link.

07:29 - So now there is a oversized packet sitting in the ring buffer.

07:33 - Next time I tell the batch to receive it, my code takes over, prints “hack the planet” on the screen.

07:40 - Well, that worked. So now I just need to figure out how to send a gigantic custom crafted packet.

07:48 - So I dug around online for specs on this chip used on this badge, the FNMI chip.

07:55 - Found a few details, some good guesses on frequencies and bandwidths.

08:00 - A pretty good guess on the modulation from a lot of random sources.

08:08 - Started looking at the signal in analog. First, on the top row you see 16 bursts over about 10 seconds.

08:19 - Middle row, I magnified one of those bursts, so you can kind of see where the different sections are.

08:23 - In the bottom row, lets you see the four distinct sections of each burst.

08:30 - 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.

08:41 - 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.

08:53 - Quick note on down conversion, if you’re familiar with the subject.

08:56 - You’re not demodulating the signal, you’re not changing at all, other than lowering the frequency by multiplying it with another signal.

09:04 - Had to think of it like a beat frequency in music.

09:07 - So you’re just shifting the signal down from, say, 10. 569 megahertz.

09:13 - You’re shifting that down to zero megahertz.

09:15 - So now all the energy is circling around that plus or minus 200,000 kilohertz.

09:23 - 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.

09:35 - And what whole bunch of squiggles that want to look much different from each other are now much more clearly data.

09:43 - You can see those repeating patterns in them.

09:49 - So section two has these patterns that plays them twice, sometimes exact copies.

09:58 - Sometimes they’re inverted. Sometimes they swap places between I/Q and there’s only, I think, eight different patterns it shows.

10:08 - I ended up calling these preambles based on them showing up later in the other packet.

10:16 - Section three just seems to be more timing.

10:19 - Tried my best to get it exactly zero hertz and never quite could.

10:22 - And then the frequency would drift, I think with temperature, I don’t really know.

10:29 - And then section four was data. 271 copies of the same data packet.

10:36 - Each one starts with eight variations. Of those preamble you saw in section two are almost exactly that preamble.

10:41 - it’s slightly different and then followed by data and then a brief null or pause.

10:50 - And sometimes they are exact copies of each other and sometimes they’re inverted.

10:54 - Sometimes the I/Q swap just like with the preambles in section two.

10:59 - The modulation used is D8PSK. PSK is phase shift keying.

11:04 - 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.

11:14 - It will actually form that on a plot, as long as your timing is right.

11:20 - The eight refers to there being eight points in that constellation and then ’D’ means differential.

11:25 - So it’s the difference between each point, is where your actual data is transmitted.

11:31 - And each of those points is called a symbol.

11:37 - The center frequency seems to move a little bit.

11:41 - In the beginning I had one frequency that I just narrowed down to a very precise frequency.

11:48 - 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.

11:59 - So I don’t under quite understand why the frequency bounces around so much.

12:04 - 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.

12:22 - And I ended up using this 1. 19055, and that worked out perfectly for 440 samples per packet, or four samples per symbol.

12:34 - Why that number, I don’t know. Using HackRF to receive the signal, it does the down conversion and resampling.

12:44 - 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.

12:54 - And then I use GNURadio to write my demodulator.

12:58 - Now, there were some examples online of some lower order, like some 4PSK demodulators and modulators.

13:04 - And I figured it would be easy enough to modify one of those into 8PSK, but it ended up being a nightmare.

13:11 - 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.

13:22 - 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.

13:37 - Now I had to deal with noise and nulls. There’s 271 copies of the same packet, but they varied a bunch.

13:46 - 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.

14:00 - So it kind of interprets them as eight for three random symbols.

14:05 - 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.

14:15 - The nulls were new to me all together, and you could maybe even call it sort of a ninth symbol in that constellation.

14:21 - 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.

14:36 - And those nulls are used for finding the timing of a signal.

14:42 - So my demodulator spits out a stream of symbols, which I then I’ve manually parsed here just to make them more readable.

14:50 - So you can see section one is 21 copies of just blast of that signal, basically junk in those symbols.

15:01 - Section two, we see that preamble copied twice, followed by a little bit of noise, and I think mostly nulls.

15:09 - Section three is just more timing blasts. And then section four is where our actual data lives.

15:17 - These are the symbols for our packets, 271 copies of them.

15:25 - They should be identical. They’re not because of some noise.

15:30 - 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.

15:41 - Each flavor of packet are in there. And then whichever one has the most copies is judged to be the correct copy.

15:48 - 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.

16:01 - The section two seems to flip randomly between two different sequences of those 12 preamble symbols.

16:12 - 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.

16:21 - It could be, I don’t know, never really figured that out.

16:24 - And then section four, every single packet always starts with the same preamble, which is different than the other two.

16:34 - And here we see the structure of the entire packet.

16:37 - We’ve got the header that has those nulls and that little random byte or random symbol I’m referring to as the primer.

16:44 - And then the preamble. Then we have the packet data, which is 64 symbols corresponding to 16 bytes.

16:56 - The first four bytes appear to be a counter.

17:00 - Then there’s one byte that is used as the length field for the user data.

17:05 - And then there’s 11 bytes available for user data.

17:09 - But the badge only uses the first eight, the last three are just left unused.

17:15 - And then the footer has what all 10 symbols that change with every single packet as the counter increments.

17:24 - So I assumed it was a checksum or CRC of some sort.

17:30 - 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.

17:46 - You get a random looking pattern of symbols.

17:50 - 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.

18:02 - But basically when you send an empty packet, you don’t send all zeros, you send a pattern.

18:08 - So I was able to able to easily change the first eight bytes to zeros and confirmed that there’s this crazy mask.

18:15 - Later on I modified the firmware to allow the MCU badge firmware to allow me to send 11 bytes in a packet.

18:23 - So all those to zeros, and that’s what the pattern you see on the bottom of the screen.

18:28 - Though I don’t actually see any sort of pattern in this pattern.

18:33 - Finding the mass for the other data bytes was a little more difficult.

18:40 - I was basically able to confirm that the counter was counting.

18:43 - It was counting by binary values, except it was counting by twos.

18:48 - And I didn’t know if it was starting off odd or even, I basically had to guess.

18:54 - And because of the tail that it has in a chain of symbols that was covering up some of the other symbols.

19:00 - 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.

19:12 - Eventually it found that after about a week, it finally flipped the 10th symbol.

19:18 - So I was able to get 10 of the mask symbols, and then the tail change afterwards.

19:27 - I have no idea what those bits are. So I don’t know if there ones are zeroes.

19:31 - 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.

19:41 - And I realized that it took 19. 1 hours to get the ninth, almost a week to get the 10th symbol.

19:47 - It was going to take decades to get 16 symbols and over 9,000 years to get all 20.

19:55 - 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.

20:00 - So I couldn’t brute force them and I needed a smarter way.

20:07 - Then I got lucky by becoming unlucky. I murdered a badge.

20:12 - It got really angry. It started transmitting a weird pattern.

20:16 - Instead of 110 symbol packets, it was doing 108 symbols and 108 nulls.

20:25 - Transmitted a different frequency and even weirder, the counter slid over by four bytes.

20:31 - So now instead of counting at byte zero through three, it was counting at four through seven.

20:38 - 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.

21:03 - So I finally got the mask of the first five bytes.

21:09 - Though, at least assuming my 0/1 guess was correct, it was odd or even that it was starting with.

21:16 - So sometimes it’s better to be lucky than smart.

21:22 - So I finished this up. We’ll kind of fast forward to the future a little bit.

21:28 - 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.

21:46 - 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.

21:58 - It also let me confirm that my initial guess was zero.

22:03 - Well that, and the some erratic counting later on in the future when I was decoding the sequential count.

22:10 - What should be sequential, wasn’t always sequential.

22:12 - It was bouncing around by eight or 32 and here and there.

22:17 - And I realized cause my initial guess was wrong.

22:21 - So what I found above as a mask was actually the mask for the value of one.

22:27 - 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.

22:36 - 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.

22:46 - 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.

22:57 - 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.

23:12 - So one thing that the counter indicated was a convolution code is being used.

23:18 - So for every odd bit that’s changed, whereas we’re defining an odd bit as a bit one with LSB being bit zero.

23:28 - So if that one, that three, that five, if any of those change only a single symbol is changed.

23:36 - But if an even bit has changed, then six of the next seven bits are changed or symbols are changed.

23:43 - Now that pattern looked suspiciously like the one used by the Voyager space probe.

23:50 - 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.

23:59 - 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.

24:11 - So to reverse engineer this, I started by changing just one bit at a time.

24:15 - Whenever you change one odd bit, that would just change one symbol.

24:19 - 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.

24:41 - 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.

24:57 - I’ve listed it by the symbol positions and then also listed it twice in two ways.

25:04 - One, is the code, basically Python code of where the mask is, like what values the mask is.

25:10 - And then if that mask exists in that position, like say mask is in one, two, five, or six.

25:18 - So if it isn’t, that’s a one times four plus two.

25:23 - And as a more lower-level electrical engineer sort of way to think about it, I also put it as an array of bits.

25:30 - So you can look at the bitmap and possibly that could be related to the Voyager probe, but we’ll worry about that later.

25:40 - 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.

25:52 - 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.

26:05 - Every sum of every step is the mask of the next step.

26:10 - And made seven different steps like that, and it all worked out.

26:15 - So here it is stepping through that. You start off with the mask and then you follow those rules from an earlier to change.

26:27 - If a bit changes, then you add, say, six. Compute the sum.

26:33 - That sum becomes the mask for the next little row or the next, the next, the next.

26:38 - 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.

26:48 - Now you use five as the mask for the next bit down, on and on.

26:53 - And it actually worked. Except when I started decoding the counter, it didn’t always count sequentially.

27:04 - It did most of the time, but every now and then it would freak out and then go back to working again.

27:09 - 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.

27:20 - 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.

27:30 - That would solve most of them. But then a few more would slip through.

27:33 - Just did that a few times and ended up with these four rules.

27:37 - All of the rules are interesting in that they don’t care what the current bit is.

27:41 - 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.

28:03 - The first convolution code that we saw earlier, it could be that Voyager code, could be a trials code modulation.

28:10 - I don’t know if that’s actually possible, but I won’t go into that.

28:15 - And then the other compilation code is I have no idea.

28:19 - 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.

28:29 - 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.

28:46 - But when I count it up, the number of patterns that actually showed up, it was only two of the 12 or 4096 patterns.

28:55 - So that was telling me it was storing 12 bits in 20 bits, which was strange.

29:02 - 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.

29:09 - And won’t that tail of changes overwrite the nulls and primers completely destroy the packets? So something, something odd was going on here.

29:20 - 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.

29:28 - So clearly all those symbols were being checked.

29:31 - So they all were important in one way or the other.

29:36 - And so I need to reverse engineer the CRC if I ever wanted to send my own custom packets.

29:42 - I tried this tool called CRC Reveng, and it just didn’t seem to work at all on the values I was pulling out.

29:49 - So I said, fine, screw it. I’ll just write a Python program and brute force every possible CRC algorithm.

29:55 - And that didn’t work either. So something really odd was going on.

30:02 - 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.

30:13 - Like every time, just the lowest bit changed, it was XORing the checksum value by the same amount.

30:22 - Which told me that the checksum was being built up by XOR probably from a table, just like a CRC.

30:33 - And I poked through that some more, eventually found a pattern to it.

30:38 - 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.

30:53 - And that gave me the XOR value for that single bit change.

30:57 - Did that for all the counter bits. Did that for a few of the length a byte.

31:07 - Couldn’t really do it for all the counter because even the high counter values would take months to flip through.

31:14 - But since I had realized that when you update a packet, it fast forwards it by some 350,000 clicks.

31:20 - So I wrote a program to speed it through a whole lot of those bits.

31:24 - 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.

31:34 - And then I wrote a cute little program to adjust all of those and build up the CRC table.

31:44 - 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.

31:55 - And the first was a pattern in how the actual data bits are stored into those symbols.

32:02 - And it’s kind of ingenious the way they’re spread out.

32:06 - So the first four symbols holds, or first two symbols holds four bits.

32:14 - And the next symbol after that holds two bits.

32:19 - 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.

32:39 - So it doesn’t overwrite the nulls or anything like that.

32:43 - So basically it used mostly the odd bits to store bits from the CRC and just a few of those even bits.

32:53 - And it all fit. And then for just extra fun I guess, they shuffled the order of those bits all around.

33:05 - And that shuffling is what made the CRC Reveng fail, what made my brute force tools fail.

33:14 - Once I removed the dead bits and rearranged the bits that actually had useful info in them, then suddenly CRC Reveng worked perfectly.

33:28 - So now I can compute the CRC table for all 16 bytes.

33:33 - 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.

33:43 - But CRC Reveng also showed me the exact name and algorithm used for the CRC.

33:50 - 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.

34:03 - 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.

34:16 - And it worked most of the time, but it was flaky.

34:18 - Probably because of those three bits that had tails that weren’t quite XORs, the way the tails change.

34:25 - So once I figured out the new mask, everything worked like rock solid.

34:29 - It was beautiful. I think the CRC doesn’t protect the preamble.

34:34 - I think it’s only covering the data. I tried coming up with counterexamples.

34:40 - 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.

34:50 - 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.

35:02 - Cause that’s how CRCs work, and based my mask off that, and it worked.

35:10 - So with that, I can finally craft my own packets.

35:14 - So those will be released on GitHub If they haven’t been already.

35:20 - 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.

35:33 - I knew this from the start. I just assumed that would fall into place along the way, but it didn’t happen.

35:38 - Never found a field in the packet that actually let me set a longer packet length.

35:44 - Skirting around the preamble didn’t work. So it was time to try and reverse engineering the NFMI firmware.

35:52 - 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.

36:05 - The ball on the ball grid array on the bottom of the chip also was not accessible.

36:10 - So I had to pick through slides and other info from the presentation.

36:16 - 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.

36:30 - That’s the circuit board before it has the white paint on it.

36:33 - So you can kind of see the middle traces faintly in the middle of the board.

36:38 - 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.

36:53 - 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.

37:05 - 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.

37:15 - Kind of made like a little C of flux on it, based on a video I watched of repairing iPhones.

37:22 - 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.

37:32 - 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.

37:47 - 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.

37:56 - 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.

38:05 - Cause I didn’t know what kind of chip it was.

38:07 - I was guessing different cortex chips and nothing worked.

38:11 - I thought, well, maybe you need pull ups, maybe you need pull downs, maybe there’s noise.

38:16 - Maybe I need to go slower. I tried everything.

38:18 - I tried going at like one kilohertz and nothing was working.

38:22 - 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.

38:35 - And then one of them just worked. So I quickly downloaded the entire memory space I could, which was a zero to 18000.

38:46 - 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.

39:08 - So the protocol was missing, but at least I got all of the other hidden stuff.

39:15 - Because the protocol only makes up like a few hundred, maybe thousand bytes.

39:21 - And I got a whole lot more than that in all those hidden functions and stuff.

39:24 - 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.

39:45 - And stuck that into IDA Pro. Once again, I couldn’t find anything indicating a packet length field or anything like that.

39:53 - And I also confirmed there’s code that actually checks to make sure you’re not claiming to send more than 11 bytes.

40:00 - 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.

40:08 - So if I fake it, it’ll try outputting it.

40:11 - But it’s outputting like zeroes and uninitialized garbage and it wasn’t helpful.

40:17 - But I had seen oversize packets happen before.

40:21 - I’d even logged them, as you can see in that log down there.

40:25 - I’d hacked a badge firmware to spit out every byte it received and the length.

40:31 - And after a bazillion length 22s, I got a length 52 and then it crashed.

40:36 - It said “Welcome to DefCon” again. So obviously it’s happened spontaneously in the wild.

40:43 - Why, how, how, why, how do I make that happen? Well, I was saved by some more bugs in the badge firmware.

40:56 - So when the NFMI chip sends a packet over the UART and it’s all padded out, the badge receives it.

41:05 - But instead of trying to copy the entire packet off of UART, it just copies one at a time.

41:12 - So that alone allows a partial packet to be copied if it runs out of space.

41:19 - And then there was also this off by one error where it seemed to make sure there was always one more spot free.

41:27 - So basically it’s checking for two bytes free before copying one byte.

41:31 - 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.

41:46 - 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’.

41:56 - So with these errors, I was able to send a ‘B’ and then 16 bytes of padded data and then no ‘E’.

42:06 - I can completely fill up the ring buffer by just sending a whole bunch of these.

42:12 - And then I tell the batch to read. And the moment it reads the first one, now it’s freed up 18 more bytes.

42:19 - So as long as I’m still blasting these packets, it will now write a second packet into that hole.

42:27 - And then the badge will keep on reading everything.

42:30 - 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’.

42:40 - So as far as it’s concerned, it just saw a 33 byte packet.

42:48 - 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.

43:01 - So I can sound like a B22, and then it’s that off by one error and chops off the ‘E’.

43:06 - 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’.

43:18 - 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.

43:28 - But basically I have now made up a 68-byte packet.

43:32 - 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.

43:41 - And maybe you can stack even more than three of these B22s, B22Es.

43:51 - So now I can crash a badge at will, a stock badge.

43:56 - This takes a long while with a 2048-byte buffer, and it makes like a pretty boring demo.

44:02 - So I cheated and I made a badge that just has a 72-byte buffer.

44:09 - What I do is I basically fill up the buffer and then I drain the buffer.

44:14 - So now that I’m like at a known state, then I fill the buffer again and keep on transmitting while that read happens.

44:23 - And it should crash the badge. Here, the buffer is full.

44:29 - I’m gonna empty the buffer. I switched over to GNURadio and start playing the packets as fast as I possibly can.

44:37 - A little faster than display can keep up with, and completely fill the buffer.

44:42 - And the video glitches up for no apparent reason.

44:44 - And then we go over here, see the packets, and it crashes.

44:58 - 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.

45:11 - So we need to cheat. I found or deducted the firmware for the NFMI chip and found where it pads data, and removed that.

45:21 - And found that ‘B’ and ‘E’ stuff also, and removed that.

45:24 - And we can still fake that if we want the badges to talk to each other like normal, but now it’s optional.

45:30 - I just found all that code and replaced it with no ops.

45:35 - 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.

45:45 - But once I finally got that in there, I was able to do a lot more fun attacks.

45:51 - Here’s a freshly reboot badge. I switched over to GNURadio and I play my attack.

45:57 - It takes up four packets to fit the entire buffer overflow attack.

46:03 - Let’s get loaded into the buffer, switchback to the badge.

46:06 - I tell the batch to read the packets and it executes my code.

46:13 - I’ll end with a few oddities and mysteries that remain.

46:17 - Never quite understood what that initial packet that it sends out with that 0403E045.

46:24 - At one point I convinced myself it was a buffer address.

46:27 - I don’t quite remember why anymore. Sometimes when it’s in error, it sends a different code.

46:31 - I don’t know what those mean. There’s also a rev strain and another value next to it.

46:37 - 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.

46:55 - Never quite figured out what the rest of the preamble meant.

46:58 - Not sure if the CRC protects it. Tried poking out a lot, didn’t help.

47:04 - 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.

47:13 - And there’s gotta be an easy way to stream or send longer packets.

47:17 - That would be fun to play with if I could figure that out or someone else could.

47:22 - And what is up with that convolution? Anyway, that’s all.

47:26 - Thank you very much for watching my presentation. .