 Before we dive into this video, I wanna give a quick shout out to my good friends over at GuidePoint Security, who are hosting another Capture the Flag event, totally free, all online, that anyone can play and access. And this event starts tomorrow. So this is part of GuidePoint's CTF series. They're hosting a week-long competition every month, and these are all meant to be very, very beginner-friendly and entry-level challenges that are still getting you on the keyboard, letting you be an operator, and doing some of that cool penetration testing stuff. So you can go check it out online. I have a link in the description, and you can be participating in an awesome beginner-friendly Capture the Flag event. And maybe you could ask GuidePoint, hey, do you wanna put on some good stuff like this for my own team? That's awesome. Winners of this game, the first person to solve all the challenges, the fastest will get $100 a gift card prize, and it starts tomorrow. So please jump in. I'd love to see you on the scoreboard. And now let's get to the video. Hello, everyone. My name is John Hammond. Welcome back to another YouTube video. And in this video, we're gonna be showcasing a Windows buffer overflow that you might happen to see in other places, like online war games or potential certification stuff. So we're gonna go through a high-level explanation of this and do it for real, get a little demo going on. And I wanna showcase this with the TRUN function, which is one of the vulnerable functions or vulnerable commands inside of Vuln Server. So I've done a few videos on Vuln Server before and hope to do a lot more of them, but it is a Windows-based TCP server that has kind of a command line interface. You can type in stuff for it to do, although they don't really do anything. It doesn't have any functionality other than being vulnerable by design. So you can use it as an educational learning tool to train some exploitation techniques. So we're gonna use kind of the most simple, the most classic, most vanilla, basic buffer overflow example with the TRUN function. But if you haven't used Vuln Server before, it's pretty awesome. I totally recommend you go download it, work with it, play with it. I have it installed here and downloaded. So I will fire it up and show you what we're working with. I've downloaded Vuln Server and it's in this directory Vuln Server here. If you were to take a look at it, you just have an executable file, Vuln Server.exe. And if you were to run that Vuln Server.exe, it will start up and it will be listening on port 999 or quad nine. So if I were to go ahead and create another terminal over here and let's say I pop into Cali, that way I can use my Netcat command because I've got that in my WSL or Windows sub system for Linux install. I can Netcat to my IP address which is 10.0098 on that port quad nine. And once I connect, I can see the server says, hey, we got a client connection and my other display over here is telling me that, hey, welcome to the Vuln Server. You can enter some commands like help and that will tell you all the other valid commands you could run. So Trun is what we're gonna end up using here. So if you wanted to fuzz it or spend some time with it yourself, you totally could. Doing that manually is good and fun but we would like to go ahead and fuzz it ourselves or with an automated tool like Bufas or Spike. So for the purpose of educational value, I'm gonna do this in Spike. Although I've showcased Bufas I think in the other Vuln Server video where I went through the HDR one. Regardless, I wanted to tell you that and give you that setup because I'm going to be using WSL to actually fire up Kali here and I'll invoke keks. So I get my good, beautiful Kali window and give me just a moment. I don't know if you can see this just yet to be completely honest. I'm going to un-full screen this and drag it down so we kind of have a window for Kali and that way we can work with it and explore and play with it. So I'll get my terminal open here. I'll make a directory for YouTube Trun. Thank you. And now we can hop in there and start to work with some stuff. Other things that we're gonna end up discussing and showcasing. I am going to be using the immunity debugger to go ahead and debug and work with this Vuln Server executable and try and figure out this overflow. So if you haven't used immunity debugger I would recommend that or any other debugger that you'd like. I think immunity debugger is just kind of pretty well known and common. So you can download the immunity debugger go grab it online. You have to throw in some, I don't know, information stuff. So totally fill it in with bogus, whatever you want. And then download it. That's it. Blah blah blah. Once you do that it'll just give you the immunity debugger and you can download it. Super duper easy. Okay. That is that for now. Let's do the thing. Let's fire up Kali and let's start to poke at this because we have availability to connect to this machine, right? We could connect to the service and we could run the trun inputs or the trun command, the trun function. And we know for our understanding that this is vulnerable or this is something that we want to poke at. We want to fuzz this and I'm going to do that with spike. So if you haven't heard of spike spike is great. It's kind of I think built into Kali, right? So spike is super duper weird though and that it doesn't have any commands that are indicating its name. You can run anything like, okay sending some stuff over a TCP connection or a UDP connection or fuzzing a web server or listening blah blah blah and having something that calls back to you be fuzz. There's a lot of interesting stuff you can do with it. So we're going to end up using that generic send TCP because we are connecting to a TCP socket and port, right? So that will tell me, hey you need to actually specify the host and the port and a spike script that you want to actually go ahead and run. Then you can also supply some skip variables or skip strings. You can supply those as zero as default values or just kind of ignore it, whatever. And then we need to go ahead and create our something.spk or our spike script. So let's go ahead and do that. I'm going to go ahead and nano just a fuzzer.spk And now we're going to work with the syntax that spike would use. So when you do this, you always typically run spike functions with an S underscore something. That's kind of like the prefix for just about everything that it can do. Now you could read a line or just grab the input that comes from it and we're going to have to do that, right? Because when we were connecting to this thing manually it gave us this little banner, hey, welcome to the vulnerable server and then you can interact with it. So in our fuzzer.spk or our spike script we should start by reading that banner. Then we can start to kind of stage the command that we'll use and what we know as the potentially vulnerable function or the command that at least we want to test and throw stuff against the wall with. So you can do that with a string notion here. And the string will indicate what you are actually going to send in a static way. So we always know that we're going to end up running the trun command and then it's followed by a space, right? That space is super duper important because that indicates, okay, this is the command that we'll run and then following that is the argument. Now, spike is super duper sensitive. You have to make sure every single line is ended with a semi colon. Don't forget that. Then once we're done specifying that prefix, right? For the commands that we want to run then we'll go ahead and tell spike, okay, this is now the area that I want you to spam nonsense. I want you to throw lots of A's. I want you to throw junk. I want you to throw gibberish, gobbledygook nonsense. That's what we're going to fuzz, right? That's the part that will be dynamic. So we can do that by sending a string, right? But noting that it is a variable. So that function is s underscore string underscore variable. And then you could call that variable really whatever you want. You could call it baloney or banana. I don't care. It's just a value that spike will know that you could potentially use later in your script to reference what the fuzz area or component really was. The value of the fuzz data that you're sending. Just for the purposes of demonstration I'm going to call that fuzz and it'll be super duper easy. Cool. Okay, now we could save that script and we could go ahead and throw it against our server. So we know that it's still running, right? Cause I could netcat to it. Now, if I were to try to run that generic send TCP command it needs to know the host 10, 0, 098. It needs to know the IP address that quad nine. And then it needs to know our script that it's going to run. So fuzzer, SPK, and then those other odd ball variables for like the skip bar or the skip string we can just apply zero for that. Now, when I do this, I will start to fuzz and I will be cramming that program with lots of random data and nonsense. So it could hopefully crash, right? It'll tip that program over and it'll fall, it'll choke, it'll throw up. We want to break. That's the whole point of finding this buffer overflows because we want to know where that program is sensitive. We're trying to exploit it. So if I hop back to my window side here you could see just barely that, oh, it died or it closed. Now, it just stopped running, right? But we kind of want to be able to see that and monitor it and understand how that happened and why it happened. So that's why we'll open it up in a debugger. We'll open it up in the immunity debugger. So I've got that over on my desktop here. Fire it up. Okay. Now, when you open immunity, sometimes you might have it in a weird space where all these random windows are open. If that's ever the case, it's okay. That CPU window that shows up at the top is what you are probably most used to when you're working inside immunity debugger. So if you see that one, just displayed up at the very top, double click on that and you'll kind of get used to your quad pane view of what immunity debugger looks like, right? So over in the left top, we'll have the assembly breakdown or the disassemble of the program. Over on the right, you can see our registers. Then we have a little dump as to kind of what is being interpreted in memory right now. And then on the bottom right, we'll have the stack and how that can be visualized and displayed. So I will go ahead and open this program within immunity debugger. You can access it in two different ways. You can attach to a currently running program or you can just go ahead and open. And I personally prefer opening a file just so it lives in the context of immunity debugger just for me. So when it dies, I don't have to restart it outside of immunity debugger and then reattach and all that. So I'm going to hit that, what is it, F3 keystroke? Yep, okay. And then we could open up that volnserver.exe. Okay, so you saw it pop up and a big command prompt window here, or at least this command prompt window popped open. There is a lot of noise in there, but it's not really showing me anything just yet. That's because down at the very, very bottom, if I were to move my face, I guess I'll go to the very top for this video, or at least maybe in the middle, because I know my commands are going to be there. You can see that this is paused way down below in the bottom right of immunity debugger. I'll also, I guess, move my taskbar. This is going to be a hard video to do, guys. So because the program has been opened in immunity debugger, it hasn't actually started running yet. It just opened it kind of at our entry point and then we can determine when we want to run the program. If I were to go back to Cali and try to connect to this thing, it's not going to return, because yeah, we've opened the program in immunity, but we haven't pressed the go button yet. So that's what we've got to do. We can do that super duper easily by pressing that big red kind of play button or the arrow at the top. And that's great. And then it'll pivot into that running mode and method out methodology. That way we could go ahead and connect to it. Our netcat already came back with it. So that worked just fine for us. I mentioned the F3 hotkey, the keystroke, when we were opening the file. And I want to get into some of the quick command or keyboard oriented, right? Keystrokes and hotkeys you can use to make your life a little bit easier working in immunity debugger. Because I think a lot of us, right? Linux command line oriented folk want this to be faster and don't like dealing with kind of the big clunky immunity debugger. I know, I know you don't like touching your mouse. So the keystrokes you could use, and I think these are super awesome, to restart the program, if you've ever broken it or it's at a state of disarray, you can hit control and F2 on your keyboard. And that will try to restart that program for you. That's actually what that back arrows look like over on the top left. It'll ask you though, hey, this is still running. Do you want to close this? And it says, hey, you can permanently disable this warning and options security. We might do that real soon because this is gonna happen over and over again when we keep trying to debug or work with this. That's totally fine. Yeah, let's restart it. And now when it's running or we've loaded up and we want it to run, we can just start another hotkey or press the F9 key on your keyboard. And then it'll suddenly be running. And that's what we want. Okay, awesome. Now that it's running and now that we have a spike script to fuzz it well-prepared, let's go ahead and fire that off. So I'll get back to Cali and I'll run my generic send TCP script one more time. Fuzzer got the host important there, got the variables. So let's just whack enter on that. Oh, and it immediately died and brought me right back to immunity debugger. Okay, so you can see that pause notice down at the very bottom right. And it says, hey, I've got an access violation when trying to execute that 41414141. Ah, okay, so those 41414141, we can see that's filled in the place of EIP or the instruction pointer, right? Where the program's gonna try and jump to next to find its next bit of code. And it died because that's not really code, right? It can't execute just a bunch of A's. So what is the happening here? Well, we've got our crash, right? We've got our seg fault. We've clobbered the instruction pointer so that way we could control the program and make it kind of do what we want. Problem is it looks like our input and you can see that up in the EAX register or the ESP register that has a bunch of A's in it. How do we know which set of A's? Cause when we say four one, right? That's hex A, but that's only one, when we say four one. So if we have four four ones, we have four A's somewhere or the length of that register where in this whole mess of variables, mess of the letter A's, did we get that crash? Can I kind of like copy this value? I'm gonna copy selection to clipboard. Will that work? Or am I just gonna get the, let's close out of our script here and let's start to write an exploit script. Open this up in sublime text. Nope, it just gave me the address. Okay, so that's kind of lame. I kind of would like to see what all these A's are. You could do a lot of different things with this, right? You could kind of open it up in maybe Wireshark if you particularly wanted to. We could probably get an idea as to how many A's that spike sent for us. If I'm scrolling through here, there's a lot. I'm looking at it in the dump, right? And then scrolling through. We went from, I guess, 0DDF1F0. Can I copy that address? I'm gonna right click. Or I could just write this down, I suppose, right? 0DD, and that was what? F1F0, cool. And then all the way, all the way, all the way down to FD98. So I'm just gonna do some quick math, right? I'm gonna throw these in a Python interpreter. Python 3, and I'll drag that over to one side. So I could take that big hex value and then subtract this tiny hex value and maybe get an idea as to what value or how many A's we really just sent. Okay, so 2,984. And we knew that would crash the program. So can we theoretically write our own standalone Python script that will crash this program? And we don't have to rely on spike to do it for us, to fuzz it. So we're gonna end up doing that. We'll import the socket module so that way we could go ahead and interact with this program. So socket is built into Python and you could of course do this with PwnTools and I'm sure that'll make a lot of stuff easier, but I wanna showcase this video without using PwnTools. So we won't use PwnCyclic. We won't have it generate shell code. We'll use MSF Venom. We'll use MSF pattern create and pattern offset to kind of find where our sweet spot sensitive EIP overwrite is. So we're doing it with native built-in stuff, okay? So let's create an object and I'll just call it S kind of for simplicity that will be a socket and Python three, which we should be using, right? Cause that's the latest and Python two is dead. We don't actually have to supply arguments here for that socket object. The default will work just fine for us. So we'll connect to the socket and then we want to send a payload, right? And that's payload is essentially going to be what spike or the fuzzer sent, but we'll expand on that. We'll keep growing it. So let's build out a payload though and I'm gonna actually make this a list because that way I can kind of have like a good vertical representation of the parts and pieces of our payload and hopefully that'll be able to make some sense for you as well. So in Python three, when we're communicating with a socket, we have to send all that data in bytes. So that means that all the strings that we try and send with the double quotes are gonna be prefixed with that B symbol. So we know that the trun command that we're going to send is what's vulnerable. But when we saw it in immunity debugger, this EAX register that looked like it had our input, right? Cause we could see that trun prefix there and all the A's, all the nonsense and garbage that we sent. It looks like it was prefixed with this slash period colon slash, which is weird, right? So that's the magic of spike because it hammered this program. It sent it so much stuff that it was able to determine, okay, this code path we went down kind of got triggered by this little magic, like syntactic sugar is not the right word but this little, I don't know, what's the right word? This thing will trigger that code path, that little magic signature will force the vulnerability program to follow down this code path and eventually break and get us the seg fault. So we wanna maintain and make sure we have that forward period colon forward all in our payload. So let's get that in there. Let's do trun with the forward slash period colon forward slash and then we'll have that as part of our payload. That's just gonna be the very, very start but then we're gonna end up adding in all those A's. Remember they have to be prefixed with a B. The benefit of Python is that we could actually specify the length that we wanna send this on. So I'm gonna multiply that A by what we knew as the total length of our program or the buffer that we sent, all those A's. And when we saw with our quick math and the command line, let me get back to that terminal here in Cali, we sent 2,984. So let's try and send a 2,984 A's. We're gonna multiply a single A by the total length and that's it. Then we'll put together our payload because right now this is in a list format but we wanna join it all together. So I'm gonna use Python again, some magic here to take that list and join it with a byte string. There we go. Now if I were to print this out and I'm just gonna hit control B so in sublime text I can run it and you can see this is our big giant data dump of all those A's. Now that we've got that set up as a variable we can go ahead and send it to the program with that socket object, right? So S dot send passing in our payload. Super cool. So now let's get back to immunity debugger because right now he's paused and we want to restart it because we already broke him. Now we've gotta get the server back so we can interact with it one more time. So we'll hit that control F2. It's gonna warn me, hey, we should probably disable this warning. So let's go do that. That's options, was it debugging options in security? We could warn when terminating active process. I'm just gonna toggle that off. So that way if I hit control F2 one more time now I don't see that annoying pop up. I can hit control F9 or excuse me not control F9 just F9 to run the program. And now bopping back over to my Cali instance I'll hit control B to run this and I have an error. I have a broken pipe. Why is that? Did I not even connect to the service? That's why. That would totally help. All right, this is the benefit in the fun part of doing this for real. When we've created our socket object of course we have to actually connect to a port. So connect S dot connect which we should run before we build out our payload and send it, right? It needs to exist prior. We need to specify the IP address 10-0-0-98 and the port quad nine. That has to be passed in as a tuple. So there's an extra set of parentheses inside of that connect function. There we go. Now if I run this fingers crossed, okay. I hit control B on my keyboard. It fired away and then immunity debugger took control because hey this program just broke. We got our access violation. So we successfully broke the program. We got our crash all within our own Python script. Now we know we have control over EIP. It's filled with all these As but we don't know where in our humongous string of all of those As that sweet spot or that offset for the EIP actually is. So we've got to be able to find that. How do we do that when it's all As for all the same character? Well that's super hard to do, right? So here's the trick. Here's the little technique that you can use. Rather than sending all of the same character we could send different characters in kind of a pattern, right? We could use like a one, a two and then a three, a four and modify the four chunks like every couple of four characters that we send it is slightly different. So that way when we get the value of the IP we could check it within that pattern and kind of look up to see where does that pattern actually occur in that big long string? Cause we've got to send 2,984 As. So we could use a cyclic pattern and we could do that in Cali, right? So we've got our terminal still over here. We can break out a Python and Metasploit actually has a good tool to be able to do this. You could use MSF and then if I prefix it with kind of a hyphen there if I just hit tab, tab you could see all the things you could do all the tools that MSF the Metasploit framework will give you the cool ones that we want to use are pattern create and pattern offset. So let's take a look at pattern create and looks like it needs some arguments. So if we want more information we want that help info we can specify that tack H and we've got to specify the length that we want. Okay. It looks like it's actually giving us an example of what that cyclic pattern looks like. And this hopefully is kind of like what I tried to say out loud. A something, A something else and slowly building out, I don't know a different cycle and pattern of characters. Because if we use pattern create to build this we can use pattern offset to find where that sequence is going to be. So let's use pattern create with tack L on that 2,984 length buffer that we had. Now we have all of this noise all this data, all this junk. So let's copy and paste that. I'm gonna double click to select it all right click copy and I'll bring it into our script. And now rather than all the A's that we're going to send let's try and send a byte string and paste in all that noise that cyclic pattern. So then when we go back to immunity debugger control F2 to restart it F9 to run it hop back over to our script run it with control B immunity debugger says, Hey, I broke and now you can see all that data being filled into our registers and EIP is a different value. It's not the 41414 when it's not all the A's anymore because we aren't using those A's anymore. But this is something that we could give to Metasploit that pattern offset program and then be able to see, okay, where is that actually in that whole long string of nonsense our 2,984 characters. So let's hop back over that terminal and now we could use pattern offset. Now, again, we've got to specify tack H to kind of get an idea for what we're looking for. So you could specify the length that you supplied. So we'll specify that tack L again, 2,984 and then the query or what we saw as our EIP or the value in the instruction pointer because we want to control that we want to be able to set that value to whatever we want so we can make the program bump around and do anything else. So let's use MSF pattern offset and specify the length of 2,984, what we did previously and that Q for the query, we can paste in just what we had earlier from immunity debugger. So I'm gonna copy this, paste it in and it tells me, ooh, we found an exact match of that string that hexadecimal representation of it, right? Cause we're working in binary. So we've got some little Andy and stuff going in and we got 2003 is what the offset is or where we can control the instruction pointer. So let's grab that, let's add that into our script. Let's say that the offset can be 2003. So if we were to modify our payload now we could specify that A value multiplied up to the offset and then just after that, that's where we're gonna have the instruction pointer overwrite and that's gonna be four characters long, right? We know that, so let's create a new variable, let's call it new EIP and for the sake of demonstration let's just make that BBBB. So we can see that rather than 414141 in our code we have 424242, we can prove that we control that. So let's specify that new EIP there. Now notice we've only filled up these 2003 plus four bytes but originally our exploit when we tried to crash it had a total length of 900 or so more characters. Now kind of as good practice, right? Just something that we should do if we know we got a crash, we know we got our seg fault earlier we should maintain that same length for that whole space that we're clobbering within our buffer. So our exploit remains kind of reliable we're just modifying what's inside that payload rather than changing the length or modifying it, right? So that means that I'll create another whole pool or buffer of characters. We've got AAA to denote the starting padding until we hit the offset we're clobbering that offset or the instruction pointer with Bs and then following it we'll add in Cs just so we can make sure, okay we've got that area after our EIP overwrite. So we're gonna multiply that by the total length subtracting out the offset. That way mathematically, no matter what we're still going to have the total length of the payload that we originally had. Now of course we still have our new EIP in there so we'll have to subtract that out just as well. I'm gonna use the land to function in Python to get the length of that new EIP and then if we go back to immunity debugger we have staged this payload so that still 2,984 characters or bytes and length but after 2,003 characters we've filled in our instruction pointer so that within the debugger we can control what the program is going to do next. All right, so control F2 restart it F9 to run it hop over to our exploit script hit control B and there we go. Immunity debugger is now back telling us hey, our program crashed. Interestingly enough, we see all of our A's and our input in the EAX register we see our C buffer seemingly in ESP and our EIP is filled with 42424242 and those are our B's. So we have built our proof of concept we've created and encapsulated this in a Python script we're continuously developing now we can control the program. We have our EIP overwrite control of the instruction pointer interesting thing though now that we can control the instruction pointer what do we do? How can we make the program do something else? Well, is there any other data that we can control because we want to be able to tell the program hey, I want you to do what I want rather than what you were originally supposed to do notice our ESP register is filled with C's or characters that we can control. That's awesome. So the idea would be to grab a little piece of code a little piece of disassembly instructions or things that this program might be doing and it's going to actually go ahead and execute where we want. So maybe we could package up some shell code and maybe get the program called back to us with a reverse shell or a interpreter shell. So if we can control that ESP value in that register and that seems to be our C buffer which we're supplying we want to make our instruction pointer use some location and code that tells the program hey, I want you to jump over to the ESP register and start to execute code that's included in that data. So what we want to do is we want to find a jump ESP instruction. So we could use Mona to do that if we really wanted to. I will control F2 to restart the program, control F9. And now Mona is a super cool tool that you could use and it's some tool in your toolkit for immunity debugger. It's a awesome utility that can really, really speed up the work that you do for some binary exploitation stuff or things that you might be using on an exam or a test or I don't know. So all it is is a Python script and you can grab it and it just says, hey, drop this Mona.py script into the py commands folder inside the immunity debugger application folder. So I've got my windows explorer open here and I have inside of the program files x86 32-bit stuff. I have this immunity ink directory. That immunity ink is immunity debugger, right? So if I click on the immunity debugger, in there there is this py commands directory. So that py commands directory, I want to be able to copy and paste the code for that Mona.py or download it and save it and I'll have a Mona.py file in here. I've already done this, but walking you through it so you know how to do that if you would like to. Mona.py is great. Then from within immunity, once you've got it all set up you could drop down this little white box at the very, very bottom and that way you can control kind of like with the command line interface what you're gonna be working with in immunity. So I'm gonna use an exclamation point which is the syntax to invoke whatever you'd like, right? So I'll invoke Mona with just exclamation point Mona and when I run it, we see all this output. We see our immunity debugger has kind of changed its screen here and now we've got this big notification. Mona has some usage and commands you could run. You could assemble some instructions like make the actual op codes like you would see in the disassembly. You could look for SEH or structured exception handler overwrites, etc. You could look for egg hunters. You could encode some series of bytes. You could find specific instructions that the binary might be using. In fact, we're gonna use that with that JMP command. We can find pointers that'll allow you to jump to a register. So if I were to use Mona and then if I were to specify that JMP command, it tells me, hey, we actually need some register arguments here. The default module criteria is a, requires a mandatory argument TACR where you can specify a valid register. So I will jump or Mona JMP TACR to specify the register that we want. And we know, because we saw in our output in those register values, our C buffer is filling up the ESP register. So let's look for ESP. There we go. Now I've noticed a really weird thing. Mona sometimes just likes to disappear, especially after you've had it run a command. So if that ever happens, just invoke Mona again, without any like command there, just get the help value one more time. And now you should be able to see if you scroll up the actual response of your command. You can see, hey, there's where I ran Mona JMP R ESP. And these are all results. So we see some hexadecimal bytes or addresses within the binary where we could end up actually using that code to jump to that ESP. Now look at the very, very bottom here. There are a couple that are indicated with ASCII. And that's pretty great because it's using ASCII characters or characters that will easily be in our program. Sometimes our programs and what we're executing will only care about bytes and will only execute them if they are printable characters within ASCII. Sometimes there are bad bytes that the program is unwilling to execute. And we will jump into that super-duper soon, but first let's grab this instruction. I'm gonna grab this ASCII one and note here, okay, ASLR is false, that address space layout randomization is false, the rebase is false, the safe security exception handler, that's false, OS is false, et cetera, et cetera. I'm gonna go ahead and grab this one because I like that ASCII representation. The others all have the same settings and you basically want all these things to be false. So you know that, hey, this is kind of an instruction internal to the binary to the program. So let's copy, I'm gonna right-click and hit copy to clipboard, that address, great. So now in our exploit script, we can change this new EIP to be something else. I'll paste in, oh, I guess it didn't copy here. Copy to clipboard, address, can I paste? Oh, WSL does really weird stuff sometimes, okay. Now note, if I were to include that in a new EIP, just as a buffer, that's not gonna work for us, right? Cause this is a memory address to the binary, which means it has to be in its normal biting, bytes encoding with a little endian format, right? That's how our 32-bit programs will typically work. So we have to actually convert that hex address into something that our program can understand or pack it into that binary little endian representation. So sure, we've defined new EIP and we'll use that hex value there, but we wanna be able to convert that. And again, you could do this with PwnTools, you could use P32 or whatever, but we're gonna just use built-in stuff. So I'm gonna import the struct module, there we go. Now the struct module, again, native and built-in to Python, you could interpret bytes as packed binary data. So struct has an excellent module function called pack, and that will return a bytes object containing the values that you pass to it in a specific format. And you'll specify the format as a string, but it takes some certain, I don't know, a legend or a key to kind of understand what that format representation is. You have to specify things in a specific order, right? So we want little endian, which means it will have to specify this kind of less than symbol or that walka walka arrow. So we'll specify that. We will use new EIP can actually equal struct.pack with a string here in the value that we wanna use. I'll actually just go ahead and copy this value so we don't have two lines for our new EIP. Little endian, but what kind of data is it? We gotta scroll down. There are different types we could use. In this case, it's going to be an integer and it's gonna be an unsigned integer. So we'll use a capital I to denote that. We know it's four bytes in size, right? So there we go. Less than arrow, capital I, and now our new EIP will totally be in that proper little endian representation. I'll show you that. I'll hop over to the terminal here. Let's just invoke Python three. I'll import struct, struct.pack with the syntax we were using and it's gonna return this syntax. So B for the bytes, of course, backslash x to denote a raw real byte representation and it's not a printable character. So those are gonna have that backslash x notation. And then the P and the B here, those are printable characters, right? They are ASCII. So those will be converted and displayed out like that. Alrighty. Now we have our script set up with a new EIP instruction. So we should verify that our program, once we throw our exploit script is actually going to go to that instruction. We can test that in our debugger by setting a breakpoint. So I'll hop back over to immunity debugger. I'll get out of Mona. Can I get back to the CPU window, please? Good. I will control F2 just to restart the program, F9 to run it. And now I'm gonna hit control G on my keyboard that allows me to enter an expression or a location that I wanna go to. So I'll paste in the value of where we know we're going to jump to when we're clobbering our EIP, right? That's gonna be our jump ESP instruction. If I go to it, you can see there it is right there in the instructions, jump ESP. Now you could right click and like set a breakpoint if you wanted to. But again, we're trying to get away from the mouse. So let's just hit F2 on our keyboard and you can see that's been illuminated now. Now we have a breakpoint set there. So if I hop back over to Cali, hit control B to run our payload. You can see immunity debugger is going off. There we go. Breakpoint at that location. It has everything still loaded in the registers, our A buffer, our C buffer, and then our EIP value is at that location with the jump ESP instruction. So now if I were to, I think it's F7, right? To step, there we go. Our F7, when we stepped just one instruction, that jumped us right back to our C buffer. And you can see that here down in the dump, right? With the stack that we're working on. And you can see all these instructions. So if I hit F7 again, you can see these instructions just ink EBX or incrementing EBX. That just happens to be what the four three or our C's actually disassembled to as an opcode, right? So you can see as we step through them, we are incrementing that EBX register. Watch as that 109 changes from, okay, moving up in hexadecimal representations. And that's right. Now we're executing code off of the stack all inside of our ESP or our C buffer. So we successfully jumped to a location that we can control. Super cool. Now, I mentioned bad bytes. This is wonky, right? Because some programs might not execute all the code that you give it inside of shellcode. Because shellcode's just gonna make a lot of random new bytes that are gonna execute really the instructions and the operations to do whatever you want, like get your meterpreter callback or get your shell. But if a program is sensitive to that, it just won't work, it'll just break. So let's try and figure out what the bad bytes might be. The way we can do that is we can just send the program all of the characters, every single potential byte that our program might use. So let's use all characters set up as a variable in our script and let's use a list comprehension in Python. Let's get x for x in range of 255. All the ASCII characters we could potentially represent. We could end up using 256, right? Because range is not including that very, very last bit. So for x in range, all those, we have our x variable, but we wanna convert that again into a real byte that our program can understand. Passing it as an integer just won't work. So let's go back to our good friend, the struct library. And now if we were to specify an integer or a byte, right, the format will actually be a capital B. We'll pack it into that representation and now it'll be an unsigned integer, right? So let's do it. Let's do struct.pack little indian capital B on our x value for every single x in all of those possible character representations. We'll have to join this altogether as a big, big payload, right? All characters. And now we could go ahead and actually verify that that worked. So let's print all characters just to see what it looks like and I'm gonna exit just temporarily. So essentially all this code beneath it is commented out and we don't run it. You could use exits to do that or you could comment it out, really, whatever you want. I'm just using that as a demonstration purpose to show you these are all the possible principal characters. Sublime text give us a zero, zero, zero, one, zero, two, et cetera, et cetera, et cetera, and all the characters. Do you notice something off here? Do you notice something bad? Right away we have a zero, zero character or a null byte character. Now in some low-level languages, right, what we're working with here, a zero, a null byte, means the end of a string. So it just terminates the whole rest of everything else you include, it just stops. So we know we can't have a null byte. We don't even have to run it against the program to know that, null bytes will just stop the whole rest of the string from being interpreted. So let's change our range. Let's specify a minimum value of one there and I'll move my face. So you can see that code. I'll literally move my face, there we go. Okay. So now that we have all the characters, we can pass that along in our exploit and see what the program will actually properly render out and work with. If some of them bytes are just deleted or malformed, then we know, hey, it's going to be sensitive to that. So rather than our C buffer, let's go ahead and add in our all characters. And we still, I guess, want to add in our C buffer after the fact, because we want to get that same length. So let's subtract out the length of all characters now that we've added that in to our payload. There we go. Hopefully you can see that. My face isn't in the way too much. And let's go back to immunity, restart the program, run it one more time. So it's ready for us to throw our exploit, hit control B to send it along. I have an error. Oh, I forgot a comma, denoting the all characters in the list there. Okay. Now let's run it. And there we go. It has died. We've hit our jump ESP. We no longer had a break point set because we restarted the program. But now you can see, we've started to execute code that looks like it has instruction zero, one, zero, two, zero, three, zero, four, et cetera, et cetera. So if I take a look at this, if I follow in dump on that address, if I go there, there we go. I like looking at it within this dump output because that way I can kind of see all the numbers in sequence or what values were successfully able to get to the program and what weren't. So to make this easier for you, I like to just kind of look at the last column and notice the pattern. So it's a zero, eight, and then a 10, and then a one, eight, and then two, zero, two, eight, et cetera, et cetera. If that back and forth between a zero or an eight stops between any of these characters, then I know, okay, something in that previous line was either removed or mangled or done something weird with it. Looks like we got all the way to FF even from zero, one. So it looks like we don't have any bad characters other than the null byte. Awesome. Good for us. Still something that you've got to do every time you're doing this. We got lucky because the trun function in Vuln Server doesn't require any bad character checking, but you have to do it. And that's hopefully a good method that you can use to work through it. So there we go. We know that we have a section of code that we can control and we know that there aren't any bad characters. We know we can jump to it and we can execute code off the stack. Hard part is we're kind of making this jump through a trampoline, right? But depending on uncertainty, and this does get a little complex, right? We don't always know that our exploit will be reliable. Something you should do is you should put kind of like a soft cushion or like a slide or a sled that your code and that program could just kind of ride the flow down until it gets to your executable payload or your shell code. I'm referring to a knob sled or a no operation sled. Now that knob operation, that means in that lower level assembly language, that programming, it means don't do anything. It means do nothing. No operation, right? So the op code for that is actually a hex 90. When we saw hex 41 for our As, we saw that hex 43 for our C and that was increment EBX. Hex 90 is no operation. So let's get back to our payload and let's start to build a knob sled. I'm gonna remove that all characters test there because I didn't really need it after we've just kind of done that test to find the bad characters. Since there aren't any bad characters, we don't really have to worry about that. At least 00 or the null byte we know is bad. So now let's start to build out a knob sled. I'll just call this variable knob sled and I'll take a byte for hex 90. Again, in Python, that backslash X representation and you can make this kind of as long or as small or as big or whatever as you want. I'm gonna make just 16 of these, right? So now our new EIP after we've controlled it with our A padding to hit the new EIP which is essentially going to be our jump ESP instruction, that brings us to what would be the C buffer just right after our input. So that's why we were able to use those all characters right there because we could easily see them. Now that we wanna put shell code there and we wanna slide down to execute our shell code, we should put our knob sled right there. And now let's subtract that out of our final padding there, LEN of knob sled. Super cool. Now if I were to test that, again, just for the sake of demonstration, let's control F2, let's F9 to get immunity back in a good state. I'm gonna grab that exploit kind of a jump ESP instruction pointer and I'll go to that again with control G and immunity bugger and I'll set that break point. I'll hit F2 so I can monitor when our exploit is doing and what it's doing. Now if I hit control B to run the exploit, you can see I've hit the break point, we are executing our jump ESP instruction. I'll hit F7 to step through it and there you go. Now you can see in that output there, we're hitting our knob sled or that no operation. So we slide right down and now we still have all of these Cs, that whole buffer that we can fill with shell code. Now we've gotta go ahead and generate that shell code, right? So let's get back to it. I will hop over to Cali, I'll get into the terminal here and I'm gonna use MSF Venom to generate that shell code. So I'll use a payload tack P here and I know I'm working on windows, I know I wanna reverse shell and I want metropodr. Windows reverse, oh goodness, how does that go? Is it just Windows reverse metropodr? Is that all it takes? I'm pretty sure, let's find out. After I've specified that payload, I wanna specify the L host or kind of what we're connecting back to. I want that to be this machine. I'm just gonna specify the interface here. So ETH0, you could IPAS to see what your IP address is. This interface here for ETH0 is my current interface and that's 172.3249, blah, blah, blah. For our quick convenience, I will go ahead and just use the interface name. Windows reverse metropodr, I think it's reverse TCP. Is that right? Why am I forgetting this? Is it, I think it's Windows metropodr reverse TCP? That's gotta be it. Windows metropodr reverse TCP, let me check. We can just check in the payloads and see if it actually is anything, but I'm just gonna end this event, it takes a little bit of time to run so I just hit enter on there. No platformless, okay, so that's gotta be right. Windows metropodr reverse TCP. Thank you for bearing with me on that, I'm super sorry. Our L host should be our interface, our L ports can be quad four or whatever port you wanna listen on cause we're gonna have to wait to catch this and we'll specify the format or tack F as to how we want the shell code to display and return back out to us. Cause when we ran this earlier, it gave us all these bytes, the non-printable characters. We don't want that cause we want them in our script in our exploit code and that's written in Python. So I'll specify tack F with Python or you can use pie as kind of a quick shorthand. I think that will know that we're using Python three because Python two is dead. So it'll print it all out with that B prefix and there we go. And now you can see that backslash X syntax, blah, blah, blah. But notice as I'm looking through here, some of the shell code that we're generating has these null bytes in there. So we have to tell MSF Venom, look, we have bad characters that you can't create our shell code with. So don't use those. So you'll specify attack B prefix or a flag there or an argument and we'll specify backslash X zero zero. Now, if you knew you had more bad characters, in this case we didn't, just the example, you could specify them here, XFE or FF or before really anything, you just specify it included in that string. We're just gonna use that backslash X zero zero for our null byte. So no null bytes should be in our shell code payload. That'll execute. And once it has generated the shell code here for us, we could go ahead and copy all of this. There we go. Final size of py file is all this. Our payload size is 3000, excuse me, 368 bytes. That's super important to know because keep in mind our exploit script, what we have in control of this buffer here, if I hop back to our exploit script, we have 2,984 total buffer. We've eaten up 2,000 of it already and then we have added in our knob sled. So realistically, we've only have about 900 or so bytes left for us to work with. If you ever get into a problem where you don't have enough of a buffer to include your shell code in, you've got to do some other tricks. I won't go over that in this video, but know that you have to do it. So now let's grab our shell code. This is all being pasted in as this buff variable. I'm gonna go ahead and actually rename that to shell code. Shell code equals buff. Just, it's totally useless. We don't have to do it. I'm just doing it for your understanding and learning, hopefully, right? So just after our knob sled, as our program executes this code, after the knob sled is when we're going to put the shell code. And of course, because we've added this all in, we have to subtract it out from our final buffer so we have it right in the proper length. Move my face, because it's in the way. Let's subtract out the length of our shell code. There we go. Okay, so if I zoom out, we have built this little gun here. We built this little weapon, this little exploit script that will use this offset that we already uncovered with MSF pattern, pattern create and pattern offset to get a new EIP, which we know is going to be an instruction to jump to a register that has data that we control, which we saw as our C buffer. And now we've put more stuff in that C buffer. We've replaced it with a knob sled at the very, very beginning and our shell code. So because that was part of the C buffer originally, we had to subtract all that out. So we still have that exact same total length that we always wanted when we were sending this exploit and filling up this buffer. So all that said, I think we have everything that we need to try and get a callback. So because I'm using Meturpreter, I've got to go ahead and start a little listener to do that. So I'll fire up MSF console. I'll get Metasploit ready and running for us. And we'll use that exploit multi-handler so we could actually prepare a listener or something waiting and ready to catch when we get that reverse shell connection from the target and exploited service. So let's use multi-handler. Good. Let's set that payload to be that Windows Meturpreter reverse TCP. Everything that we set as options within MSF Venom, we still have to make sure that it matches inside of our exploit multi-handler configuration. So when we set the payload, that has to be included. Our L host has to be the same. Our L port has to be the same. Those just have to sync up with what we created as our shell code. Now, if I were to run this exploit here, it will start and wait. It'll have that reverse TCP handler. There we go. Now, fingers crossed. If I go ahead and move this over to one side, I wanna be able to see our shell come back. So I'll move the sublime text code over here so I can invoke it. I can run it with just control B. And let me check on our immunity debugger. Looks like he's still paused. So we have to control F2 to restart him and then hit F9 for him to run. And then let's go ahead and start our script because everything that we've weaponized, our exploit script that we've built should get us a metterpreter callback on our target or an attacking machine, exploiting the target. So I'll hit control B and there we go. Metterpreter session one is opened. Taking a little bit of time to call back. There we go. We've got our metterpreter prompt and I can be running like, oh, let's get you ID. Let's see where I am. Let's check out whatever is it hostname? Is it sysinfo? Good, good. If I LS to check out my current directory, I have code execution, command and control. I have a shell on that target or victim machine because we were able to exploit and take advantage of that vulnerable server or vulnerable server in this case. So, wow, we've done a lot. This was a super long video. I hope I did a decent job of explaining things. I know this was kind of a slow pace but I hope you as maybe beginner, maybe newcomer, maybe someone that's not as familiar with the stuff, this is what we can do using immunity debugger, using Mona, building out an exploit script in Python. This is all the cool stuff we could do to be able to take advantage and get code execution and control that box. So there we go. That is our exploit script, the shell code that we generated, the payload that we wrote, all the fuzzing that we did with Spike. This is it. And you could maybe experiment with that total length or see how big you can get your buffers to give you more, I don't know, flexibility and control over what you're firing off here. But that is it. Holy cow, long video. Thank you so, so much. I really appreciate you sticking with me for this one. I hope this was fun. I hope you learned something new if you haven't done this. Windows, buffer overflow before. Again, this is the most classic vanilla, no bad characters, nothing up against you, no stumbling blocks or roadblocks. This is the cookie cutter stack-based buffer overflow. So thanks so much, everybody. I really hope you enjoyed this video. If you did, please do press that like button. Please do leave a comment. Please subscribe, do all the YouTube algorithm things. You know, I'm super duper grateful. And I love you guys. I'll see you in the next video. Take care, everybody.