WEBVTT

00:11.110 --> 00:15.450
Hello and welcome back to the final day of live CTF at DEF CON Finals.

00:15.790 --> 00:17.770
This has been a day.

00:17.970 --> 00:21.070
We're starting late, so without further ado, let's just kick it off.

00:21.070 --> 00:22.330
Final thumbs up?

00:22.330 --> 00:23.090
Let's roll.

00:23.090 --> 00:23.850
All right.

00:23.950 --> 00:27.970
Five, four, three, two, one.

00:27.990 --> 00:29.170
Let's go.

00:29.290 --> 00:33.250
All right, so first off, we're gonna be taking a look at Macaroni.

00:33.250 --> 00:36.810
Yeah, so we've got Macaroni versus MMM.

00:37.190 --> 00:40.590
At this point, we're looking at the lower bracket.

00:40.750 --> 00:41.810
They're fighting to survive.

00:41.810 --> 00:42.690
They still have a chance.

00:42.690 --> 00:44.270
They're very close to the finals at this point.

00:44.270 --> 00:47.210
Both of these teams have only lost one match on their runs.

00:47.570 --> 00:50.230
So, it's double elimination bracket.

00:50.310 --> 00:54.470
Whichever team loses this is out in, what is this, fourth place?

00:55.290 --> 00:56.430
Fifth place?

00:57.350 --> 00:58.090
One of those.

00:58.250 --> 00:59.310
Something like that.

01:00.010 --> 01:01.090
They had a good run.

01:01.090 --> 01:02.090
They're in the top half.

01:02.090 --> 01:03.250
We know that for sure.

01:03.310 --> 01:03.830
Definitely.

01:03.830 --> 01:05.730
You've had to win a lot to get this far.

01:05.730 --> 01:06.190
Yeah.

01:06.190 --> 01:16.130
So going into this challenge, is uleb4096 written by our very own Glenn, who's been running production for a large part of us?

01:16.870 --> 01:19.510
This is a pretty straightforward challenge.

01:19.510 --> 01:20.470
It's a challenge.

01:20.670 --> 01:23.590
In terms of the construction, right?

01:23.590 --> 01:27.450
It presents and says, give me some decoded shellcode.

01:27.450 --> 01:28.050
Yeah .

01:28.110 --> 01:34.030
And so the uleb is a reference to the unsigned little endian byte encoding.

01:34.030 --> 01:34.550
Yeah.

01:34.550 --> 01:40.510
Which is a pretty simple encoding, but it's something that I had never seen before I looked at this challenge.

01:40.530 --> 01:40.890
Same.

01:40.890 --> 01:48.610
But I mentioned it to our resident Mac and iOS expert, and she was just like, she took one look at the function, she's like, oh, this is web.

01:48.730 --> 01:49.090
Wow.

01:49.090 --> 01:50.410
I'm like, are you kidding me?

01:50.410 --> 01:51.330
I could have asked you.

01:51.330 --> 01:53.170
I was trying to verify this thing for so long.

01:54.570 --> 01:54.990
Yeah.

01:55.070 --> 01:57.630
So apparently some people know it very well.

01:57.630 --> 01:59.490
So let's hope the competitors do.

01:59.630 --> 02:00.610
At least one.

02:00.630 --> 02:00.970
Yeah.

02:00.970 --> 02:03.590
Well, I mean, so the good news is, is it's just encoding.

02:03.590 --> 02:04.410
It's not encryption.

02:04.410 --> 02:05.490
It's not crazy.

02:05.490 --> 02:09.810
So even if you aren't familiar with it, which I wasn't, you know, you can Google this.

02:09.810 --> 02:14.510
There are functions online in Stack Overflow that talk about how to use this.

02:14.950 --> 02:20.190
Heck, you can ask ChatGPT to write a functional ULIB decoder and it can do that.

02:20.190 --> 02:20.710
Really?

02:20.710 --> 02:20.970
Yep.

02:20.970 --> 02:21.670
Did you try that?

02:21.670 --> 02:22.230
I did.

02:22.230 --> 02:22.570
Oh my goodness.

02:22.570 --> 02:23.570
I'm not ashamed to say it.

02:23.570 --> 02:27.090
I installed the Python lev128 package.

02:27.090 --> 02:28.570
Which was the right thing to do.

02:28.570 --> 02:36.570
I did that too, but then I fell back to the ChatGPT function because I had made a mistake and it wasn't working.

02:36.910 --> 02:42.310
So we see over on MMM, PPP, ducks.

02:42.850 --> 02:44.310
They've had a lot of names.

02:44.310 --> 02:45.570
They've had so many names.

02:45.570 --> 02:46.730
They're going through.

02:46.770 --> 02:52.290
He's running just straight, you know, shellcraft-sh-shellcode, seeing what happens to it.

02:52.490 --> 02:57.250
And then going back into S-tray, seeing what the actual calls are, wondering like, did my registers get messed up?

02:57.250 --> 02:58.330
What's going on?

02:58.790 --> 03:01.890
No, this actually changes the encoding.

03:01.890 --> 03:04.630
Or I guess decoding?

03:04.630 --> 03:05.050
Right.

03:05.050 --> 03:11.950
This is a little bit of a weird challenge to think about because normally you'd think, oh, I've got my bytes.

03:11.950 --> 03:14.950
I want to encode them into some sort of encoding.

03:15.930 --> 03:18.730
But this is actually asking for decoded.

03:18.870 --> 03:24.830
And so you're kind of having to do the mental math of saying, okay, how do I go from decoded to encoded?

03:24.830 --> 03:28.950
Because what gets encoded is what's going to be run as shellcode.

03:28.950 --> 03:29.650
Yeah.

03:29.810 --> 03:35.910
So it's kind of reminiscent of like a targeted plain text attack.

03:36.250 --> 03:38.730
Like, it's really weird.

03:38.730 --> 03:40.130
It's mental gymnastics to get around.

03:40.130 --> 03:46.470
And actually, over on Macaroni, they're looking at the Leb128 Python package we were just talking about.

03:46.470 --> 03:47.390
It's just a matter of time.

03:47.390 --> 03:48.830
And I was thinking about that.

03:48.830 --> 03:53.010
I was interested to see how long would they look at the challenge before looking at the encoding?

03:53.110 --> 04:04.350
Because it's definitely necessary to look at the encoding in this one because the encoding itself enforces a constraint that's actually very difficult for shellcode and really I think is the crux of this problem.

04:04.470 --> 04:04.870
Yeah .

04:05.030 --> 04:11.410
And honestly, one thing I'm learning from this is we can make people install whatever package we want just by making a challenge around it.

04:11.490 --> 04:21.930
You know, I want to say that CTS was the one who famously had said you can use a CTF problem to get people to do work for you.

04:21.930 --> 04:22.950
Oh, it's so true.

04:23.110 --> 04:27.490
We were talking about like, oh, what if we have a challenge where it's please fix our CMake config?

04:27.670 --> 04:28.990
Yeah, exactly.

04:29.050 --> 04:34.490
You know, we can get some of the best hackers in the world to look at it for 48 hours for free.

04:34.950 --> 04:37.290
Imagine, we just need to give them fake points.

04:37.550 --> 04:39.430
People will do anything for internet points.

04:39.430 --> 04:45.610
Honestly, I've stayed up 48 hours straight CTFs just for like a couple of 500 point challenges.

04:46.550 --> 04:54.690
So over on MMM, we see them walking through and they're just trying to get a normal like push A rep.

04:55.270 --> 04:56.150
Right.

04:56.230 --> 04:59.850
So I think what they're doing here is that they're exploring the constraint.

04:59.850 --> 05:02.290
And if I recall, the constraint is that...

05:04.070 --> 05:14.330
So ULAB 128 is the actual encoding decoding going on here, which is to say you can take 128 bits and pack them into bytes is kind of how it ends up.

05:15.070 --> 05:20.890
And so what that means is you don't get the high bit to use as your shellcode.

05:20.890 --> 05:24.190
And that really limits the instructions you can use for your shellcode here.

05:25.170 --> 05:29.090
Now, is it that you don't get the high bit or that it sets the high bit for you?

05:29.090 --> 05:31.210
So you need to pass.

05:31.210 --> 05:32.410
Can you only use...

05:32.410 --> 05:35.610
You can only use instructions that have the high bit set.

05:35.610 --> 05:36.450
Yes, you're correct.

05:36.450 --> 05:36.950
Sorry.

05:36.950 --> 05:44.750
I'm just making sure here because like I said, mental gymnastics, looking at this thing, like trying to verify after casting and running offs all day.

05:44.750 --> 05:47.130
It's been a lot, man.

05:47.130 --> 05:47.770
It's been a lot.

05:47.770 --> 05:52.890
I think Carl was saying that our bingo card is getting full for things that can go wrong.

05:52.890 --> 05:53.330
Absolutely .

05:53.770 --> 05:55.490
We had hardware failure.

05:55.490 --> 05:59.790
We had just at the venue, there was a suspicious package that kicked everyone out.

05:59.790 --> 06:00.190
That's right.

06:00.190 --> 06:01.410
They kicked everyone out for it.

06:01.410 --> 06:03.570
We, this morning, had capture card failures.

06:03.570 --> 06:06.090
We had network problems.

