 Hey folks, Adam DuPay here, and in this video we're going to be going over the ponables.kr challenge coin one. So this is a challenge I haven't done yet, and so this should be very interesting. So let's dive right in. So it says, mommy, I want to play a game. Don't we all? If your network response time is too slow, try to netcat from inside the ponable.kr server. So it's saying it's running at ncponable.kr 9007. So right here we should stop and tell ourselves, okay, so they're not giving us a binary. They're not giving us any source code. They're not really giving us anything about this challenge. So what should we think about here? Well, it is possible to, and there have been some, I believe, DEFCON quals challenges like this, where you had to break a remote binary through a buffer overflow or something like that by leaking data about the program. So it was a completely blind attack, but that's probably not for a 6-point challenge here. It's probably not what we want to do. So let's then look at what we got. So here we have this netcat. Let's go and let's try this. So we just have to go in with an open mind. This literally could be anything. Shall we play a game? Yes, we shall. It says, you have given some gold coins in your hand. However, there's one counterfeit coin among them. The counterfeit coin looks exactly the same as the real coin. However, its weight is different from a real coin. Real coins weigh 10. However, the counterfeit coin weighs 10. Help me to find the counterfeit coin with a scale. If you find 100 counterfeit coins, you will get reward. Wow, okay. So an FYI, you have 30 seconds to find 100 counterfeit coins. Okay, so how to play. You get a number of coins and a number of chances, C. You then specify a set of index numbers of coins to be weighed. Important note just off of here, it's clearly zero based because of this example we can see. Then it says you will get the weight information. Two to three repeats C times. So however many chances we have and then we give an answer. Okay, interesting. So that's how we actually supply which one we want to do. Cool. All right, so we have the server n equals 4. So the server is going to send n equals 4. C is equal to 2. So we can see it did that here. It sent, wow, n is 309 and C is 9. And so here on the case, so this is actually a, I believe this is a fairly standard programming type question. We're basically going to do a binary search here. So the idea is, so here there's four coins. So in this example, there's four coins. So what we're going to do is weigh the first two coins. If we get 20 back, we know that the bad coin must be in the second half. If we don't get back 20, then we know the bad coin is in either zero or one. And so because we got back 20, then we know we should weigh the one of the coins in the second half. So three either two or three. We weighed three. We got back 10, which means that the counterfeit coin is two. And the two, this is important. It means that we have two guesses. So on the third one, we need to guess what the actual, we need to put what we know that the counterfeit coin is. So this is a, I'd say this is a newish trend among capture of the flag. So this doesn't really have anything to do with security or buffer overflows or messing with file descriptors or any of the other, you know, reverse engineering, any other challenges that we saw. But clearly the interesting thing that this has to do with is about finding, being able to code this up to be able to do this and to do this. So it's really more kind of like an ACM programming challenge where you need to write a program that's going to be able to do this. So this should be fun. And so to do this, where it will turn to our old friend, Pwn tools. So from Pwn import star, I believe that's how we want to start. And actually, like I always do, I was going to try to impress you by just showing that I could type all this off the top of my head. But that seems useless. Let's look at our.py. When did I write? So I always like to bof the buffer overflow. So I always like to use these connections if I can. So that should be fine. Cool. So steal whatever you can from what you've done in the past don't necessarily need to do it from scratch. So I'm going to go to 9007. So by using port 9007, so by using this debug level, this means this will output everything that's happening. So this actually makes programming this a lot nicer. Okay, so I want to receive until so really what this is about managing state of where we are. So I want to basically read receive until we get to this. And to be honest, I'm going to spend a lot of time in the Pwn tools documentation because I don't remember all the syntax here. The other thing of what I'll do is I will open up a I will need to install first an ipython environment here. I also probably need to pip install Pwn tools, but that should be fine. And really, so what I want is an ipython environment so I can ask for documentation about Pwn tools and generally try to recover here. So I guess I could I could receive until ready. So that should receive until about this line, depending on the semantics of receive until receive until tubes. There we go. This is what we want in the Pwn tools documentation. So now we want receive until so basically this is just going to keep time out. We don't want any time out. So basically receive until yeah, space were okay, great. So that will receive until it gets to this ready line. And we don't really care about the output there. Then so what are all the receive functions. So now we need to receive you want to we just don't want to receive bytes. We don't want to receive that receive lines until one line is found with Canadians at least and items. Okay, we can do ends with we can do a predicate at regex. So this is nice. Okay. So wraparound pred, which returns a regex match the lines is used. That's exactly such a true match we used instead. If the request is not satisfied before time out seconds past. Okay, great. So connection dot receive line regex and we want to receive until we get to the regex n is equal to slash D plus space C is equal to slash D plus. So that should we should be able to get that. So that should return that line I believe receive pred receive data until truth file drop all other data cool. So this is going to return us this line. So this should return us this line. And now we need to import we need to import the regular expression. And we want to do a regular expression matching on this because we want to extract out those values for N and C. Okay. And so we will all right. And presumably, we will, I think we'll keep doing this in a loop. So let's put this in a while true loop and say the first thing. So basically, each of this is one round of the game. So it's telling us we have to do it 100 times. But hey, a while true loop should be just as good and should tell us exactly what's happening. So we want to get this line out, then we want to re dot search, I believe. Let's go over here. Python development headers. All right, well, goodbye. My good friend in boon to. So in this example, we don't even need a boon to I'm just going to develop locally on my Mac because I have not set everything up here. So let's go to our directory, vulnerable dot kr, coin one, there we go. And do I Python? I usually use Python two, because I'm not a Python three expert right now. Or yet, I should guess I should say. All right, cool. So now we can say help re dot search. Again, I love to use the built in helps as much as I can, whether it's the man pages or Python's help. I want to use that. So re dot search. And I've already, and I could probably make this a variable. Let's do something like this. And I don't really care about efficiency right here. Remember, time is of the essence. Sometimes you get extra points for being getting first blood being the first one to cap a flag. Really, you just need to get hacking. So that's the thing that matters. So let's paste that in there. And was that re dot search pattern, then string, and then the string is line. There we get the result. So now we can go over to our example here. And we can say this is our input line. So we'll say line is equal to something like this. And then we will get so we do have a match group. The problem with groups. Awesome. N is equal to result dot groups zero. Actually, we can just unpack this like this. Let's say n is equal to that. C is equal to that. So now that we know the coin is somewhere within here. So we have our and we have our C and let's just print out and see the import says. So now I always like to test these things. So seeing can we just to make sure can we do this three, two, one. Boom. There we go. So we properly got that. So yeah, so I just like to always test my code as I'm going to make sure that way if I had a bug in any of this code, I would know it right off the bat. And so I could start dealing with that fixing any bugs. But now I know I'm able to parse and see very well. So now we're going to need to write an algorithm essentially that goes through and figures out what to do here. So let's see, I know I'm going to need to do something. Maybe n times. Let's try this. Let's try to do found equals none while. Okay, well, we haven't found the answer. So we need to start splitting up our ranges. So this should be a binary search. So so the start bound is always going to be zero, the end bound is going to be n minus one. So basically, the way I'm thinking about this is starts at zero. So I'm indexing all the coins, this is an inclusive bound. So we include start to end, these are all the, the possible chances. And what we're going to do is we're going to split this in half, choose, it actually doesn't matter which half you choose, you just choose, let's say the first half. I'll put that as your guess, get the result back and say if the, then switch your start and your end based on where we are here. So that should be good. And actually I should be able to do this. Let's do this. Let's say for I in X range C, there might be some problems here, but we'll just go with this for now. Okay, so for every chance, every guess, what we want to do is first select the midpoint, then output to server leave up until up until the midpoint and then check result and update, start and end. Okay. Great. So how do we detect the midpoint? Well, this should be easy. We should be able to take, say midpoint is equal to start plus end. Let's see, start and end divided by two, I think that should just give us and we can actually rely on Python's automatic truncation here. So it will automatically give us an integer. And we'll say the midpoint is inclusive. Maybe the math is wrong, but we can go back and fix that at some point. How much more of a fix the math later kind of a person rather than make it be 100% correct right off the bat. So let's set the midpoint, then output to the server of the midpoint. So output, I'm going to want to get a X range from start to midpoint, I think plus one to make sure we get that midpoint value. And let's try this. So we already actually have an end. So we can kind of play this a little bit. So we can say n is equal to 693. C is equal to 10. Start is zero and is n minus one. Midpoint will be here, which would give the midpoint. So 693 divided by two. Right. So then we want to output all of this. So we should be able to do space dot join. This is what I want. Let's see. Expected string int found. Because these are all integers. So I suppose I could turn this into this by calling this stir I for X range sounds like a Star Wars fighter. Cool. So that's n zero, one, two, three, four, five, six, nine, 10, up to 46, including 46. So that's great. That's why we did midpoint plus one. And connection dot send line output. Then we need to read in a, and then read in a response match. Ah, so it is important that we do this C time. So I do get C number of guesses. And then after that, I will make sure that I get the correct one. So just like in this example here. So we get two guesses is our first guess. This is our second guess. And then we say that the counter for coin is the third. So all right. So now we need to read in this result back. This should be pretty easy. The response match that we want is just simply a slash D plus. And I mean, we could be fancy. We could say, Hey, we want it to be at the start to the end. But Hey, that's probably overkill for this. And line is equal to connection dot receive. Just we can just do a receive line. We don't need to necessarily receive on that result is going to be RE search, the response match in the line. The weight that we get back from the server is going to be will be the same as before result dot groups bracket zero. So that should give us the second match to give us that weight. And we should calculate the expected weight if these are assuming these are all good coins. What we want to do is calculate the let's see we want to take midpoint minus start. That should be how much we can actually coins coins to test. This is actually much easier rather than calculating it from here again. Let's not worry about the math. Let's do that times 10. So it should be times 10. So if Okay, so I have two cases. If weight is equal to the Okay, and this should be an until it's past this as an ent. Otherwise, this check won't fail if weight is equal to expected weight. Okay, so if it's equal to the expected weight, then that we know that means we the counterfeit coin must be in the next one. So we can set so start must be equal to let's see midpoint plus one end is still equal to end because we don't know about that. Otherwise, it could be somewhere in here. So start is equal to start and end is equal to midpoint because that still could be the counterfeit coin. Okay, we definitely have a case here of if let's say if midpoint is equal to the end, we could have problems here. So we can actually check up here rather than just dealing with it. Let's just say and I'm definitely need some debugging information here. So I'm going to put round I start midpoint and let's go with expected weight. Great. And then so what will happen in the case that start and end are the same values. Let's say there's zero. So zero plus zero divided by two will be zero if they are let's say one. So we both one plus one divided by two still should be one. Oh, that's not actually a Python shell. All right. And so we should converge on I believe the start should definitely be the shell. There may be a problem here already that I'm thinking about when the case that we found the counterfeit shell and it tells us nine, then we'd want to make sure that have start as that. But let's say we get here and then we get out of this. So let's say at this point, we want start start to be the counterfeit coin. So we do cond that send line start. And should say so going up back to the example, we yeah, so we should pass in now the counterfeit coin we send it and we should get back correct. And then if we do we start this whole bad boy all over again. So this wall true loop. All right, let's see, we've written a bunch of code. Let's see you know what it's going to be. So let's see if this actually works. Let's move that up to the top. So B three misses that be unsupported operand types for string. Okay, so NC is result groups. That's right. So n is equal to 10 equals NC. There we go. At least I got the right values for there 3355 and 90. So we sent there we go. Correct. There we go. Interesting. So we have only 30 seconds to do this. Right. So wow, I'm actually shocked that this got this right on the first try. But hey, see, oh no, time has expired. Okay, so that's the problem. So just like it said, the problem is that we can't actually converse with the remote system fast enough. It may help by changing this debug, but what will help a lot more is if we SSH to one of these other levels that we've already done, let's say, I don't know, shell shock or something. The problem that I wonder about, but that's okay. Let's see what happens. Make directory slash temp slash atom t coin one point one is not a proper one. Let's see. Let's see. I Python. Well, all right, we will see if this works. Cat bang. And then the other thing is, so what I need to change is rather than connecting to the remote system, we want to connect to local host. So one two seven zero zero one nine zero zero seven. I don't care about that. Oh, cool. All right, looks like that works. They have everything they need. It actually be much better, I guess, if I didn't have all this debug info, but hey, there we go. All right, played 10 games. Wow, I'm actually shocked that this algorithm worked on the first try, but hey, that's sometimes you get lucky and sometimes things work exactly as they should. So that was super fun. binary searching is easy. So there we go. Got six points. So this was a very fun example and a really good example of these types of challenges that require you to not just know how to do security stuff, but to know how to actually program. And so that's why these are the kinds of levels, why I think it's so important to get really familiar with how all the functionality of poem tools. So you can learn about like, I didn't have to know that, oh, is there a received line regex or how to do all this kind of parsing and interacting with the remote process. So this is something that I think is really important to develop your skills in. And so yeah, I really enjoyed this level. So thanks for watching along with me and I'll see you next time.