Alright, we're still getting that challenge ready. I want to go ahead and give everybody an update of just kind of where we're at. Again, this is the final round. We've got MMM and we've got Hypeboy. We had just the closest match. They were both running locally, but the payloads weren't working remotely. We're not sure why exactly that, we're going to have to go back and look at it. We did have one, our test solver script, we were running at the same time. We were running that remotely on the same server at the same time, just to verify it was still solvable. That was still working, so we're pretty confident that the challenge wasn't broken, but we're hitting our time limit. And unfortunately, because we have a hard stop that we have to attend to and we want to have consistent rules, we had to pull that challenge back at the 50-minute mark. Every challenge in live CTF this year only runs for 50 minutes. And so we've got our sudden death challenge in, which is even easier. We sure hope. This one should be really, really fast. All the sudden death ones are very, very quick. It's just even more nerve-wracking. I feel awful for the players. I know how stressful that can be. We're preparing that right now. We're getting it in the system. And hopefully we'll be prepared for that soon. They're getting the config as real. They're letting the competitors know. So we'll be back shortly. What a nail-biter. So I'm going to pull up the chat again and see if we've missed anything. So the question in chat that I saw was, because this is a double elimination tournament, if MMM wins, will there be another round? And unfortunately, no. This is the last round. The rules that we published and gave to all the teams several days ago, we basically said the competition is double elimination until the very, very end. So if you actually look at the livectf.com bracket that's been posted, there is no other match. This is the last match. Win or lose, this is it. It would be a bummer if Hypeboy doesn't get a second chance, but we didn't have enough time on the schedule. We didn't have enough ability to run that in. Also, this is a way that you sometimes run double elimination matches. It sounds like we're ready, so let's go ahead and queue up the competitors. Let them know that they should be on the page, and we'll do the countdown. Looks like they're both there right now, so let's go ahead and put this in. 5, 4, 3, 2, 1, go! And here we go. And we have the Sudden Death Challenge started. And this is going to decide... I know nothing about this challenge. Do you know? I know a little bit of this challenge. This challenge is called Hopscotch. So they made some changes to it throughout the development, but the basic idea is that you write shellcode, but you control, I think, you control four bytes, and then there are four bytes that you don't control, and so on, repeating. So basically two bytes of shellcode payload plus a two-byte jump over the next four, and you can arrange anything you want. As I said, I might not have the latest version of the challenge in my mind, but I think it's something like this. Just like you said, a two-byte useful, two-byte relative jump, and you continue like that. I've had a very real-world thing similar to that, actually, many years ago, where I had to write a similar payload. I got real good at knowing all the one- and two-byte opcodes in the manual. So Hypeboy went to the debugger very, very quickly as the first thing that they did. MMM, I saw they pulled it up in IDA earlier, and they're back now. They're already copying in the remote address, by the way, this time. In a lot of the matches, we've seen the players not do that until they're actually throwing it against the remote, but now they got it immediately there just to have it so that there's nothing once they have the solution. It is appropriate that, again, this is another shellcoding. This is our sudden-death shellcoding challenge, which makes it appropriate for this particular one. Here it is. And, yes, the challenges will be all in GitHub like last year. So we will publish all of the solutions, all of the challenges, all of our solutions anyways. The teams are welcome to publish theirs as well. So I see here, and I remember the shell script, their export script was that they were just throwing shellcode immediately. I mean, this is sudden death. It's an easy challenge, but it's not that easy. It's a little more than that. So maybe they just did that without even... they just tried it. Like, I don't know, just in case or something. Without even seeing it. Yeah, it's very nice. But I want to switch over to Hypevoid because here we have some actual debugging and stuff going on. And if they're looking at this stream, the awesome stream, you can see what was written out. So they're looking at what bytes were changed, how things have been modified. Now, are the bytes in between actually totally rewritten, or are they just randomized? Do we know what happens to those bytes? So I actually don't remember that part. But if I remember, I think it's a specific byte. It's a specific byte value that just gets placed there. Written each time. Yeah. But, you know, don't quote me on that. And we're seeing Hypevoid have that same kind of workflow as before, right? They're still using that same online assembler, disassembler. They use that to kind of go back and forth. It is interesting. Some people end up using, like, a little command line tool. Like, you know, I had, like, dis.sh or, you know, asm.sh or a little REPL that they'll put something like Capstan into. And then, actually, over there on MMM, what's going on over there? Right. So it looks like they're putting together a shellcode. And maybe they are going to attempt something like what you did. It looks like they're just getting the instructions there. Maybe they will, you know, do the assembly to get the various bytes and then try to maybe piece this together with some jumps or something else. So we'll see how that goes. You see one function there just called remap page as read and executable. And then the, yeah. So we have the export script there with what they are trying to do. Over on Hypeboy, what I've seen, you can see the writing there, again, the hand-coded assembly. So they're doing a similar kind of approach. We've got these two-byte opcodes of the moves, single XOR reg reg. Oh, so if I understand correctly, they are doing the, you see they add some NOPs there? Yes. So they are kind of emulating the, like, the modified bytes. Is it only a single byte that's being written? So this is where I might have been wrong. It might have been, like, you had a few bytes then or something like this. If it's only a single byte that's being written, then I really like that approach. There's no jumps needed. You know what it could be? It could be that they are just adding those NOPs as kind of, like, delimiters to know how to cut up the byte string afterwards. That's a good point, too. They could be then reassembling it later. So, like, you assemble. Because if you just assemble your shellcode, you would just get a string of bytes. And you don't know, like, what bytes correspond to what instructions unless you're using some specific tooling for that. So, like, an easy and hacky way of doing that is to just put that NOP instruction in between each instruction. Then you can easily see these bytes are... It would be kind of, like, similar, like, to just assembling one instruction at a time. But you're doing it in one go, maybe. Here we go. So you notice they've got that sleep in there. I think we're seeing the sleep over on Hypeboy's payload. Because I think they're a little cautious about, like, the network socket, the remote. It may be in their head. They want to run up on something. Are we possibly this close? Are we still just looking at how it's working? It's hard to tell. Like, you know, when they're running these debuggings, you start to see, you know, is it... So they've got a full payload now. And they're going to write that payload into the buffer. Right. So they do a staged approach to this one as well. So they think their stager is working. They're going to go ahead and test it and see if it works. But they might still be... So they're still looking at the payload. They want to watch it run. They're going to check their registers. Yeah. And then... Well, I think there was almost working, but there was this... There's something... I think there's something that's off. It's encircling our assignment. Yeah. Some, you know, a little bit of, you know, frustration or thinking about that. But it's... It seems like they have most of what they need. Yeah. Is it the REX instruction that it's being inserted in between? Well, I don't think I even know what that instruction does. Well, the REX is right on 64-bit, right? Isn't that what puts it in? It's a prefix specifically if it's for... Oh, right. Yes. 64-bit or 32-bit. It was part of... Most of my shellcoding days were all 32-bit. I'm just that ancient. But I believe the REX prefix is... So how will that modify or how will that change the behavior of... No, the trick is you just don't want... You want to avoid it entirely, right? The answer is your payload should just work around it. Right. And in this case, I was just thinking about why... How did their shellcode behave differently due to those REX bytes? We're dividing a pointer. This is interesting. So what's... Yeah, I'm wondering how much... Because, again, there's a lot of ways you could do this. You could try to account for the bytes that are being written by working them into a working functional command. We've seen the pop immediate 8-bit, for example, would be one way you could eat a single byte afterwards. Right. Or pop... And now we have the jump approach here going on. We will see it here. You can see a push, jump, and they're adding the labels. And they're just doing the relative jumps to this. So this, I think, is definitely the way to go, right? Well, sort of. Except that push zero, we don't have a size on it. So depending on if you've got a push zero and it's like a 32-bit immediate, you're going to write five bytes. So A is actually... Yeah, but I think... Right? That's not going to be... No, so let's see. Push... I would have just done four nops under that A label if I wanted to skip over the A label. In fact, actually, I would have used another label. I just would have put the label after and jumped straight to the label, right? And then have my garbage there. Oh, you're saying you put your jump instruction and you put four nops or something. Exactly. Like fake nops. Just put anything you want to get rid of. And then you do the label instead of doing the label plus an offset. I feel like you're just setting yourself up for it. I actually think that push zero is a bad idea. Because I think it's going to default to five bytes. It's going to be a... Was it 68? Right, because there is no immediate... Is there no 16-bit push immediate instruction? No, it's only 8 and 64. Right, so you would have to do something like XOR racks, racks, push racks instead to get that. Or something like this. Let's see. They're jumping over the A1, but I feel like I still don't see... If the bytes that are being written, if those are multiple bytes, I would expect to see multiple bytes of just not padding or something, right? Yeah. Just put a DB. Right. But I mean, this is kind of going in the right direction. But I guess it takes a little while to wrap your head around this way of thinking with the shellcode and do that in an efficient way. Let's check back in with... Hi, boy. It's been a little bit. So we've got a whole bunch of A's. Always a good sign. Yeah. It's a buffer overflow. So a push 44. So... And they're verifying that value. What have we got here? Okay, so I do... Okay, now we do see two byte NOPs here. So we've got two NOPs, or actually more than that in a row. We've got three. Okay, so they're doing an interesting pattern. So it may be that the bytes that are being overwritten are not necessarily contiguous, too. So if they've... I think actually one thing it would have been to do is just write in a bunch of nulls. It probably would have been easier to write a whole bunch of nulls if you could send those and then just see what bytes it ended up at. It might have been an easier hint. It certainly would have helped us poor presenters as we tried to do it as we were watching them solve it. But I'm more confident, at least right now, in the way Hypeboy's payload is looking. Just looking at it as it has those NOPs kind of built in. There's a syscall and a read there. NOPREX, NOPREX, PUSH. Yeah, but I really thought I saw a... Okay, so they're checking the register value. Yeah. And RCX is not good. So they're going to need another... Yeah, so they're working on... Shift left. Okay, interesting. You probably need RCX if it's the whole width measure. That'll encode more efficiently instead of like the CL. No, no, but it's shifting... Because they had a small number and they wanted a larger number. I think they didn't care about the specific value, right? Maybe they just wanted a larger number or... They're trying to... It seems like they're trying to piece this together from these small instructions. Oh, is it possible that they are like doing... Basically making the REX a prefix of the NOP instruction? Yeah, they've done it several times. You can actually see them stepping through it. Right, right. So you effectively then get three bytes of useful... You do like... In each four byte block, you do NOP and then your three bytes of whatever useful stuff, which is actually more efficient than the two bytes plus the relative jump that we were talking about, which MMM is doing. So this is actually... I didn't... So now I'm starting to understand what the NOP idea actually is. Okay, this makes now complete sense to me. And I think this is... I think it's both easier to write and more efficient. Absolutely, because you're going to get... For every sort of chunk of unobfuscated stuff, you're going to get three... And you don't need to fiddle with the labels and stuff when you're writing your assembly. As long as you put your NOPs... And you do have to be a little careful, because some of those prefixes can do weird things. But again, they're stepping through it in the debugger. As long as the debugger doesn't change the behavior... Okay, that's off the end. Where are we at now? Okay, so now it looks like they're just doing them basically one instruction at a time, inserting it. So you get the three byte instruction there. We've seen this pretty consistently. Right. It really doesn't do a lot of... So I would say that this approach is marching steadily towards the answer. Yes. And it will work. The question is, will MMM catch up? Let's go ahead and take a look back at MMM and see what they're up to as well. So again, if they've got a full solution, although... Yeah, so we're still seeing the NOPs, right? We're seeing single instructions and then jumps and then... But you can see there at the top, you don't have the push anymore. You have a XOR AX AX. So you don't have the push with the immediate, which you pointed out would be an issue. Was that a solution? That is... That is there. Is that it? Let me get a... That's it. We have a winner. Congratulations, MMM. Oh my God. Clearly it works. Yeah, it works. Clearly it works. It can't argue with success. Yeah, that's really cool. That was... Oh my God. Congratulations first to both of our finalists. Yeah, that was... They're both unbelievable. They're both fantastic. Really well played. Best of luck. I'm sorry, Hypeboy, we don't have another round for you to be able to try one more time. But that was fantastic. We have to get all the scores over to Nautilus. We got to get the scoreboard. All the teams are going to go to the final awards ceremony. Yeah. And we want to also bring out the live CTF team here too. Right. We've had a lot of folks that you haven't seen on camera. Right. So basically, just to give a very short recap. So over these three days, we have run this knockout tournament that's been running as a sub-event of the DEFCON CTF. We've had all the 12 teams of the DEFCON CTF finals participating in this double elimination, one-on-one bracket, where they each send one person to play. First one to solve goes on. The other person, you know, loses. And yeah, we will, you know, we're going to wrap it up here very soon. And we will be, we will have recordings of all the matches that we have casted. We will be publishing all the challenges on our GitHub together with some information about which team played in which match and links to the vaults and everything. So, you know, if you missed anything, you can go back and watch. You can try the challenges yourself. I think we will try to get the solve times as well. So you can try to like, you know, try to benchmark yourself against those players. We do know, for example, that we had also some network issues on one of the days. So we're going to make sure we upload, like, the full quality videos. So we'll do separate matches. And you can, yeah, we want to see some races. Maybe in the future we'll let you race live. We'll list your challenges as the competitors see it too. And you and the audience. Let's get the rest of our live CTF crew up here. Thanks to all of everybody that was a part of this. That's what Zoom is for. We'll Zoom out. So we've had a bunch of us. Okay, we have a lot of us people here who have been contributing to this. We've had multiple commentators including Josh and Mark here. Thanks to Gamoza for coming out. And this one is on the team. That's all right. Do you want to join us? Do you want to come on camera? Do you want to come on camera? All right. So we'll get the last one. We'll get everybody out here. Yeah, just trying to get everyone here to close out this thing. That last race challenge was actually a last-minute surprise for Kat who joined us. So awesome. All right, we got everybody. That's it. I guess that's it for everyone. We'll say goodbye. Say goodbye. Bye.