06:06.210 --> 06:08.170
We had proxy issues.

06:08.190 --> 06:09.770
It was, oh, okay.

06:09.770 --> 06:14.150
Now we see MMM finding the same Leb128, PwnedToolsLeb128.

06:14.210 --> 06:15.570
I wish.

06:15.610 --> 06:17.190
That would have made my life easier.

06:17.190 --> 06:18.570
But they have a lot of things.

06:18.570 --> 06:19.890
They don't have everything.

06:20.490 --> 06:28.790
But looking at that same Leb128 crate over on Macaroni, they were just looking at usage docs for it.

06:28.790 --> 06:31.230
I think they're going to, yep, they're doing it.

06:32.090 --> 06:34.790
They're going to plug in the code to chat GPT.

06:35.590 --> 06:36.250
See?

06:36.250 --> 06:38.310
Can you explain this function?

06:38.310 --> 06:39.750
Great minds think alike.

06:39.750 --> 06:40.970
I love it.

06:40.970 --> 06:43.450
You know, but this is a real thing, right?

06:43.450 --> 06:44.470
AI is here.

06:44.470 --> 06:49.130
These LLMs are extremely powerful, can help with a lot of varied things.

06:49.810 --> 06:55.250
You know that it might be showing you some things that are incorrect, right?

06:55.330 --> 06:59.590
But it's still better than nothing, especially when you're pressed for time.

06:59.590 --> 07:01.450
This could give you a little bit of a leg up.

07:01.450 --> 07:02.150
Oh, absolutely.

07:02.150 --> 07:09.990
That forward training and just throwing a question at such a large, like, well, LLM, way better than MLM.

07:09.990 --> 07:15.910
And I only got to see the response there for a second, but it did seem to have recognized it as uleb.

07:15.910 --> 07:16.350
It did.

07:16.350 --> 07:20.650
I'm wondering if that's just from the name and if it's going to give information that might lead him down a rabbit hole.

07:20.650 --> 07:21.130
Good point.

07:21.130 --> 07:23.930
Yeah, you can't trust those AIs.

07:23.930 --> 07:25.990
Just like my grandmother always said.

07:26.830 --> 07:32.570
Over on MMM, we don't see any LLMs, which is surprising because it just rolls off the tongue.

07:32.670 --> 07:43.410
We saw him staring for a second just at the code, trying to get a mental model of what's going on and understanding, OK, so it transforms my code, but my code also needs to match a certain set of constraints.

07:44.310 --> 07:59.670
Yeah, and like I said, this encoding, if you're not familiar with it, which I don't think that either of these players are based on what we've seen in terms of them looking at packages and asking questions about what can this do, what does this do, the constraints aren't clear.

07:59.670 --> 08:03.170
If you read the Wikipedia page on this encoding, the constraint isn't clear.

08:03.170 --> 08:08.810
And so what I think we're seeing on the MMM side is that sort of interactive exploration.

08:08.810 --> 08:20.050
So he had a push instruction, I believe it was a push of a 64-bit register, which all of those instructions are going to have the high bit not set.

08:20.310 --> 08:29.330
And so, like I said, this forcing the high bit actually puts you in a weird spot with the x86 instruction set.

08:29.810 --> 08:39.610
Oh yeah, no, and I mean, unless these guys know off the top of their head, you know, the instruction space blocks and the distribution of them, I think this is going to take them some work.

08:39.630 --> 08:50.130
Yeah, I was asking around on our team for the other folks that had looked at this problem, how did you go about trying to figure out what instructions you had available given that constraint?

08:50.130 --> 08:51.770
Because it's kind of a weird thing to ask.

08:51.770 --> 08:52.950
Oh , it's super weird.

08:53.050 --> 08:59.850
And I think that Jordan's answer was, well, you just go straight to the Intel manual and start reading, right?

08:59.850 --> 09:00.910
Which is valid.

09:00.910 --> 09:01.670
Oh, very, yeah.

09:02.030 --> 09:16.930
And Glenn said, oh, there's a table linked from Stack Overflow somewhere that actually has a pretty decent, oh, here's your leading byte, and then it sort of broke down by the value of the leading byte, what instruction categories you could get, which was pretty helpful.

09:17.070 --> 09:18.370
That's really nice.

09:18.370 --> 09:21.830
And honestly, Stack Overflow is a great resource we've seen used earlier today.

09:21.830 --> 09:27.050
It's had some misleading information that led people down side paths and rabbit holes for a bit.

09:27.090 --> 09:30.790
But for weird knowledge like this, it's kind of invaluable.

09:30.810 --> 09:32.090
Yeah, yeah, definitely.

09:32.090 --> 09:43.730
And while it is definitely within the realm of CTF tricks to point people to resources that aren't quite correct, we're not going to be playing those games here.

09:43.730 --> 09:45.250
No , definitely not.

09:45.550 --> 09:50.370
Everything you need for the challenge is laid out in front of you, and if you just experiment with it, you can get it.

09:50.510 --> 09:54.810
Yeah, and we want the competitors to be able to solve this speed challenge.

09:54.810 --> 09:58.390
We know that this is challenging, and we are getting down to the finals here, right?

09:58.390 --> 10:06.230
So we know that these players are the very best, and we want it to be challenging, but we also want it to be solvable.

10:06.230 --> 10:12.010
And I think that the hints for this challenge, we did address that and try to give some good hints.

10:12.010 --> 10:16.050
Yeah, the hints are definitely explaining a lot of the theory behind it.

10:16.210 --> 10:20.250
And if they're off in wrong directions, push them back to the right one.

10:20.330 --> 10:26.090
Right, which if I recall, I think the first hint sort of lays out the constraint that you have to deal with.

10:26.090 --> 10:29.390
The first hint does the chat GPT, can you please explain this code to me?

10:29.730 --> 10:31.990
But a little nicer because it's from the author.

10:32.010 --> 10:40.830
And we saw over on MMM actually, experimenting with different size mobs, or mob of different size registers, and kind of looking at the first byte result of those.

10:41.230 --> 10:47.810
So I'm curious if he's figured this out, and he's just writing the constraints now, what he needs to end up with.

10:48.170 --> 10:48.930
Very interesting.

10:48.930 --> 10:52.970
Yeah, and I think that that experimentation is exactly what I would expect.

10:53.090 --> 10:59.110
You can see he's sort of laying out what he needs and what the constraints are.

11:00.370 --> 11:11.990
So the real kicker with that constraint, and I think that Glenn designed it this way, is that you can't get 64-bit instructions for a lot of the ones that you're going to want.

11:12.410 --> 11:12.810
Yeah .

11:13.830 --> 11:23.150
And so moving the shellcode around, or your shellcode has to be able to read or write memory typically.

11:23.190 --> 11:27.950
It's harder when you don't have the full-width registers, which you would be expecting to use.

11:27.950 --> 11:28.910
You have to find some alternatives.

11:28.970 --> 11:29.830
Absolutely, yeah.

11:29.830 --> 11:48.810
And move of the lower half register, so EAX, EBX, et cetera, operations on low-byte registers, POPs of the low four-byte registers, clears out top four bytes, which is going to be really nice when you end up needing, like, OX3, BNREX.

11:49.070 --> 11:51.810
Oh, and now we see it on the MMSI.

11:51.810 --> 11:55.390
They're looking for that opcode table, and that's exactly the table that I was referencing.

11:55.390 --> 11:56.070
Awesome.

11:56.070 --> 11:56.510
Oh, my.

11:56.670 --> 11:58.570
This table terrifies me, honestly.

11:58.570 --> 12:01.790
They are reading it very fast.

12:01.790 --> 12:03.470
I love BOP code.

12:03.590 --> 12:05.090
That was a challenge recently, wasn't it?

12:05.090 --> 12:05.710
Was it?

12:05.710 --> 12:07.490
I thought it was a DEF CON CTF.

12:07.490 --> 12:08.470
Oh, I don't know.

12:08.470 --> 12:09.730
I'm not sure.

12:09.910 --> 12:10.770
Anyhoo.

12:11.770 --> 12:13.290
Okay, but let's see.

12:13.950 --> 12:17.190
So, I honestly have no idea what he's writing in this.

12:17.190 --> 12:22.310
I don't know what that syscall equals OX05 CD88 question mark, like...

12:22.310 --> 12:28.170
I believe that he's laying out what the bytes are for the syscall opcode.

12:29.090 --> 12:29.630
Okay.

12:29.630 --> 12:32.630
I think OX05 is syscall.

12:33.230 --> 12:33.950
Okay.

12:34.570 --> 12:38.290
Well, honestly, oh, man.

12:38.590 --> 12:40.650
I don't look at bytes for disassembly anymore.

12:40.670 --> 12:48.410
We have, like, on trips to CTFs, done just kind of, like, back and forth trivia of, like, who can name more opcodes to bytes.

12:49.530 --> 12:51.350
Or, like, instructions to bytes.

12:51.510 --> 12:55.970
In RPI's sake, we did this, you know, when we were taking the train to and from Seesaw and stuff like that.

12:55.970 --> 13:07.890
Oh, and see, this experimentation is exactly what I think you're going to see on both sides, is how do I do clever little things where I can set the bytes just right or at least get that high bit set?

