 Folks, Adam Dubey here, and today we're going to be looking at the Poneble.kr level. BF is what I'm going to call it. So this is the first of the Rookies section here in Poneble.kr. And so I'm excited to get started on these, what should be more difficult levels. So here, this BF challenge is 150 points, which I believe all of the past challenges the most points were 10 points. So we'll see how this goes difficulty-wise. It said, I made a simple BF language in relation programmer to C. The bracket commands are not implemented yet. However, the rest of the functionality seems to be working just fine. Find a bug and exploit it to get a shell. So we can download the bin BF and the BF underscore libc.so. You can see that it's running at Poneble.kr on port 9001. So for those that don't know, language BF has been used in a lot of CTS. It's in this family of esoteric and weird programming languages. And so it is basically an extremely minimal programming language. So let's go down to a, we may have to figure out and actually use this. Thinking off the back, this may be a write a BF program that actually triggers the vulnerability. So it will maybe to set things up correctly. So this may be good. We can see this Hello World program here. So all the characters, I mean, all the commands you have are these characters. And so your program is completely out of those characters. So you can see that it looks kind of ridiculous like this. So this is the Hello World BF program. And so this will be a fun challenge, I think. So we should dive into other things. We can get right off the bat just by looking at this. So it's A, we know it's running on some port, which means we're going to have to do a remote exploitation, which is great. The other thing we notice is that it gives us the specific version of libc that they're using. And this leads me to think that we, obviously, they're not going to give us something if we don't maybe need it. And so what this is going to do is going to allow us to really try to understand if we need to know what's the difference between offsets in versions of libc or something. That's what we'll have there. So the first thing, as you know, I like to do, run file on BF. So we know it's a 32-bit executable, which is a good dynamically linked. We know we actually have the exact version. We also know it's not stripped, which is nice. We'll have some symbols for us. And we can do the same thing on libc.so. And just to prove that there's no spoilers, the exact way file is quickly emptied. So same thing with the libc. The other thing I always like to do is to run strings on the binary, especially if it's something like this. Like, I have no idea what it's doing. And just really scroll through it to see. So we can see that here's a string in here. And so it's important to understand what strings does. It just goes through looking for sequences of ASCII characters that are a certain length or longer, followed by, I believe, an alternating string. So we can see a lot of this stuff, standard in, FGED string length, and set get car, standard out, set be buff. This is all going to be in the global offset table of the program. So we can see the string of this is not supported, which is actually exactly what it said. Welcome to BF testing system, types of BF instructions, except for those brackets. And then we have other stuff, symbols, all that kind of. So now we can just execute it. I like to get a feel for the program. Let's see if we can get it to do a hello world, like, example here, which will probably not work because it can't use arrays, but hey, we should be able to still see what's going on. Get out with some stuff, but our brackets syntax was clearly not working. So another thing I like to do is run it under Strace and Ltrace. So Strace is going to put all the system calls that it's making here. So we can just see that it's, and you have to look at these things a lot of times to really understand it, but really it's writing some output, it's calling Fstat, it's reading onto the heap, which is probably one of these break calls, it's calling read, it is reading it, it's writing out that these things aren't supported, it's also writing out these characters that we just saw in the output, and then it's closing. So we can do Ltrace, do the same thing. So Ltrace is going to be hooking instead of the system calls. So the system calls are all in between the program in user space and the kernel in the operating system. So if you're confused as to the difference to those, I highly recommend you check out my CSE 545 videos, specifically on application and security, because we cover this a lot. So here what we're looking at is all of the, these are now all of the, these are all the libraries, so the libc functions that are getting called. So it's actually a lot, there's, so it's using trunlang, it's using buts, so these are things we should be able to see in this assembly, so let's pop over, so that's all that, I mean I guess we could try what happens if we run vf, just passing a obnoxiously large input to it, so what happens if we say to, we can see it's not crashing on all of this input, so that's good, so this means that it's not just a buffer overflow on the string that you pass in, it could be probably a little bit too. So let's see, let's start, so we got this open now in hopper, let's go and look for the thing and see what's going on. So it's calling set vbuf on standard out and standard in, but basically what these are doing, you could ignore these for now, oh the other thing we didn't see is what happens when we just netcat to this guy. So we should see exactly the same thing here, and this may be surprising because what we're used to is that this is, so for netcating to a program, it means that we're connecting to it over a socket, but as we can see here, we're running this program locally from standard out, so the key is the wonders of x, i, net, b, so I won't go into it, but basically you can use this to set up a console program that's accessible over the internet. The problem is you get into issues of buffering, so you may not get all the output you want, so this is what this set vbuf is, so essentially the idea is I'm going to be kidding for it, which is going to start with the testing system and then set variable eight, zero, four hundred, and then set build to the first n bytes and they're ready to go through, like that's what the console might see, so basically, so this variable 408 is going to be on the stack, so it's 400x, and so this is why we couldn't overflow the buffers, so we know we can only give 1024, so the most we can give is 1024, so that's what this app gets to make sure that only 1024 bytes are going there, and then it's going to have the counter of bar 40c from zero, the string like app gets, I should have wondered, it's what happens when app gets more, so app gets read in at most one last-in-size character, so it stops reading the line, turning nobody's sort of last-in-size code, so they're able to write, so this is the very basic portlet to be via, it's going to pass in bar 40c, that's what we're going to dereferent borrow again, so it's passing in, and then zero, and then that's what this is going to do, all we can see, so the other thing we didn't do is run this in a check-sec on our binary, just to see what screen corrections it has, so it is not positioned at 10th pendant, it has a non-expecable stack, and it has a stack in it, okay, so this do-vf function, looks like this is going to be our main, and it looks like it's going to be passing in our input to this function one after the other, so that's what this, so far, 40c is our iterator variable, what's the variable, i, and then 408, so it's just going into the indefinite variable, so it's just going to be forward, maybe it's our memory variable, so we can see the pss segment, which is pretty large, it's going to be data segment, it's going to be symbols of all the symbols that it's going to use, get a car, okay, so this tape looks like it's some memory, so, okay, I guess the thing I didn't explain about vf, even though it has these incredibly simple commands of incrementing a data pointer, decrementing it, incrementing a byte, decrementing a byte, outputting a byte, accept one byte of input, storing a byte of the byte, and then the brackets with my jump commands, essentially the idea is that this is a turn-complete programming language, and so the idea would be with the tape, they're probably implementing that in terms of a tape close to a turn, so it sets the tape on the path where we should be able to figure out how that, it's actually a pretty standard thing, awesome, so essentially what this is going to be is, this is essentially what they've done is they've put in a very basic interpreter, so something that's going to, so the way you have basically an interpreter, and the way you write it, if you go input by input, you first tokenize it here, that's very easy because the token is simply just one character, so then you're just gonna have this huge big block that says basically a switch statement with all the different cases of what character it is, what happens here, so then this is very standard if you look at any type of emulation or interpreters, that's what we're gonna get, so, okay, so, the pd, the stack pointer, the base pointer, push, pd, x, so r, one, this is a, so subtract, so then create, it's based on the stack pointer variables, move that variable to eax, move the ale at the lower byte, the eax register on to rc, so this is the s and x, move with sign extension, okay, so move with sign extension in eax, so subtract to b from eax, which this is a plus, so then it's gonna compare eax to 30, plus, we can see that plus is at 2b, so we can go here to our vf22 and we can see that the characters that are important to plus, my is dot, comma, here, so it's attracting that eax into the variable 30, it's less than 30, it's gonna go down to this point, so it's like, so then we compare, so basically the idea is to figure out what this, so this is move into the switch table in eax and export jump to eax, so this is, yeah, so this is how the switch table is important in all of these different cases, so the idea is, and what's nice is that, so this is actually an indirect jump, and you can see the value to jump to from the switch table, but copper very nicely has decoded all that more on switch 3, so the copper then says, so it's kind of saying that it's putting this not supported, so this must be to figure out that. Actually, I mean, it should be pretty easy to, for example, to say to a friend it's case here of 19, do you ever, to be moving into eax, add one to eax, eax to that part, so this must be, I think, from the d-reference, this must be a lot of this, as I've said, so 17 or 19. Here, another case, do we take the, the reference of the d-k-a-x to the right, d-reference, e-a-x, so I extended the d-reference back, so let's go and put the two in, so to create a case 3, so this would be, the 3 would be docked to the board, yeah, so docked is 3, so it's angle bracket, and the other angle bracket are here, so these are incrementing the pointers, this is case 1, so it's going to be plus plus 1 comma, so that's going to be getting into the character, so this is how we compete in p-b-x, we'll get character in a-l, but in case 0, it's in plus d-reference, e-a-x, e-b-x, add one, all right, so then, so this is what we got, so this is the start program, so, okay, so p initially points to the tape, right, we saw that, so we saw that in the main, it should be set to the tape, so this is where p currently points to the tape, so one thing we could do is we could move it back, keep moving it back with p and then we could, okay, we always got to remember what's our goal here, so we want to read out the flag, so easiest if we can do some kind of NSH funness, let's see, the question is, okay, so we know we can move the tape back onto p, which will actually let us then, we just keep going forward and backward, so we know, so we can only increment 5, 1 and we could drag it in our month, this is 8, so we only have 10.4, we don't have any moving constructs, so we can't have that help us, but we can go backwards into p and then completely change the value there, change that, so, okay, positive for a bit, so I could do a little bit of research, so what I was looking for was, so essentially what I'm picturing this exploit being is what we're gonna do is we're gonna use our, we're gonna use our overwrite permission, so we're gonna move our pointer p into byte writing itself, we're gonna try to move it onto the, where we want to in the global offset table, then we're gonna read out four bytes for one of the values from the global offset table, so we can figure out, basically, essentially leaking us a pointer into libc, which we already have, and then when we know that address, then what we'll do is we'll calculate the offset from there into what's known as the magic number, so basically the idea is every version of libc or most versions of libc, when you think about it, they have a libc as a function called system, which it essentially calls execde slash bin sh, and so there's actually an instruction where if you were able to jump directly to that, it'll call execde slash bin sh with null and null. So I'm gonna try out this one gadget tool, which I haven't used before, because I am aware of this concept, but I haven't actually used it before, and it's CTF stuff, so it's a good, and then you can take learning experience for me, and so now that it's installed, I should be able to say one gadget, hash user local bin, one gadget permission, for roast into mix. I mean, the idea is this simplifies it because essentially we need to jump to somewhere, but we want to jump to system, but we want to make sure that we're calling system with bin sh, so not the problem. All right, it was a pubcat problem exists between keyboard and chair, so clearly what I realized is I was passing in bf, not bf, underscore libc.so, so right in here, we can see that we have some constraints here that we can do this if depending on what various values are, so here there's this one, which depends on ESP plus 28 being null, ESP plus 22C being null, ESP plus 30 being null, ESP plus 33, 34 being null, VAX is equal to null, which may be something we can control, maybe the value of VAX depending on what happens, so or where the stack pointer points you to be null, but essentially we do have all of these things, so this is interesting, so we have some targets that we can do, and these are offsets from the base pointer in libc, bf, underscore libc. So the next thing we need to figure out is what do we actually want to overflow? So the idea is we're gonna look back on our main function, see if there's anything else it does, so stack check fail, we can't make that fail, so there's nothing after this, although string length could be called every time, it could be called every single time, so it'll be part of the array, so topper is trying to force it to disassemble, it's going to be super far from vf, so a couple things, so a, what we want to do, what we're trying to do is figure out the name of the dvf function, like this, so we'll look through each of these things to see which one, okay, perfect, puts, so it's puts used anywhere else, let's see now, so I'm looking to see it, okay, great, so puts is only used, and it's passing in this argument, so we can play around with it, all right, so got our target, we want to change puts to be essentially the length of our awesome address, so we can scroll the value of the a, so we can use this string here, just doesn't give us something to scroll, so we can do that, okay, so the idea is what we want to do is we want to get the put care, so we need to look at the dot entry, lowercase r for the put, 040, 040, all right, so this is the dot, so we know that that's an address at runtime, so now we can actually try building up our exploit by bit, which, okay, so we're going to do our first challenge is to get this key pointer and point to where we want to do, so let's first just set stuff, stuff will happen, okay, it's really important that I use punctuals for this because punctuals will make sure that this, that when we get back, that we can read in those bytes at a time to leak that, we need to leak the address of put car, and then what we're going to do is overwrite it, so we need to leak it first to calculate the fixed offset that we actually want to go to, our variable, we know our variable is going to be stacked, so it's going to be possible to leak, so we want to get our entry there, so we know at the start of the program, main is going to put take, all right, so key, which is at 080480, so let's start with bytes of 08048080, so to move the take onto the fifth, so if I just wanted to try to move from the take to this GOT entry, maybe as I was going to figure out how many characters do I need to do, I have that, so I could just do this with 112 incremented, if I could do something clever, if I need to, I can pop here, change right here, change right here, it's going to be inside our pointer, the only time that I've got it's multiplication, it appears to be an entry, so I'll do this, but see where I want this, 112 of those guys, so what that should do, and what I'm changing is the book character, so, but now I'm actually at there, so what I want to do is, so this will key to GOT entry, for looking here, so now I need to read out each of those bytes, so I want key plus equal to what I want, so the important part is, so I want to receive is four bytes, so I think I can probably specify exactly how many characters like this, so make sure I'm not actually receiving, up to num bytes and data return, so you can receive n there, receive n, so I want four receive n more bytes, which takes a, data return to a string, so that makes it what I need to do is, now I've leaked out those four bytes from the GOT table of the character, now what I'm going to do is write those back, but let's make sure that I'm doing this correctly, I want to, so I need to make sure that I want to, so last thing I'm going to do is, I'm going to come down to see all the rest of those bytes, clearly I'm going to need to GDP this sort of seed, right, so I've got to then debug this and figure out what's going on, so let's go and exploit, steal my script, do you want to write points, it's pretty easy because I do have tape and I have keys, so I can figure out what's going on, iteration here, so I see what's wrong, so now we shouldn't see some actual results on some bytes, so it's working now, now that I'm moving actually in the correct direction, let's go back to the dvf function, let's go to the getpar8756, now that's good, so now we pxp that there and then v0, okay, so I guess, I'm going to do one good examine, so p, we now have the value of 08048030, which is 100%. And so this is the go to entry, so y is, okay, so I'm going to put character first, just to, I was thinking the first byte of it was y7, so the first call, and then now I'm going to value that it's f765p920, so now I just want to make sure f765p920 great to go back, so now I'm actually going to be loud if I didn't, if I didn't debug that, I wouldn't have thought to have to call put character first to load that value, so I wouldn't get in the wrong value back, now I know that I can steal that value from there and then now I know I can change it so I can do a byte-by-by character replacement to replace that value with whatever I want, using the comma character, a little more time, which will then should hopefully give me what I want, so now I can essentially, at this point I can completely hijack the control flow of this application, so now at this point where it's going to call put character, put part, I can force it to go wherever I want, so I can, so what I'm going to try to do is try to expand my repertoire and I don't want to have to deal with, I guess I could put slash dnsh in a member location and then figure out how to create some kind of rock chain to do that, but this kind of seems like a lot of work, so let's see if we can just use this magic jump to the magic value. The tricky part though is debugging this, so how can I, what I want to know is how to run, I'm using a different, send a different version of this, so I can kind of run this program by LTV preload, one of the greats, let's see if this works, process, put a pass name, set up an object, power, so close, let's just see if this is, why don't we see if I can just do it, this would be a good tool to make, but this isn't testing this a little bit dangerous, so what we'll do is try this on a farm, let's use it against our version of Lipsy to make sure we can do this, the address is different, but we've got to do it, we need to product it the same, so we've got to work locally with this offset. So now, so what I need to do, so basically what I have now, so I know where that is at, I can get that there, so I can leave that value, so our target, what I can do is I can figure out where is the put character offset, honestly, I've done this a few times, I never remember exactly, but I know you can realize this, now we need to write it out, we need to want to say zero, and so now we need to make sure we send it, so I've calculated it here, so this is part of the chain that we passed in previously, and then we do, and then we want to actually trigger that at some point, we get F7, 5, 8, 0, and F7, 5, D, C, 5, address, and this is awesome, so then it goes zero once. Okay, next instruction, now do you reference the AX, that into AX, I can't actually make sure that, okay, then jump to the AX, so we did correctly overwrite it and we did correctly come there, which is awesome, the problem is that ESI needs to be that value that we calculated of what the zero to do is figure out, now this is the value, okay, so we know after this the bunch of zeros, so we know before we want to trigger over with the character, we want to move the pointer to one, two, three, four, so this should output a goal fight, thank goodness, can't be choosers as they see, so then, all right, okay, so this is obviously against our local copy, but that doesn't help as much, and I just got to figure out how to change this around, put in the values that we want, about a bang, about a boom, and so, it's good, so I think I love about all the set, how it's assuming it's not super fun as always, and hopefully you saw some of the tricks and techniques that, there we go, and it's working, all right, thanks everyone, we'll see you next time.