start	end	text
12320	18240	Welcome back to the second day of live CTF here at the DEF CON CTF finals.
18700	21400	I'm Zita2 and I'm here with Mark.
21400	25560	Mark Griffin here. Yep, so we're jumping back into it. Same format as we've been doing.
25560	27120	Excited to see this challenge.
27120	32500	Yeah, this is going to be great. I think let's not keep this for long.
32500	39440	Let's get the game started and then we can talk more once they have started looking at the challenge.
39440	42280	So I'm just going to get a final confirmation from production. We have that.
42280	51760	So we're going to start the second round of the second day in 5, 4, 3, 2, 1, go.
51760	54460	All right. Let's jump over and see.
54460	58400	Yep, let me just find this.
58400	64180	So we have the teams participating in this match that we're casting.
64960	68660	Shellfish versus TWN48.
70540	76520	Yeah, this is in the lower bracket of the tournament.
76640	81640	So whoever loses this match is unfortunately eliminated from the tournament.
81860	85100	Yeah, there's definitely a lot on the line.
85100	90600	But with the double elimination bracket, they also have the chance to go all the way back up and win the whole thing.
90600	100300	Right. So maybe they just had a bit of a rusty start yesterday and now they will just go all the way back to the top.
100460	105160	And we can see we've got Shellfish over here already digging into the code.
105160	106660	It's a Python challenge.
107300	110540	And so they've got the whole challenge right in front of them.
110540	113760	They can read the code. They just have to figure out what to do.
114020	116280	And so I think we saw a prompt already.
116420	121720	And this is an interesting problem.
121720	125220	I wanted to do a riff on a standard Python jail.
125220	135200	So Python jail problems are, hey, we're going to establish some sort of constraint that makes it hard to do arbitrary things from within the jail.
135280	140960	Instead, this one is more of a, it looks kind of like a jail, but it's actually a bytecode problem.
140980	149740	Right. So roughly they have to provide some Python code that goes through a filter.
151280	163980	But then after the filter, they are allowed to swap out the bytecode, which is part of the whole code object.
163980	166180	So they can basically modify the code object.
166180	178780	And this way they can then change the code from doing something that passes the check, supposedly something benign, into something malicious that will get them there.
178780	182160	Yeah. And so there's not a ton of code in this.
182160	186600	There's enough that it's, you know, they've got to take a little bit of time and read through it.
186600	197880	There's some stuff that sounds like it's debug related, which does kind of mirror real world problems where developers leave in some extra debug functionality.
197880	201700	They didn't intend it to go into production and can be leveraged.
201700	205020	Yeah. So a little bit of...
205020	209160	So I was attempting to try to solve this challenge.
209160	213700	I also noticed that, well, we don't have the camera on, but our banner is falling down behind us.
213700	214860	But that's fine.
216040	217460	We're overcoming today.
217460	217920	Yeah.
218980	231000	No, but what I was going to say that, yeah, there is like a bunch of stuff in the code, almost like, you know, decoy code or like stuff that's not quite relevant.
231000	238060	Which I think it's, we kind of balanced this a little bit by most of the challenges we have are like compiled machine code.
238640	245680	But very, very minimal, like pretty much all the code in the challenges are relevant to the solution.
245680	247480	In this case, it's Python.
247480	249540	So it's like by default, more readable.
249580	253420	But then there's a little bit more stuff there that you don't actually care about.
253420	257200	Yeah. And it's just trying to toe that line, right?
257200	266280	Get it so it's not going to be solved in like five minutes, but it's not too hard that you can separate the chaff from what actually matters here.
266280	277760	And we've already seen the competitors looking at that, the code module, which allows you to build these Python objects, which is ultimately what we're going to see modified.
277760	285120	Right. And if we switch over to Shellfish here, you can see that they are playing around, having a more dynamic approach.
285120	287680	You know, trying various inputs.
287680	292000	You saw that they were running the program with various inputs.
292000	297560	You see like the answer is they are looking at what different objects are available.
297700	304200	This looks to me a little bit like the approach you would take if you were to the jail challenge.
304200	307260	You're looking at like what various attributes.
307260	321060	In Python, there's a lot of like reflection and like various ways to access, you know, like parent objects and global kind of meta objects and stuff like this.
321220	330760	Exactly. And, you know, with a problem like this, I certainly expected that maybe they could come up with something that I didn't expect and they'd bypass the check and win that way.
330760	344640	I'm not open to anything here. These competitors, not only have they seen and studied Python jail problems from the past, but they may even have stuff in their back pocket that is non-public, you know, bypass type stuff that could come into play here.
344640	355080	Yeah, definitely. I mean, it would not be the first time we saw, you know, zero days and so on at the DEF CON CTF.
355080	372380	So, yeah. Let's switch back over to TWN and you can see them like going around in the code. I feel like they are taking a more static analysis approach to the problem.
372380	386740	And they're also, though, because this is a Python problem, it's very easy to modify. And I think I've seen both players do something along these lines, but certainly TWN48, they're changing the code at least to make it more readable.
386740	398160	But they're also thinking, hey, I can just skip this or add an extra print here, changing the challenge a little bit so that they can understand what they've got to deal with.
398160	412060	And you can see the comment there, cannot call built-in and function. So they're like, you know, kind of like figuring out the implications of the constraints that are given in this problem.
412400	422360	Also, like looking here, cannot use DEF and class. So they're like, you know, just trying to figure out what the playing field is here.
422360	436340	Yeah, and both competitors immediately trying to find the bounds of what they can do. I think that's a great approach. It is kind of interesting to see what the limits are, because the limit is done at that bytecode level.
436660	448920	So they may not be used to seeing that. I know that writing this challenge, it was interesting to see. I was checking a lot of different things that competitors might do and making sure that the filter was sort of going to stop those things.
448920	462420	Right. We saw there that CWM, they were trying to define a lambda function, but they were having some problems with that. So, you know, we'll see how that turns out.
463060	481540	If we can switch over to Shellfish here, I see them highlighting some of these functions. This is really some keyword checking is what's going on here. And you can see that there's some different if conditions here. I see that they've highlighted AI log text, which looks like it's logging.
482100	493900	There's also another function you can see sort of sandwiched in between those that's different AI log code. And that's really the it's a little bit of an innocuous sounding function, but really what they're going to be most interested in.
493900	512600	Right. Yeah. So I think a lot of the, as we kind of mentioned, like a lot of the initial work here will be focused on trying to like separate, you know, what are we actually interested in here? Like which part of this code actually is relevant?
512600	535260	Yeah, and this is this is actually a problem that I've been very fascinated about recently, which is when you're looking at a whole file full of Python, how do you understand how these functions relate to each other? How do you understand the overall whole? I actually feel like the linear view, actually reading the code is a pretty inefficient way to do it. If you could see all of the functions sort of arranged, I feel like it would give you a big advantage in this case.
535260	551620	Right. That's, you know, get some kind of flow view, some flow visualization, like a call graph and, you know, something like this to help you understand the flow that these things are going through.
551620	562460	Yeah, because in this case, there's really one core module here that that is being used for that bytecode manipulation. And so obviously anything related to that module is going to be very interesting to the compiler.
562460	582460	And speaking of that module, we can switch over to TWN again. I saw, let's see if it comes up again, but it looked like they were looking into the documentation around the code module. And, oh, it seems like...
582460	601400	It looks like they're trying to figure out what keywords do I need to put in to get to the different functions there. And so they were looking at AI log code, I think. And they're adding print statements again to make it easier for them to debug. Hey, how do I get to this spot?
601400	623220	And I think, yep, you can see that they're enumerating what each of these words as they relate to a bit field, they're sort of like binary flags packed. And they're seeing that this is a function of interest. And I think we're on the right track here to see them explore this.
623220	634100	So it was cool to see how they went from testing the bounds of the Python jail to enumerating what these keyword functions were.
634320	649940	Yeah. And maybe start trying to figure out how they can circumvent these things or what things they are going to need to care about more here.
649940	657340	So this AI log code function, what is it doing?
657340	682900	Yeah, so really you can see the argument input obj is the same code object that they put in earlier. And so it has to pass a filter check. But then you can see, if you get a good look at the code again, it also allows the user to, so that defend the eggs prompt is saying, hey, take in some more input here and then we're going to do something with it.
682900	703400	And it looks like they're exploring exactly what they can do with it here. But it's going to modify that code object. And so that really the path to exploitation here is to understand that you have to set up an object that has the pieces that you want in order to run your payload. But it still needs to bypass that filter.
703400	722860	That's very nice. And I think we just saw here that they just tried inputting this hex string here. They just took like the string hello and sent it as this additional input. So now we have like a Python crash.
723880	738680	Right, because it's raw bytecode is what is being selected. So it's platform specific, interpreter specific. I expect that they will quickly move from trying to put raw hex into it to getting some sort of bytecode production.
739340	754240	And this is a little bit of a challenge when it comes to solving this, right? Because they need to kind of match the version running on the server, right? For the Python.
754240	759440	That's right. I believe there's a comment in the code that says what it was tested on. And they can verify that.
760900	770740	Yeah, I think it will print out the version. So if they connect to the, if I remember correctly, like if you connect to the server, it will print out the version as well, right?
770740	772960	You can also query using this.
772960	775360	Right, since you can execute code.
775360	775760	Right.
775760	782960	Yeah. That was the way we made it so that they can use the remote servers to get the rights.
782960	796920	And I want to go over back to TWN because I saw that they had a, you know, here they're like printing the, like they have the disassembly of the bytecode.
796920	799920	So you can see there's a load constant and return value.
800340	806140	Right. There's a hidden debug function that allows them. And so, again, this is trying to point them in the right direction.
806140	817300	Hey, we'll show you this object, give you an idea of what's in it, which should help you understand how to solve it, which is, you know, modifying that bytecode as we talked about.
817300	824520	Right. And maybe just, you know, to kind of explain this for people who might not be like too familiar with Python.
824520	851040	So like the Python programming language, you have like a bunch of different implementations of this with the kind of standard one that most people use is CPython, which when it executes Python code, it will take the human readable text code, do all the parsing and so on and compile this into an internal bytecode format.
851040	855240	And then it will execute that within its virtual machine.
855500	855620	Right.
855620	870420	So they are allowed to modify like not the text code that they send in, but like the bytecode that the interpreter has produced after, you know, parsing and so on the code.
870420	894960	That's right. It's almost the lower level language. So you're typing the text, your print hello world that we're seeing, but really what they're going to want to do here is they're going to want to take the code that they want to run at that high level language and then get the bytecode that does the equivalent and then stuff that into the code object that they're able to modify.
896560	903500	Yep. And let's see if we can see what's going on here with TWN48.
903500	933220	They're looking at the filter again. They've got the debug output going on. So they're starting to think about, okay, what is really possible here? I'm not sure that I've seen them look and see if they've found the code modification bit, but that is the first hint that we tell them that it's perhaps not the problem that it first appears to be. It's not a Python GL problem. It's more of a patching problem.
933220	956920	Right. So at this stage, I would say that Shellfish might be just a little bit ahead in the progress. And let's switch over to them and see that they are, in fact, I think you could see it there very briefly, but they were compiling some code there in the script.
957710	973080	So they have this test script. You can see there. So they have these two calls to compile command. And they have two different code inputs. I think this is very much along the right line.
973080	995600	They are trying to, well, if I would guess, they might be trying to produce two different text inputs, which result in maybe the same byte code or different byte code. And they're trying to see how changing the text of the code changes the compiled result of that.
995600	1003240	Exactly. You can see that they've got this fn.replace.co.code. That's exactly the construct that they've got in the challenge.
1003240	1017120	Right. So they have basically taken the whole big program and they have distilled it down to the core thing that's going on here. And then moved that out into a small test environment, which is excellent.
1017120	1033740	Great approach. And you can see in that other terminal window there, you can see the byte code, that load name, load const, very simple operations there. But it also is going to refer to these strings, for example.
1033740	1044920	The strings aren't in the byte code. They're being referenced. And so what they're determining now is how do I end up with the things that I want to have happen? The references have to line up.
1044920	1056920	Right. And I think you can see that they're printing out these various attributes of the code object. So if I were to take a guess, they realize that they can only change those...
1057500	1058120	The byte code.
1058120	1061300	The byte code. So they need to make sure that all the other things agree.
1061300	1062020	Exactly.
1062020	1076160	But if we go back to TWN, we can see here that they're also looking at the documentation for the compile command function and doing some...
1076800	1079420	Yeah, looks like they're looking right at it.
1094440	1105600	Yeah. And it's funny. If you look at the documentation for this, a lot of the documentation is kind of like, don't poke around with this. It's negative and you should be using other stuff.
1105600	1105980	Yeah.
1105980	1110600	But here we're a competition for hackers and that's what we're asking them to do.
1110600	1120540	Right. And you can see here they were copying the system command and trying to...
1120540	1126920	They have here a piece of code that they want to run. So this is kind of the goal, I think.
1126920	1136860	But now I guess they're trying to get... this looks like they were trying to figure out the byte code of this.
1136860	1143500	So what they probably kind of missed there is that they need to compile that code into code object and then get the code attributes.
1143640	1152460	Yeah, they're definitely in the phase of understanding the primitives that they have, the code module itself, and what they can do with it.
1152460	1157080	Right. And I want to switch back over to Shellfish because you can see here now there's some progress on their script here.
1157080	1164600	You can see the two pieces of code. They have print high and import OS and now comparing these two things.
1164860	1172000	And what I think is an important thing that they will want to look at is this list of constants.
1172000	1182100	The CO constants there, you can see there is a high in one of them and... OK, no, they're only printing one object, so it's high in all of them.
1182820	1186880	So, yeah, definitely look like some progress there.
1186880	1195460	But then that's exactly the approach, though, is they're looking at, hey, I've got two objects and I understand I can only change one of these other things.
1195460	1200500	What do these other parts need to be so that when I do make the swap, it'll all work?
1200500	1201160	Right.
1201460	1205100	I feel like they're making great progress and they're on the right track.
1205660	1213140	Yep. And they're here again looking at just a little bit of documentation for the compile command function.
1213220	1223480	Yeah, this is actually a key detail here. That compile command, the third argument there, the eval argument, controls how the input is going to be parsed,
1223480	1229020	whether it's a single expression, whether you can do multiple expressions, a whole block of code like a module.
1229020	1241160	Right. And this explains why, so it's set to eval, which is a single expression, which explains why earlier when TWN were trying to define their lambda function,
1241160	1246980	because an assignment in Python is not an expression, it's a statement.
1246980	1250680	So you cannot have that in an eval context.
1250680	1269000	However, with the new walrus operator that was, well, relatively recently introduced in Python, you can have an assignment as a statement.
1269960	1280660	I actually wrote a little bit of a blog post about this, how this enables you to write certain types of these Python payloads more easily with this.
1280660	1288300	Yeah, so if they would have changed the code that they had, it was like A equals lambda something something.
1288300	1294200	If they would have just added a colon to the assignment thing there, that would have worked fine.
1294280	1298800	They would still not have been able to call that function, but they could have defined it, right?
1298800	1300980	Right, and that's exactly what I was talking about.
1300980	1305440	When you've got competitors at this level, I totally expect stuff like that.
1305440	1309680	The walrus operator was not something I was thinking about when I was writing this challenge.
1309680	1311860	But it's modern, right?
1311860	1315640	Python 3.10, we've got some extra tools in the toolkit.
1315640	1321820	Right, and if we do switch over to TWN, we see that they are looking at these code objects.
1321940	1326840	You can see that they did compile a piece of code, and they were looking at what different attributes.
1327000	1332080	And now googling again about the code attributes.
1332280	1338700	Yeah, and that co underscore code, that is the key to zero in on here, so I'm glad that we've got both competitors looking at that.
1339400	1341540	And that's just the byte code.
1342040	1342720	Right.
1342720	1344260	As we've talked about.
1344260	1344880	Yeah.
1344880	1348720	So the larger code object has these other pieces.
1349200	1353760	I think that they've both realized they have the ability to modify that co underscore code.
1354440	1359400	So at this point, it's off to the races who can figure out exactly how to use that to gain execution.
1359400	1365420	Yeah, and I feel like, even though I still think Shellfish is a little bit ahead,
1365420	1370320	I feel the gap has become smaller.
1370320	1370680	Definitely.
1371100	1383720	Because TWN is definitely in the right area here, looking at these, compiling this code, looking at how it behaves in various contexts like exec here.
1383740	1389720	So yeah, it's definitely still very much an open game.
1389720	1395800	Yeah, I think that we see this in all sorts of challenges where one competitor will find something.
1395800	1398220	That's the insight that they need.
1398220	1400240	They'll sprint ahead to the next roadblock.
1400240	1402860	And then it's really, it's not over.
1402860	1409320	They get a temporary advantage, but then the other competitor can bust through that insight and then maybe overtake them really quickly.
1409320	1410360	It stops and starts.
1410360	1411240	Absolutely.
1413100	1425400	Looking here at Shellfish again, you can see now that they have the thing they want to do down there.
1425400	1434440	There was an interesting approach where they make use of a second layer of evaluation.
1434440	1449160	So it seems like their goal is to just take the thing they want to execute, put it in a string, and then in their initial code just print that string, but then in their second code do eval on that string again.
1449160	1449960	That's right.
1449960	1451980	I really like this approach.
1451980	1466100	And whenever we see somebody jumping back to the rule page there when they're close to the end, we are watching out because that shows them exactly what they need to run to win the challenge.
1466100	1467340	It looks like they're very close.
1467340	1470340	They've got the sort of secret keyword there, which is omelet.
1470340	1473940	Again, I don't think that's the first time we've seen reference to eggs and shells.
1474100	1476620	So Python shellcode kind of challenge here.
1476620	1483900	I think they were going back to the info page because we released the hint there.
1483900	1489100	So you can see the hint that said this is not a jail problem, it's a patching problem.
1489100	1492840	These competitors both see what the problem is.
1493880	1496280	I think we're pretty close here.
1501960	1505800	It's going to be really cool to see there if they can get this going.
1505800	1509620	They seem like they're making some small changes to the exact code they want to run.
1509620	1513880	Yeah, try and subprocess instead of OS system.
1514000	1514480	Right.
1514660	1520960	And you can see here they are going straight for running the submitter binary instead of popping a shell.
1520960	1531660	So that's a good opportunity to talk about how the goal of this challenge is to solve the challenge and it will always end in you getting code execution on the server.
1531660	1538660	And then on the server you have a small binary called submitter which you need to run to kind of prove that you have code execution.
1538700	1544240	So most of the times you usually just go for like popping a shell and then you manually run that binary.
1544240	1548740	But here you're baking in the submitter run straight into the code.
1549140	1550040	That's right, yeah.
1550040	1554260	And the reference solution that I wrote was more of the shell approach.
1554260	1563020	But I can see that just looking to iterate, get that submitter run, feels it is close.
1563060	1563680	Yep.
1567060	1579340	And over on the TWM side, we have again some more progress around investigating these code objects, compiling stuff, printing these objects, trying to like...
1579340	1588180	It seems like this person is not that familiar, so they're trying to just understand how these things work.
1588460	1593300	What are these attributes and how do they interact with each other?
1593300	1596520	Right, looking at that eval, understanding exactly how it works.
1596520	1602620	So I'm dropping the keyword omelette in there and trying to understand, okay, what does this need to be?
1602620	1605700	Is this going to cause problems if I need to have it in there?
1605700	1610500	But yeah, zeroed in on the ALogCode function so that they know they need to get in there.
1610500	1613780	It's just a question of what's the next step.
1613780	1618120	I actually want to go back again to Shellfish because I saw some really interesting progress here.
1618120	1623200	You can see they compiled the code, they're inputting this, and they win.
1623840	1624880	I think they ran it.
1624880	1625220	They win.
1625220	1627220	I think they dropped the hex bytecode in there.
1627220	1629360	Do we have the confirmation?
1629580	1630760	Yep, Shellfish won.
1630820	1631820	Shellfish takes it.
1631820	1633840	So very, very good job.
1634040	1636280	Let's switch over here.
1636380	1641640	It went from they kind of had it and then suddenly they won.
1641640	1643840	So that's really, really cool to see.
1643840	1645000	Great job.
1645640	1650000	Congratulations, Shellfish, advancing to the next round.
1650000	1654700	Unfortunately, that means goodbye to TWM.
1654700	1657040	Yeah, best of luck to them in the rest of the finals.
1657040	1659440	But this was really a great challenge to see.
1659440	1662080	Both competitors start moving down the right track.
1662080	1665240	Really, I feel like they kept up their lead.
1665380	1673160	But this was actually one of the problems that I think we thought internally was potentially a harder one that might have gone the distance.
1673160	1673840	Oh, absolutely.
1673840	1678900	I think because it's like, you know, maybe not something you're not quite as familiar with.
1679040	1682320	So, yeah, definitely...
1684080	1685980	Yeah, could have been definitely a challenge.
1685980	1686780	Could be stuck.
1686780	1688240	To be fair, we do have...
1688240	1694520	So in this tournament, this is a good time to mention this, is that we are running two matches in parallel.
1694560	1694900	Right.
1694900	1698100	So we are commentating one of the matches.
1698380	1701180	But then there's another match going on simultaneously.
1701180	1703060	And that one has not finished yet.
1703080	1706840	Yeah, and all of these competitors are from DEF CON finals teams.
1706840	1709060	So everybody is top, top tier.
1709240	1715120	We do give the teams a little bit of a heads up in that they know that this is a Python challenge coming in.
1715120	1720260	So they're probably sending in their people who are the very best on their team at dealing with Python.
1720580	1722460	Yeah, totally.
1722540	1727520	And I mean, it's really, you know, the pressure, the stress of being there.
1727540	1730020	Just you, no help from your team.
1730380	1733240	You know that you're kind of like representing your whole team.
1733240	1735980	And there's a bunch of points on the line for this.
1736140	1737180	It adds up.
1737180	1737440	Right.
1737440	1742240	So definitely not an easy task to play these matches.
1742240	1743440	Yeah, a lot of pressure.
1743440	1750700	And again, you can't, it can't be understated or overstated how much the fatigue is going to set in.
1750700	1752460	We're in day two of the finals.
1752460	1753940	Tomorrow is going to be even tougher.
1753940	1754500	Yep.
1754500	1759960	And before we go to a break here, let's bring up the bracket.
1760340	1765340	We do have, as we said there, Shellfish beating TWN.
1765340	1772020	We still have the Orge crowd versus Pigbuttsad going on in the background.
1773020	1780420	So, yeah, the winners of these two matches actually will face off in the next round, which will be coming up...
1780420	1781360	Very shortly.
1781360	1782300	Very shortly.
1782340	1786380	So it's going to be exhausting for the players.
1786380	1787920	Yeah, that's tough.
1787920	1794840	But I think when we were putting the bracket together, it was, hey, somebody is going to have to play back to back to jam in all of these matches.
1794840	1796420	That's just the way it's going to have to be.
1796420	1801420	So I think that's it for now.
1801860	1803300	It was a great match.
1803300	1808240	Really cool to see these teams approaching this problem.
1808640	1811020	And, yeah, we will go to a break.
1811020	1815100	We will be back with the next match in a bit.
1815100	1820420	You can check out, if you want to see the raw feed from the other match, we're just streaming the screens without any commentary.
1820420	1825800	You can go to livectf.com and there will be links there to the YouTube channel and so on.
1827020	1830520	But otherwise, yeah, we will be back in a bit.
1830840	1831340	Yeah.
1831420	1832620	Yeah, great match.
1832620	1834120	Great commentating with you, Carl.
1834120	1835020	Yeah, it was great.
1835020	1837800	And I will be back for the next match.
1838000	1842100	And, yeah, they will see you later.
1842100	1842680	Yep.
1842720	1843280	Great.
1843280	1843840	Till then.
1843840	1844400	Bye.