13:07.890 --> 13:16.090
What can I do to have equivalent operations or at least get the primitives that I need to shape a shellcode without breaking the constraint?

13:16.250 --> 13:16.850
Yeah, absolutely.

13:16.850 --> 13:20.970
And it looks like he's finding some really funky instructions to work with here.

13:20.970 --> 13:26.690
Over on Macaroni, we see experimenting in the same sort a little more targeted.

13:26.690 --> 13:32.870
It looks like they're trying to get generic control of written bytes.

13:32.870 --> 13:41.230
Instead of targeting exactly what they need, they're trying to come up with just a system for writing arbitrary bytes.

13:41.230 --> 13:48.730
I got stuck on this for a long time because I didn't focus on writing, you know, just one instruction at a time, get the state closer and closer and closer.

13:48.730 --> 13:54.390
I tried to make a function to just decode.

13:54.390 --> 13:55.490
That's so weird to say.

13:55.490 --> 13:59.690
Decode my shellcode into the right form and then push it to the server.

13:59.690 --> 14:03.330
So I'm hoping Macaroni does that here.

14:03.330 --> 14:06.810
They have, oh, it looks like just a PwnTemplate thing.

14:07.910 --> 14:17.030
Yeah, well, that's really the two approaches I think is that I would expect to see on this challenge is on one hand, just start experimenting and see what makes it through.

14:17.030 --> 14:27.990
And then the other side is the more static approach, which is let me understand the encoding really well and then I can write a function that will allow me to pass whatever I want through unscathed.

14:27.990 --> 14:45.030
Yeah, but understanding the encoding that deeply, you know, it sounds fairly simple, but looking at the code, your brain gets kind of jumbled because it's just so much bit shifting, oring and spacing that it's easy to lose track of where you are and what byte you're working on.

14:45.030 --> 14:50.490
Yeah, we see here, it looks simple, but if you actually trace through the path, it's funky.

14:50.490 --> 15:00.210
Yeah, it's simple enough, but when you're under this kind of time pressure, you really do feel like, man, how much time do I have to sit and think about this and really understand it?

15:00.210 --> 15:01.390
Yeah, exactly.

15:01.390 --> 15:04.490
And I think, yeah, we see anger coming out.

15:04.530 --> 15:06.910
Oh, now that is an interesting idea.

15:06.910 --> 15:08.570
That's a very interesting idea.

15:08.570 --> 15:10.710
None of us tried that as far as I know.

15:10.810 --> 15:16.370
No, and it's just encoding, so there's nothing that should really stop anger from working.

15:16.370 --> 15:17.630
It should be able to solve right through that.

15:17.630 --> 15:25.270
But the question is, you still have to have some shellcode that's going to run unscathed.

15:25.270 --> 15:29.830
You do, but I'm wondering if this is going to be able to find a way to write arbitrary bytes.

15:30.350 --> 15:37.210
Because if you can just use the shellcraft-sh and it'll write arbitrary bytes for you, who knows?

15:37.210 --> 15:39.590
Well, you won't be able to use the shellcraft-sh, actually.

15:39.590 --> 15:44.730
It'll probably return that there's no path available.

15:46.170 --> 15:46.970
Right, right.

15:46.970 --> 15:57.590
I think if you were trying to push things that aren't going to be possible with the constraint through, anger is just going to come back and say it's unsat, it's not solved.

15:57.590 --> 16:00.850
Yeah , and actually, Z3 would be pretty good for this, too.

16:01.010 --> 16:04.690
Well, we'll see how that works out for them.

16:05.910 --> 16:10.150
Over on the MMM side, we're looking at the encoder.

16:10.150 --> 16:23.830
This is definitely what the reference solution sort of did, which was understand, can I have a limited set of operations that allow me to write out or encode, decode?

16:23.830 --> 16:26.430
I think they're going to be self-modifying shellcode.

16:28.870 --> 16:29.430
Yeah, definitely.

16:29.430 --> 16:30.890
I think that's the approach they're doing.

16:30.890 --> 16:35.110
Because they're looking up PwnTools, Zortools.

16:35.890 --> 16:37.170
Yeah, and that would totally work.

16:37.170 --> 16:43.450
If you can write a short decoder stub that stays within the constraint, then that's a great solution.

16:43.450 --> 16:44.770
That's super smart.

16:44.770 --> 16:45.290
Yeah.

16:46.030 --> 16:52.930
Or even if you get an off-by-one instruction, then you just ink RIP.

16:55.900 --> 16:56.880
Yeah, I want to say...

16:56.880 --> 16:57.960
Ink RIP and not.

16:59.300 --> 17:00.960
Add RIP, too.

17:04.980 --> 17:06.900
Oh, and so now we see that he's...

17:06.900 --> 17:10.100
So this is a key insight that we're looking over on the MMM side.

17:10.100 --> 17:17.320
He's realized that he doesn't have access to RSI, RAX, but he does have access to EDX, ESI within the constraint.

17:17.320 --> 17:18.000
That's right.

17:18.000 --> 17:18.940
Key insight.

17:20.280 --> 17:22.200
So this is great progress.

17:22.240 --> 17:26.020
I'm trying to mix and match, see what the different first byte turns out to be.

17:26.020 --> 17:35.060
Right, and he's using sub as the operation, subtract instead of move, because maybe you want to fix up by using...

17:35.060 --> 17:37.540
or write bytes by subtracting constants.

17:37.800 --> 17:39.980
There's a lot of different ways to do this.

17:40.440 --> 17:41.620
Oh, there are so many different ways.

17:41.620 --> 17:44.460
I mean, as far as I know, x86 is turning complete.

17:47.320 --> 17:49.000
I was really waiting there.

17:49.000 --> 17:51.620
I'm like, oh, God, no, that one fell really flat.

17:53.300 --> 17:54.780
Okay, so we see...

17:54.780 --> 17:57.400
I think in that shellcode there was still a V.

17:57.520 --> 17:59.760
Where would that be?

17:59.760 --> 18:02.360
No, that has upper bit set.

18:03.480 --> 18:07.760
I remember looking at the load string instructions.

18:07.760 --> 18:09.500
That was definitely something that I explored.

18:10.200 --> 18:12.440
No, V is 0x70 something.

18:15.340 --> 18:18.700
It's before 0x7F, so it doesn't have upper bit set.

18:18.700 --> 18:19.600
That's right.

18:21.320 --> 18:23.280
That good old 7-bit ASCII.

18:26.270 --> 18:29.430
Good old ASCII should never belong in the same sentence, honestly.

18:30.310 --> 18:32.250
Let's switch to UTF-16 for everything.

18:32.250 --> 18:33.750
That's a way better encoding, right?

18:35.610 --> 18:40.010
I prefer that every byte needs two bytes, and the second byte is a null.

18:44.950 --> 18:50.690
Having written a Unicode decoder, this entire thing is bringing back some PTSD.

18:52.770 --> 18:57.370
I think encoding has to be one of the least favorite topics of most hackers.

18:57.370 --> 18:59.510
I don't know anybody that really loves encoding.

18:59.530 --> 19:04.690
Take this concept, transform it into an entirely new space, and then operate on that.

19:04.690 --> 19:05.550
It's easy, right?

19:05.550 --> 19:08.450
Every programmer wants to needlessly complicate things.

19:08.790 --> 19:10.970
Everyone has the best new encoding.

19:11.090 --> 19:11.850
That's true.

19:11.850 --> 19:14.590
There should be a standard.

19:15.130 --> 19:16.190
Who can make a standard?

19:16.190 --> 19:18.390
You need some sort of consortium for that.

19:19.270 --> 19:21.430
This is how we end up with new standards.

19:24.210 --> 19:26.990
So how is Macaroni doing?

19:27.330 --> 19:32.210
Macaroni, looking through, making sure they have a solid understanding of the code here.

19:32.250 --> 19:36.170
In IDA dark theme, this makes it really easy for us to keep track of, because we have light theme versus dark theme.

19:36.170 --> 19:37.270
I do appreciate that.

19:37.270 --> 19:39.030
Light side versus dark side.

19:39.110 --> 19:41.310
I'm not taking sides by saying that.

19:41.870 --> 19:46.310
But looking through, leaning back in the chair, understanding, okay.

19:46.630 --> 19:49.650
So it's seven bits per byte.

19:50.170 --> 19:52.270
But you encode it.

19:52.450 --> 19:58.770
So you need to pass a normal byte, and it only takes seven bits from that, and sets the top bit.

19:58.930 --> 19:59.850
That's right.

20:00.110 --> 20:00.930
That's right.

20:00.930 --> 20:02.070
And this is...

20:02.650 --> 20:06.470
The encoding itself is actually for arbitrarily sized numbers.

20:06.470 --> 20:07.070
And so even...

20:08.110 --> 20:13.310
Just the idea of like, this isn't a, oh yeah, you just provide your bytes, and it encodes, decodes.

20:13.310 --> 20:17.230
Base 64, for example, right?

20:17.230 --> 20:17.990
This is...

20:17.990 --> 20:19.330
No, it's for integers.

20:19.330 --> 20:24.050
It's for integers, which definitely was a little confusing for me when I was reading through it.

20:24.050 --> 20:24.370
Oh , yeah.

20:24.370 --> 20:27.750
No, that library does not work nicely for it.

20:27.890 --> 20:30.370
Does not work nicely for arbitrary bytes, rather.

20:30.370 --> 20:36.130
And the decode method just returns an int, so you should see like, where is it?

20:36.150 --> 20:39.570
Like bytes to hex in these people's solve scripts.

20:39.570 --> 20:42.550
And we saw a macaroni a second ago, checking for the hint.

20:42.550 --> 20:46.070
First hint was coming out in 20 seconds, so it should be out now.

20:46.070 --> 20:48.210
We don't see either team looking at it.

20:49.450 --> 20:52.750
Which is interesting, but we see mhacaroni.

20:53.230 --> 20:54.170
Yeah.

20:55.290 --> 20:55.810
Encoding...

20:56.690 --> 20:57.210
7...

20:57.210 --> 20:59.710
Oh, 7 bits from binary output.

20:59.810 --> 21:07.470
Yeah, I think that they're trying to graphically print out what their bytes have.

21:07.470 --> 21:10.450
I think this is exploring the constraint.

21:10.450 --> 21:11.430
Oh, it absolutely is.

21:11.430 --> 21:14.950
I'm wondering if this is going to work, because this looks very similar to my script.

21:14.950 --> 21:16.450
Or it's starting to, at least.

21:17.090 --> 21:18.430
But I don't think...

21:19.530 --> 21:22.350
Yeah, shabcd, so those are all the 0x40 range.

21:22.350 --> 21:26.250
Those are going to get transformed, and you might be confused by that.

21:26.670 --> 21:27.830
But we'll check back.

21:27.830 --> 21:29.710
Yeah, there's that long to bytes we saw.

21:32.150 --> 21:37.310
Actually, let's see what the script does here before we switch back over to MMM.

21:37.670 --> 21:39.070
To send not defined.

21:39.470 --> 21:40.510
Yeah, that would help.

21:42.110 --> 21:47.190
Do you think that we're going to see the classic, all right, I'm going to look at what I'm sending into the decoder.

21:47.730 --> 21:53.710
uleb128 breaks up the input, like base64, into 7-bit blocks, did it say?

21:53.710 --> 21:54.070
Yep.

21:54.070 --> 21:58.030
So kind of explaining the function to them in English.

21:59.030 --> 21:59.590
Right.

21:59.590 --> 22:02.750
I think that MMM has an understanding of that.

22:02.750 --> 22:03.790
We'll see if that changes.

22:03.790 --> 22:10.830
And actually, Macaroni just saw that their 0x41, 0x42, 0x43, 0x44 got transformed to C1, C2, C3, C4.

22:10.830 --> 22:11.290
Bingo.

22:11.290 --> 22:14.350
So I think they're starting to really understand it.

22:14.350 --> 22:15.270
Yep, here we go.

22:15.890 --> 22:18.750
And now they're looking for a similar table.

22:18.750 --> 22:21.110
Oh, wait, they're one click off.

22:22.010 --> 22:24.710
Oh, no, look, over on the right, it has first bytes.

22:24.710 --> 22:25.790
Oh, that's helpful.

22:25.790 --> 22:26.570
That's so nice.

22:26.570 --> 22:27.390
It's not an order, though.

22:27.390 --> 22:28.890
It's an alphabetical order.

22:28.890 --> 22:37.730
Well, it allows you to reference, if you know what instruction you want, you can check what the opcode ends up being.

22:37.730 --> 22:46.010
And here we see Macaroni going to be doing very similar things over to what MMM was just doing in their Python terminal here.

22:46.010 --> 22:49.790
And it looks like they're doing the same 7-bit encoding, not using any nice Python helper, though.

22:49.790 --> 22:52.570
So they're going to have to write the helper themselves, which is prone to errors.

22:53.050 --> 22:53.770
Definitely.

22:53.770 --> 22:59.990
If you can download a library and have it do the work for you, you should, right?

22:59.990 --> 23:03.930
It's not about writing stuff you don't have to.

23:03.970 --> 23:04.730
Absolutely.

23:04.730 --> 23:07.470
It's about minimum work, maximum flags.

23:07.870 --> 23:09.350
That is the goal.

23:09.350 --> 23:12.090
And that's what players are really used to doing here.

23:12.090 --> 23:15.210
And it looks like he's just going to be rewriting his helper.

23:15.250 --> 23:18.010
So rewriting his unpacker?

23:18.730 --> 23:19.870
It's so weird to say.

23:19.870 --> 23:23.270
Yeah, okay, this is literally what my script looks like.

23:24.790 --> 23:27.470
Except I had, like, a mod in the...

23:27.470 --> 23:30.450
Yeah, wait, is he going to do times len mod 2?

23:30.510 --> 23:34.490
Because if he does times len mod 2, that is my script.

23:34.690 --> 23:35.430
Oh, wow.

23:37.390 --> 23:40.270
Okay, so going to be reading through the code again over on MMM.

23:40.730 --> 23:46.610
mHackaroni, they just switched, but mHackaroni was just going through PwnTools asm various opcodes.

23:47.390 --> 23:49.590
Main has unknown type casted to declare type.

23:49.590 --> 23:50.450
Is this true?

23:50.710 --> 23:53.750
No, no, you can do this as main here.

23:55.330 --> 23:55.970
Weird.

23:56.770 --> 23:58.390
I don't know why it failed to disassemble them.

23:58.390 --> 23:58.770
Yeah.

23:59.890 --> 24:03.130
So they're going to be breaking on the call and trying to understand what's going on there.

24:03.290 --> 24:09.270
Yeah, because if you look at the disassembly of main, you see that it basically ends in a call to a register, and so everything's set up.

24:09.270 --> 24:13.430
It's just putting the shellcode into a buffer and jumping to that buffer.

24:13.430 --> 24:15.050
Yeah, there are no complicated states to get there.

24:15.050 --> 24:16.250
You're going to have the same register state.

24:16.250 --> 24:17.150
There's no randomness.

24:17.150 --> 24:21.270
Well, there's randomness in ASLR and stuff, but you have fixed register entry state.

24:21.270 --> 24:30.810
And now we see Macaroni really doing exactly the same thing we saw MMM do, which is let me see what the bytes are for a bunch of instructions that I'm going to want to use.

24:30.810 --> 24:31.330
Absolutely.

24:31.330 --> 24:33.050
And they're going to be going through that for a bit.

24:33.050 --> 24:37.230
Over on MMM, you see he finished writing the repacker.

24:37.610 --> 24:39.890
Ah, re-unpacker.

24:39.890 --> 24:40.770
The un-repacker?

24:42.590 --> 24:45.970
And he's going to be going through, finding the right instructions to put there.

24:45.970 --> 24:49.610
His shellcode is not assembled instructions.

24:50.110 --> 24:50.930
It's just bytes.

24:50.930 --> 25:02.010
He's just writing the raw bytes, which honestly makes sense, because that way you don't have to go back from assemble shellcode to integer back and forth and try and keep a mental model of it.

25:02.010 --> 25:03.970
It's just laid out clearly for you.

25:04.570 --> 25:09.310
Yeah, that was something as I was working on this, I definitely had...

25:09.310 --> 25:11.150
I wanted to see the mnemonic.

25:11.150 --> 25:12.670
I wanted to see the opcodes.

25:13.150 --> 25:13.930
It was...

25:14.490 --> 25:18.170
There's not really a good tool for that that I can think of.

25:18.650 --> 25:19.230
I don't know.

25:19.230 --> 25:22.930
I'm sure there's one out there, but I haven't used one as far as I know.

25:22.930 --> 25:28.850
I mean, I did some work in Binja, just assembling stuff in and then doing show opcode bytes.

25:28.850 --> 25:29.030
Yeah.

25:29.030 --> 25:32.270
And then that was my play for a little bit.

25:32.270 --> 25:35.330
But this is not an easy thing to do.

25:35.330 --> 25:47.450
Yeah, I was working with Disasm.pro in the browser, just because I'm a browser tool kind of guy, and just typing stuff in, seeing what top byte is, moving stuff around, similar to what we saw these players doing earlier.

25:48.970 --> 25:51.830
And it looks like...

25:51.830 --> 25:54.870
Okay, MMM just getting calls right.

25:55.010 --> 25:57.870
Yeah, passing bytes of int.

25:57.870 --> 26:02.110
I mean, the speed at which that they're putting these things together is really impressive.

26:02.150 --> 26:17.430
And I mean, there definitely is an argument here, because the encoding is not really complicated, that maybe writing your own keeps you from having to deal with maybe an API issue if you don't like what the module is presenting.

26:17.950 --> 26:25.970
We talked about you have to figure out your big integer, so to speak, and then hex encoding it, and figuring out that stuff.

26:26.150 --> 26:37.010
Yeah, and it's very much like the ease of use of using that package, that API, versus understanding the internals and making sure that you have access to intermediate states.

26:37.370 --> 26:42.810
And kind of the overhead of learning a new thing versus writing your own thing is really something you have to weigh out.

26:42.810 --> 26:51.710
And going back and changing your approach to do the other from either is going to be a decent-sized lift, and you're going to be making mistakes on assumptions that don't exist anymore.

26:51.710 --> 26:57.130
Exactly, and that's what I was going to bring up, is that when you're using a library, you're limited to the assumptions that they made.

26:57.130 --> 27:07.690
Whereas if you're just looking at the assembly and you see exactly what this is doing, does it really matter if it's truly encoding the way it's supposed to be?

27:07.870 --> 27:09.550
Because the assembly is the truth.

27:09.550 --> 27:14.470
Yeah, I mean, that's really all that matters in the end, is what your state is when you get to that call racks.

27:14.470 --> 27:15.030
Exactly.

27:16.450 --> 27:19.290
And actually, call racks, you're going to have the...

27:19.290 --> 27:25.850
you could do self-modifying there, because you have racks equal to what your current rip is.

27:26.030 --> 27:28.170
Right, you do have a register that points...

27:28.170 --> 27:31.090
you have a register that points right to the beginning of your shellcode.

27:31.690 --> 27:33.970
If I recall, the register state's not that bad.

27:33.970 --> 27:36.690
We see MMM going into their debugger.

27:36.690 --> 27:45.390
I actually really love to see the debugger integrated with your disassembly, decompiler, RE framework, in this case IDA.

27:45.390 --> 27:50.650
I think that's a really powerful move, because I hate switching between windows.

27:50.650 --> 27:57.330
And if you've got a script, a debugger, a decompiler, you're flipping between these three things.

27:57.330 --> 27:59.590
It's just easier when you've got everything in one view.

27:59.990 --> 28:09.110
Yeah, and over on Macaroni, we see them printing out every instruction that matches the constraint that they were given.

28:09.610 --> 28:11.290
And lots of new lines.

28:12.070 --> 28:14.370
Yep, looks like there's an extra new line in there.

28:14.370 --> 28:16.230
Yeah , check if the string is empty, continue.

28:16.670 --> 28:18.410
Grep one line, or I'll filter that out for you.

28:18.410 --> 28:19.670
Oh, yeah, just grep.

28:20.750 --> 28:24.310
Oh, yeah, because they're printing one line in between instead of one line after every valid one.

28:24.850 --> 28:25.670
Oh, man.

28:26.090 --> 28:28.310
Yeah, I mean, this is CTF code, through and through.

28:28.310 --> 28:30.070
This is what we would expect to see.

28:30.070 --> 28:31.590
And honestly, this is...

28:31.590 --> 28:41.110
if you've got something that prints things out exactly the way you see, that can be a lot more useful than a Wikipedia page, which somebody else put together, probably for people doing sane things instead of CTF.

28:41.750 --> 28:42.890
CTF is sane?

28:42.890 --> 28:43.490
What are you talking about?

28:43.490 --> 28:48.810
It's just writing shellcode and 7-bit unpacking for an integer encoding.

28:49.410 --> 28:50.290
Exactly.

28:50.290 --> 28:51.630
Oh, I get your point.

28:53.110 --> 29:05.590
You know, I started off in CTF, reversing, all of that stuff, and I didn't realize how weird it was until I started dealing with real software people.

29:05.590 --> 29:06.350
Oh, yeah.

29:06.350 --> 29:12.430
No, I was talking with, once again, the iOS, macOS cat who's helping us behind the scenes.

29:13.450 --> 29:17.470
And we were staring at this problem, and she was just like, wait, no, this doesn't make any sense.

29:17.470 --> 29:18.410
This is so stupid.

29:18.410 --> 29:21.150
And we were staring at this thing for like 30, 40 minutes.

29:22.050 --> 29:24.010
And she'd never played a CTF before.

29:24.190 --> 29:27.410
And I turned to her and I'm like, congrats, this is what playing a CTF feels like.

29:27.410 --> 29:28.950
And she's like, oh, no.

29:29.190 --> 29:30.230
This doesn't make sense.

29:30.230 --> 29:31.110
This is so stupid.

29:31.110 --> 29:32.370
Yep, that sounds like CTF.

29:32.390 --> 29:33.030
Exactly.

29:33.070 --> 29:36.570
You either solve it or you look at the solution and you're like, wow, yeah.

29:36.650 --> 29:51.250
Yeah, not to date myself too much here, but when Python 3 came out and they made it a little bit more difficult to deal with bytes because you had to worry about strings versus bytes, I argued vehemently about why Python 2 had gotten it right.

29:51.250 --> 29:55.310
And all of the hackers that I knew were like, yeah, no, it's a lot easier to deal with.

29:55.310 --> 29:58.030
But everybody else in the world was like, you're crazy.

29:58.330 --> 29:59.850
Have you heard of internationalization?

29:59.850 --> 30:01.330
No, absolutely the same thing.

30:01.330 --> 30:02.870
I argued completely against it.

30:03.730 --> 30:06.910
RPISec's internal tools, I believe, still use Python 2.

30:06.990 --> 30:07.630
Oh, my gosh.

30:07.630 --> 30:08.210
Some of them.

30:09.470 --> 30:10.710
Hey, look, OK.

30:10.710 --> 30:11.950
At this point, that's cruel.

30:12.570 --> 30:15.910
RPISec, you know, we haven't really been playing CTFs much in the past couple of years.

30:17.670 --> 30:19.310
But, yeah, I argued completely against it.

30:19.310 --> 30:22.290
And now I'm, like, strong Python 3.

30:22.930 --> 30:23.830
Me too.

30:23.830 --> 30:24.370
Yeah.

30:24.370 --> 30:25.010
Me too.

30:25.010 --> 30:29.310
Now when I see tools that are still written for Python 2, it's like, hey, man.

30:29.330 --> 30:30.490
Yeah, it's kind of like, come on.

30:30.490 --> 30:31.750
I had to switch my code over.

30:32.370 --> 30:34.050
Python 2 was EOL.

30:34.110 --> 30:35.390
It's been EOL for a while.

30:35.390 --> 30:35.850
It's true .

30:37.190 --> 30:47.730
So getting back to it, we're looking at Macaroni, still looking through the tables, finding the opcodes that they can use, giving the constraints.

30:48.310 --> 30:50.170
Oh, going into XMM registers.

30:50.170 --> 30:51.110
Wait a minute.

30:51.510 --> 30:52.410
Oh, clever.

30:52.410 --> 30:54.070
You know, I wondered about that.

30:54.250 --> 30:54.730
Oh.

30:54.730 --> 30:56.190
I didn't explore that myself.

30:56.190 --> 30:56.690
Gosh.

30:56.690 --> 31:00.870
But I thought maybe, you know, you could use these extended registers.

31:00.870 --> 31:04.270
To move things around, you know?

31:04.270 --> 31:06.710
I'm wondering if they're going to go into, like, AVX 512.

31:06.710 --> 31:08.310
And I'm like, does my CPU support it?

31:08.310 --> 31:09.210
Yeah, okay, good.

31:09.210 --> 31:09.890
We're good.

31:09.890 --> 31:10.550
Oh, man.

31:10.550 --> 31:15.670
How much of a heartbreaker would that be if you write this beautiful shellcode and then it just doesn't support those extensions?

31:15.670 --> 31:16.350
Yeah.

31:16.590 --> 31:17.270
No.

31:18.010 --> 31:20.530
New CPU, supports just about everything.

31:21.550 --> 31:23.130
Really hope they're not going to do the...

31:24.010 --> 31:24.810
What's the new one?

31:24.930 --> 31:26.250
Zenbleed downfall?

31:26.550 --> 31:27.210
Oh.

31:27.250 --> 31:29.510
Which one was the AMD one again?

31:29.510 --> 31:31.510
Well, I know Zenbleed was, but...

31:33.590 --> 31:34.970
What are they looking at here?

31:34.970 --> 31:35.930
Is this Python codecs?

31:35.930 --> 31:36.790
Yeah, it's Python codecs.

31:36.790 --> 31:37.410
All right.

31:38.430 --> 31:44.970
So, switching back over to the MMM side, you can see they've got their interactive debugger within IDA.

31:44.970 --> 31:46.330
They're flipping back and forth.

31:46.330 --> 31:51.450
I really feel like this is the right view, or at least a view that is very helpful.

31:51.930 --> 31:53.810
Because it allows you to see, hey, this is the memory.

31:53.810 --> 31:56.470
He's got that hex view with the bytes of memory.

31:56.570 --> 32:02.790
You can see the disassembly, swap back and forth, the decompilation, and the registers all in one window.

32:02.790 --> 32:04.350
I think that helps you move faster.

32:04.490 --> 32:05.710
Yeah, absolutely.

32:05.710 --> 32:09.370
It gives you kind of the full context in one view, which is really nice.

32:09.370 --> 32:11.010
At the end of the day, we're only people.

32:11.010 --> 32:13.270
We only have like max one set of eyes.

32:13.670 --> 32:18.770
So, keeping track of all these different things, we're going to have that context switch overhead.

32:20.170 --> 32:25.910
Right, and as I said, you like to have it as much as you can in one view, but now he's got...

32:27.250 --> 32:30.290
He's got his IDE that has a script and two terminal windows open.

32:30.290 --> 32:32.450
He's got flipping back and forth to the...

32:32.450 --> 32:32.870
The big table.

32:32.870 --> 32:34.870
The browser, yeah, with the table.

32:35.170 --> 32:36.030
This is a lot.

32:36.030 --> 32:38.490
You've got to cross-reference a lot of information here.

32:38.490 --> 32:39.530
Oh, absolutely.

32:39.530 --> 32:41.150
Be able to organize it in your head.

32:41.150 --> 32:53.130
I really like in CTFs having like a dual monitor setup, a little external monitor, because you can have your reference up there, you can have a chat up there if you're talking back and forth to someone, or just like a notepad to keep track of.

32:53.130 --> 32:56.790
But live CTF, you do need a mirror screen, so it is...

32:57.630 --> 32:59.870
So it is harder.

32:59.870 --> 33:01.810
And we see...

33:01.810 --> 33:08.110
I don't want to leak Mhacaroni's file system there, but they were searching their file system and funny files came up.

33:08.110 --> 33:11.430
It was like, challenges to hack and code better.

33:13.510 --> 33:18.170
Well, you know, I've got some friends that are really interested in starting a school, you know, for...

33:18.170 --> 33:20.670
School of hacking for kids that want to learn to...

33:20.670 --> 33:23.430
Kids that want to learn to hack and be good.

33:23.430 --> 33:24.330
Hack good.

33:24.330 --> 33:25.390
Hack good.

33:25.450 --> 33:26.410
Yeah.

33:27.270 --> 33:32.330
Okay, well, I'm going to switch over to Mhacaroni, because they're looking for...

33:34.270 --> 33:37.170
Maple CTF CPO 37 write-up.

33:37.170 --> 33:42.050
Oh, I think that they're looking for a reference solution to another challenge that might mirror this one.

33:42.050 --> 33:44.070
Car set constraint shellcode.

33:44.110 --> 33:44.910
Another challenge.

33:44.910 --> 33:49.290
And I think they're hoping that they can just plug the constraints in.

33:49.790 --> 33:51.130
CPO 37 not found.

33:51.130 --> 33:51.890
Oh, yeah, look.

33:51.890 --> 33:55.230
They're like, I solved this challenge before, right?

33:55.330 --> 33:56.590
Like I solved one very similar.

33:56.590 --> 34:02.210
So they're trying to find their own solution on GitHub because they couldn't find it on a file system.

34:02.570 --> 34:07.930
That's pretty good when you have that kind of flashback and you're like, wait a minute, I've been here.

34:08.350 --> 34:15.970
And I think that that's really a thing in the CTF community is that if you have played a lot of CTF, you kind of have that knowledge bank.

34:15.990 --> 34:24.210
You've got an understanding of what are the kinds of problems that people ask you, and you can pull different pieces, even if it wasn't exactly the same challenge.

34:24.210 --> 34:29.190
Maybe you can pull like a real slick encoder or a bit of shellcode to do a very specific thing.

34:29.190 --> 34:31.270
Oh, yeah, or a Z3 script would be gold.

34:31.270 --> 34:32.090
Exactly.

34:32.230 --> 34:32.670
Yeah .

34:33.730 --> 34:34.850
But going through...

34:35.590 --> 34:37.910
Yeah, no, I mean, I know personally my CTF folder.

34:37.910 --> 34:40.390
I have some of my CTF solutions uploaded to GitHub.

34:40.390 --> 34:42.990
The other ones are too gross for me to upload.

34:42.990 --> 34:45.650
And I think that folder is like five gigs now.

34:45.650 --> 34:46.710
It's giant.

34:48.550 --> 34:51.450
Oh, no.

34:51.490 --> 34:58.650
I thought I saw, you know, a controlled exit there, like setting racks properly.

34:58.770 --> 35:00.870
But it looks like it was just...

35:01.290 --> 35:02.970
Yeah, exit zero.

35:03.770 --> 35:08.910
Oh, but it looks like they might have code then if they like got a proper ret.

35:10.530 --> 35:12.070
Yeah, looking at what they're doing...

35:12.070 --> 35:12.830
Oh , no, I'm sorry.

35:12.830 --> 35:14.030
This is their own code.

35:14.030 --> 35:14.370
Right.

35:14.370 --> 35:20.410
I was thinking they might be compiling something and then ripping out the bytes for it.

35:21.030 --> 35:26.670
Oh, they could, but they still need to either jump to a read or...

35:26.670 --> 35:27.730
Well, yeah, wait.

35:27.730 --> 35:36.490
No, because they'd need a move racks RDI and then they'd need to unset other args and then they'd need a read.

35:37.470 --> 35:38.650
I think once you've got...

35:38.650 --> 35:42.330
If it's only register manipulation, that's not so bad.

35:42.330 --> 35:56.950
But I think that the tricky part here was trying to get the code that you need, sort of your final shellcode that you're going to execute, getting that written to memory cleanly was really the difficulty.

35:56.950 --> 36:02.010
And it looks like here, over on Macaroni, they're working with CL now.

36:02.010 --> 36:06.130
So that's the lower byte in any register.

36:06.810 --> 36:12.830
And I think they found out that that meets the constraint that they can change that low byte, which is going to be BIN.

36:12.990 --> 36:14.050
Yeah, and that's what I...

36:14.050 --> 36:17.130
We see them writing BINSH now, which is going to be living in their input.

36:17.470 --> 36:20.250
So they know they have RIP in racks.

36:20.470 --> 36:21.550
Well, they have RIP and RIP also.

36:21.550 --> 36:22.690
They have access to every register.

36:22.870 --> 36:25.990
So they know relative offset of their BINSH string.

36:26.110 --> 36:28.450
You can control lower byte writes.

36:28.630 --> 36:32.550
And I believe also second byte writes.

36:33.270 --> 36:34.570
Not 100% on that one.

36:34.570 --> 36:37.730
I think you can get a 16-bit register right.

36:37.950 --> 36:40.670
You can get 16-bit register right, or do you have to do AL and AH?

36:42.590 --> 36:44.550
Look, I'm not the Intel manual.

36:44.550 --> 36:45.370
I don't know.

36:45.450 --> 36:46.570
Believe it or not.

36:47.390 --> 36:49.390
Yeah, I definitely had a similar approach.

36:49.390 --> 36:55.350
I was using the sort of one-byte register with instructions.

36:55.730 --> 37:00.210
And so there's really, at this point, I think two different ways you could be going.

37:00.210 --> 37:02.070
You could be looking at the encoder style.

37:02.070 --> 37:06.830
Hey, just write an encoder stub, and then decode my shellcode and jump to it.

37:06.830 --> 37:22.110
Or you could do sort of a byte or a chunk at a time where you have essentially a mini-decoder stub, where it's more like a writer stub that writes the byte that you want to a targeted area in memory and then jump to that.

37:22.210 --> 37:22.890
Yeah, absolutely.

37:22.890 --> 37:25.470
Because where you are, it's RWX, I believe.

37:25.510 --> 37:26.190
Oh, here we go.

37:26.190 --> 37:27.230
And you're not limited.

37:27.230 --> 37:30.890
Use 16 and 8-bit RWOFs to get a real write primitive and write a second-stage payload with real shellcode.

37:30.890 --> 37:31.950
Exactly what you were saying.

37:31.950 --> 37:33.010
Exactly, right.

37:33.070 --> 37:36.990
And that works in this case because you're not really limited on size.

37:36.990 --> 37:42.310
You're just really limited by this constraint that's really tricky to get around.

37:42.390 --> 37:47.490
And with this hint now, we see...

37:47.490 --> 37:49.730
Oh, we still can't operate on RAC.

37:49.730 --> 37:51.010
Oh, no, RACCL.

37:51.010 --> 37:51.450
Yeah.

37:51.450 --> 37:52.010
Exactly.

37:52.010 --> 37:56.270
So this is where that's exactly the instruction that they need.

37:56.270 --> 38:04.210
But the hint there, the 16-bit or 8-bit read-write ops, you can't use RAX there because it's going to violate that constraint.

38:04.210 --> 38:09.450
But you can use things like EAX.

38:09.490 --> 38:16.710
The 4-bit width, 4-byte width operations for writing to memory should work.

38:16.730 --> 38:20.290
Can you use EAX or do you have to use AX?

38:20.710 --> 38:28.470
I believe you can use something like MOV, dereference, EDX.

38:28.470 --> 38:29.510
Oh, okay.

38:29.510 --> 38:31.610
So the deref might...

38:31.610 --> 38:32.230
You're right.

38:32.230 --> 38:36.370
I'm going to trust you on this because, once again, I'm not a disassembler.

38:39.530 --> 38:39.970
But...

38:39.970 --> 38:41.110
We still love you anyways, Josh.

38:41.110 --> 38:43.090
Oh, thank you so much, guys.

38:43.150 --> 38:47.030
Even though I don't have 8,000 pages and so many mistakes.

38:47.030 --> 38:49.090
Some of my best friends are manuals.

38:50.030 --> 38:51.410
I have a friend named manual.

38:54.690 --> 38:56.230
MOV, byte point, okay.

38:56.230 --> 38:57.830
So therefore my string is broken.

38:58.950 --> 39:01.690
So they need to add brackets around the J.

39:01.690 --> 39:04.350
So we'll see them figure that out eventually.

39:04.350 --> 39:05.750
There's a lot of experimentation.

39:05.750 --> 39:08.230
It's so much easier being a commentator, honestly.

39:08.690 --> 39:11.270
I mean, I definitely banged my head on this challenge for a bit.

39:11.270 --> 39:12.910
Oh my gosh, same.

39:12.990 --> 39:16.710
So the hints are released at 20 minutes in and 35 minutes in.

39:16.710 --> 39:20.910
So that means we are max, like, 15 minutes away from sudden death.

39:20.910 --> 39:21.590
That's right.

39:21.590 --> 39:24.230
Yeah, we are getting near the end.

39:24.230 --> 39:26.070
We knew that these challenges are hard.

39:26.070 --> 39:31.470
Sudden death was sort of always on our minds as it might come down to that.

39:31.470 --> 39:33.250
I'm hoping that that's not going to be the case.

39:33.630 --> 39:35.890
I have faith in our competitors here.

39:35.890 --> 39:37.870
I think that they're going to figure this one out.

39:38.130 --> 39:38.910
I think they are.

39:38.910 --> 39:44.050
I think they're both making really good progress towards the final goal of setting up that second stage payload.

39:44.050 --> 39:45.110
Well, final goal.

39:45.590 --> 39:49.010
Towards the intermediate goal of making that second stage payload.

39:49.170 --> 39:49.690
Right.

39:49.690 --> 39:54.630
You know, I think that MMM, they kind of got to the idea pretty quick.

39:54.930 --> 40:00.430
They have been spending a bit of time now working through how to get things lined up.

40:00.430 --> 40:03.150
I think that they're on the right track.

40:03.530 --> 40:06.250
Yeah, well, I see a lot of Zord D-word pointers.

40:06.430 --> 40:11.990
You know, RSP plus 0x7B89, like, these random offsets.

40:12.050 --> 40:21.690
So, I think they're getting close, but they might get hung up on some small details of, like, I have a null byte in the middle of my shellcode somewhere that I just missed.

40:21.950 --> 40:28.670
Yeah, it's always something that you can just have the littlest thing mess you up.

40:28.670 --> 40:33.850
You don't catch it, or you've got, like, 99% of the solution, right?

40:33.850 --> 40:35.930
It totally happens in CTF.

40:35.930 --> 40:38.790
Absolutely, in this challenge, those mistakes are cascading.

40:38.790 --> 40:41.330
They will mess up everything after them.

40:41.350 --> 40:44.650
You know, potentially around them, like on either side, too.

40:45.650 --> 40:51.390
So, catching one is going to be hard, and you might just think to yourself, like, I'm messing all this up.

40:51.390 --> 40:58.130
What I really liked doing in this challenge was setting up a known good beginning write that was just garbage.

40:58.130 --> 40:59.590
You know, it was a bunch of nops.

40:59.590 --> 41:01.510
It was just a bunch of A's, whatever.

41:01.510 --> 41:04.410
Just to make sure that my write primitive still works.

41:04.410 --> 41:06.770
Like, I can still write that first stage shellcode.

41:07.790 --> 41:10.430
Yeah, I think that there's a lot of...

41:11.190 --> 41:13.890
This is one of those challenges where you want to have those sanity checks.

41:13.890 --> 41:17.470
I definitely was printing out my disassembly.

41:17.470 --> 41:19.550
I was checking the hex dump every time I ran it.

41:19.550 --> 41:23.370
So, if something did change, I would at least be able to see, oh, the pattern changed there.

41:23.370 --> 41:24.490
Something went wrong.

41:24.490 --> 41:25.550
I've got to go back and fix that.

41:25.550 --> 41:29.670
Yeah, like I'm doing stir of bytes instead of dot decode or dot encode.

41:29.670 --> 41:31.210
God, now this has me backwards.

41:33.610 --> 41:42.550
Again, this is a challenge that on the face of it seems simple, but is actually really kind of a mind bender and a weird constraint that...

41:43.090 --> 41:46.090
It's a simple concept with really hard execution.

41:46.150 --> 41:46.530
Right.

41:46.530 --> 41:56.570
And I think all of Glenn's challenges kind of follow the same principle of, you know, it's this kind of a little away from normal idea.

41:56.570 --> 41:58.470
And you're like, oh, that's close enough.

41:58.470 --> 41:59.310
I can just do this.

41:59.310 --> 42:04.050
And then you get to actually implementing a solution for it, and you're like, oh, my God, I know nothing about computers.

42:04.230 --> 42:05.270
These were a mistake.

42:06.250 --> 42:12.050
Yeah, I think that this is one of those challenges where it's like, I know what I want to do, but I just can't do it.

42:12.050 --> 42:14.410
And that's how I felt when I was working on this.

42:14.410 --> 42:16.870
Yeah, no, absolutely same.

42:16.870 --> 42:25.890
I really had the layout down, but actually writing, like, that first stage payload was not a good time.

42:25.890 --> 42:28.230
And it took me way longer than it probably should have.

42:28.950 --> 42:34.650
So it looks like MMM debugging their writes not working out quite right.

42:35.010 --> 42:43.030
And, okay, so here over on Macaroni, we see them using debug assembly, which is a great feature of Puntles.

42:43.030 --> 42:46.250
And just trying to figure out, they have a move racks.

42:46.270 --> 42:50.810
Oh, they're trying to figure out what's the, they're trying to make a stack frame via enter.

42:50.990 --> 42:52.570
Oh, that's clever.

42:52.570 --> 43:04.610
Yeah, I wonder, I mean, you could SROP here, SIGROP, but I'm not 100% sure if that's what they're going to go for.

43:04.610 --> 43:07.030
That seems a little overkill in my opinion.

43:07.030 --> 43:13.610
Well, you know, I never count the competitors out for coming up with clever solutions that we didn't expect.

43:13.610 --> 43:14.550
Exactly, yeah.

43:14.550 --> 43:16.330
And it could be easier for them.

43:16.410 --> 43:18.830
Like, they might be, like, SIGROP masters or something.

43:18.830 --> 43:19.190
Sure.

43:19.190 --> 43:22.170
And they're just like, I don't know how to write shellcode math.

43:22.490 --> 43:24.770
Yeah, they could be like, no, I invented this technique.

43:24.770 --> 43:26.150
Yeah, really, really.

43:26.350 --> 43:29.850
Well, I mean, we have Jinmo on MMM right now, and we were talking about it.

43:29.850 --> 43:32.650
He had a solution yesterday that was, I think, eight minutes.

43:32.970 --> 43:36.170
And we're looking at each other, and we're just kind of like, did this happen?

43:36.170 --> 43:39.490
And we look at the username on the screen that says Jinmo, and we're like, oh, yeah.

43:39.770 --> 43:41.110
Okay, that explains it.

43:41.270 --> 43:43.570
Yeah, we've got some truly impressive competitors here.

43:43.570 --> 43:44.250
Absolutely.

43:44.430 --> 43:48.970
Anybody who has won against this many other competitors at this level.

43:49.090 --> 43:49.690
Yeah.

43:49.690 --> 43:50.610
Top tier.

43:50.670 --> 43:51.510
Exactly.

43:51.510 --> 43:54.470
No, these are all fantastic hackers.

43:54.470 --> 43:59.530
We need to point that out, that these challenges, they have little to no time to get acquainted with them.

43:59.530 --> 44:05.910
Their mind is still on, you know, the challenge they've been staring at for the past 12 hours in DEF CON CTF.

44:05.910 --> 44:07.430
You know, the non-live version.

44:09.050 --> 44:11.670
And just they have so much going on in their mind.

44:11.670 --> 44:15.030
They have someone sitting directly across from them that they're hacking against.

44:15.350 --> 44:17.310
And even that adds its own stress.

44:17.310 --> 44:18.190
They're on stream.

44:18.190 --> 44:19.670
That adds more stress.

44:20.090 --> 44:22.110
It's a foreign concept, you know.

44:22.190 --> 44:24.070
They don't have tools set up for this.

44:24.070 --> 44:28.270
They don't know that, like, oh, yeah, this is normally like a Pwn CTF, like DEF CON finals usually is.

44:28.890 --> 44:30.670
It's new territory for them.

44:30.670 --> 44:32.270
And I think that can be really daunting.

44:32.270 --> 44:35.150
And the first step in this isn't getting acquainted with the program.

44:35.150 --> 44:42.950
It's kind of getting your bearings and resetting, you know, getting focused on what you need to do and the order you need to do it.

44:43.110 --> 44:49.070
Yeah, DEF CON CTF really could include challenges in any weird area.

44:49.070 --> 44:56.090
I mean, I think we had a competitor ask us, hey, can you specify what architecture this is on?

44:56.090 --> 44:58.350
And so far we've only seen x86.

44:59.270 --> 45:02.110
But with the finals, anything goes.

45:02.110 --> 45:05.370
Well, we had your Python shellcode challenge, too.

45:05.650 --> 45:11.270
That's true, that's true, which, you know, technically you didn't need to care about the native implementation.

45:11.310 --> 45:12.750
We had people walk up to us.

45:12.750 --> 45:15.150
I don't know if you know this, but we had people walk up to us.

45:15.230 --> 45:19.570
And the category we gave them was Python, I think Python shellcode.

45:19.910 --> 45:22.610
And they walk up to us and they're like, hey, can you be more specific?

45:22.610 --> 45:23.430
What exactly does that mean?

45:23.430 --> 45:24.790
And we're like, what do you mean more specific?

45:24.790 --> 45:28.030
And it's like, well, like, is it Python written to shellcode?

45:28.030 --> 45:30.170
Is it like shellcode that has to be valid Python?

45:30.170 --> 45:32.850
And we're like, dude, you have an hour for these challenges.

45:33.450 --> 45:36.550
It's not going to be like Python bytecode that's also valid shellcode.

45:38.070 --> 45:39.570
Oh, was it?

45:39.570 --> 45:41.950
No, it would be interesting to try something like that.

45:41.950 --> 45:44.030
I'm like, did we do that?

45:44.590 --> 45:45.570
No, no.

45:45.570 --> 45:49.410
So in that challenge, you didn't need to go low level.

45:49.410 --> 45:51.810
You could just ask Python to compile the bytecode for you.

45:51.810 --> 45:53.230
Yeah, OK, OK.

45:53.290 --> 45:57.270
No, I didn't think we'd have them, you know, do a polyglot challenge like that.

45:58.470 --> 46:01.370
See, and coming up with stuff is hard.

46:01.490 --> 46:12.210
So having a challenge that involves the topics that you're interested in, that you think will be fun for competitors, but also, you know, reasonable for the time frame.

46:12.290 --> 46:13.690
Yeah, it's not always easy.

46:13.690 --> 46:18.730
Well, we were talking, just organizing this, that I think writing the challenges is easy.

46:18.730 --> 46:20.470
Coming up with the ideas is hard.

46:20.670 --> 46:25.030
And then talking with Glenn and Carl, I think, they said, oh, the ideas are easy.

46:25.030 --> 46:26.010
Writing the challenges are hard.

46:26.010 --> 46:27.270
And I'm like, wait a minute.

46:27.270 --> 46:30.890
It's very much like, you've got chocolate on my peanut butter, you've got peanut butter on my chocolate.

46:31.230 --> 46:34.550
It's the perfect team that works out.

46:34.650 --> 46:37.730
And that's why it's great to have people that think differently on your team.

46:37.730 --> 46:38.190
Oh, yeah.

46:38.190 --> 46:50.590
And if we switch back to the MMM side, it looks like what they're doing is having a handwritten decoder there that's just decoding a D word at a time via XOR.

46:50.590 --> 46:53.430
Oh, they're just, wait, but they're just XORing.

46:53.430 --> 46:57.650
So they're just only using shell code that doesn't have top bit set.

46:57.710 --> 47:02.470
Which is definitely easier because when I tried to solve this, that's what I thought the constraint was at first.

47:02.470 --> 47:04.270
And so I wrote this nice shell code.

47:04.530 --> 47:05.610
No top bit set.

47:05.610 --> 47:06.210
But it's working.

47:06.210 --> 47:07.350
They have a syscall.

47:07.690 --> 47:08.930
They have syscall.

47:08.930 --> 47:10.570
They don't have bin sh.

47:10.690 --> 47:12.770
So they probably just determined...

47:12.770 --> 47:13.730
Error no 14.

47:14.330 --> 47:16.050
I love how they search error no 14.

47:16.050 --> 47:18.330
It says, oh, yeah, HTTP error 404.

47:21.210 --> 47:21.730
Wow.

47:21.730 --> 47:23.730
So that's a really clever idea.

47:23.730 --> 47:29.050
And it looks like there might have been some corruption on their shell code.

47:29.050 --> 47:32.350
But other than that, they're looking like they're on the right track.

47:32.350 --> 47:33.930
I think they don't.

47:33.930 --> 47:36.450
So they've got a big NOP sled.

47:36.610 --> 47:40.750
They've got their payload that they're going to XOR back.

47:40.870 --> 47:42.950
And then...

47:42.950 --> 47:45.050
Which that's totally valid.

47:45.050 --> 47:46.130
Great idea.

47:46.270 --> 47:46.870
Yep.

47:47.070 --> 47:48.190
Got EOF reading and interactive.

47:48.190 --> 47:50.330
So NOP's going to have the top bit set.

47:50.330 --> 47:53.330
So your vanilla x86 NOP.

47:55.670 --> 47:58.510
Oh, yeah, yeah.

47:58.730 --> 48:02.830
So now he's just troubleshooting what went wrong with that, right?

48:03.250 --> 48:04.530
Is the shell code intact?

48:04.530 --> 48:08.990
Was the string reference the address of bin sh?

48:08.990 --> 48:11.750
Pop rdi, push rdx, pop rsi, syscall.

48:11.750 --> 48:13.710
Does he have bin sh on the stack?

48:14.250 --> 48:15.610
I think he forgot about bin sh.

48:15.610 --> 48:17.270
Oh, no, he's using shellcraft down there.

48:17.270 --> 48:20.910
Hidden under his two global area terminals.

48:21.770 --> 48:23.390
Okay, so it's just NOP.

48:23.630 --> 48:31.730
Do you recall if the shellcraft shellcode, if that just uses a move to push the string into a register and then out?

48:31.730 --> 48:33.070
I believe it does.

48:33.630 --> 48:37.390
And I think it also sets all the register states, so he should be good there.

48:37.390 --> 48:45.390
I was going to say that's one of the things that this is a little nonstandard, but every challenge you have to understand what your register states are.

48:45.390 --> 48:48.110
There may be some implicit assumptions in your shellcode.

48:48.110 --> 48:49.350
Yes, absolutely.

48:49.350 --> 48:59.070
But I think it's really nice that the path to your shellcode being executed is so simple that you don't really need to worry about any randomness outside of ASLR.

48:59.070 --> 49:02.530
Stack offset is already in a register.

49:02.730 --> 49:08.130
You have RAP in two different registers, so you have different possibilities for instructions there.

49:09.230 --> 49:11.550
Wow, I think that he's getting very close here.

49:11.550 --> 49:12.970
I think MMM is really close.

49:13.050 --> 49:14.090
Macaroni?

49:14.850 --> 49:15.410
Macaroni?

49:16.010 --> 49:16.610
Macaroni?

49:16.610 --> 49:17.590
Not sure.

49:17.590 --> 49:21.350
Still looking at instruction encodings, trying to figure out which one they can use.

49:21.350 --> 49:31.790
It looks like they're iterating through all the possible registers and figuring out what can encode correctly or what can encode and match the constraints.

49:32.130 --> 49:45.130
Yes, and like we mentioned, all of those R prefixes on those registers indicating the 64-bit width, pretty sure that those aren't going to be able to be used with this constraint.

49:45.130 --> 49:47.070
Oh, and it looks... oh my God.

49:47.290 --> 49:52.170
Wait, they just got immediately... MMM just immediately solved.

49:53.130 --> 49:54.610
Did they solve?

49:54.900 --> 49:56.230
They solved.

49:56.670 --> 49:59.510
40 seconds before sudden death we heard.

50:00.840 --> 50:02.630
Let's double check here.

50:02.970 --> 50:06.230
Yeah, Team 2 made... yeah, MMM won match 19.

50:06.230 --> 50:07.410
Wow, incredible.

50:07.630 --> 50:08.390
Incredible.

50:08.390 --> 50:09.470
Oh my goodness.

50:09.470 --> 50:14.190
Just an outstanding job throwing together this, getting it at the last moment.

50:14.190 --> 50:15.570
This is a tough challenge.

50:15.570 --> 50:21.510
We can see that Macaroni was also having a real hard time.

50:21.510 --> 50:26.010
This is, again, sound simple, hard challenge, excellent work.

50:26.010 --> 50:28.150
Very close for a long time there.

50:28.150 --> 50:40.510
And then MMM really had the idea of setting up their second stage payload using XOR, which top bit unset is going to be a lot easier in 64-bit x86.

50:40.510 --> 50:44.530
Yeah, I think they just did XOR negative 1 because negative 1 is going to have all the bits set.

50:44.530 --> 50:46.830
And then away you go.

50:46.830 --> 50:48.790
And then you just flip-flop everything.

50:49.550 --> 50:52.150
Yeah, they had 40 seconds left until sudden death.

50:52.150 --> 50:52.550
Wow.

50:52.610 --> 50:53.510
That's crazy.

50:53.510 --> 50:54.630
So that could have been really close.

50:54.630 --> 50:56.890
That could have been a big upset in sudden death too.

50:56.910 --> 50:58.530
Well, a great challenge.

50:59.530 --> 51:01.130
Outstanding job to our competitors.

51:01.530 --> 51:02.230
Absolutely.

51:02.230 --> 51:03.390
Difficult, came down to the wire.

51:03.390 --> 51:05.090
I'm glad we got to see that solved.

51:05.090 --> 51:10.710
And so MMM will be going into the finals of the lower bracket.

51:10.850 --> 51:14.890
So they'll have a chance to fight all the way back to the finals and maybe even win it.

51:14.890 --> 51:15.070
We'll see.

51:15.070 --> 51:21.130
Maybe see them in grand finals against one of Hypeboi and Strawhat coming up next.

51:21.130 --> 51:25.950
We're going to go ahead and get those teams swapped over and we'll see you back for the next match very shortly.

51:25.950 --> 51:26.670
Alright.

