 Hey, what's going on everybody? My name is John Hammond and in this video I want to showcase this baby boy challenge from seesaw CTF 2019 this was the first challenge in the PON category or binary exploitation and it's I Guess trivial right and that it's a low 50 point challenge in the binary exploitation category But this is not really my strong suit and I learned something really cool in this challenge that I wasn't aware of before So I wanted to share it with you so let's go ahead and get started It gives us a couple files to download here It says welcome to PON as the description and we're given a netcat command that we could use to connect to the service So it has to work remotely, right? I'm gonna go ahead and create a little connect autosage script just so we can save that and Connect to it as we needed to so I just created a simple bash script and copied it in there So we'd be able to actually run that command and don't have to worry about oh here is my actual netcat host important number, etc. Just a convenience thing that I like to do It says hello here. I am and gives me some hex value here. So Hello, okay, and that's it. That's all the binary seems to do But we can go find out what it really does because they give us the binary of libc Like the C library a shared object file and the baby boy dot C source code So let's download all these I'm just gonna right-click and hit W get or copy locations We can throw that to W get we'll download it and let's work through all of these So W get that Do the exact same thing Cool. So now we have these files here. We have the libc We have the source code and I had add downloaded it previously my bad. Okay. Now we're clean Let's see what this is. This is a 64-bit executable. So we know we're working the 64-bit architecture x86 64 and not stripped binary So if you wanted to you could do things like read elf on all of that and see what we have in here Nothing particularly interesting But we don't need to do all that because we have the source code. So let's take a look at baby boy dot C And this is our source code. It looks like we're just including regular standard libraries for C We have a simple main function with arguments that just flushes the buffer here or works with standard out centered in Senator that works just fine for us and we have a buffer variable 32 bytes and it's just saying hello here I am with the value of printf So we actually get to see one Location of a C standard library function and know where it actually is in that binaries runtime That's gonna be pretty handy for us because it looks like the next line is a gets function call So gets is just that hey Super dangerous function never actually use this if we check of the man page for gets it says this will read in a string From standard input, but it's deprecated It doesn't check for any buffer overflows It doesn't verify whether or not it actually is within the bounds of the buffer that you pass to it that variable That's created there. So it tells us up here. Hey Never use gets it's impossible to tell the data in advance before how many actually characters were reading in so we could very well Be subject to a buffer overflow attack and that's exactly what we're gonna do So we know that that is the shape of the binary. That's what we're working with I'm gonna clear out all of these things in my Sublime text so that's kind of clean for us and now let's go ahead and start to beat up this binary I'm using PON tools So I've got PON cyclic that I can actually use and we'll actually be able to use that to fuzz data We're actually send a cyclic pattern to it. We know that it is about 32 Just pulling up the source code here. We know that it is 32 characters for a buffer So we could send more than that. Let's send like 50 just to send it to our baby boy here And I need to mark that as executable. So don't forget that chmod plus x baby boy and Now if you wanted to PON cyclic, let's just send some data to it when I'm using PON cyclic What that's doing is just actually creating a cyclic string So we'd be able to tell okay if we're looking at D message where our instruction pointer crashes or overflows We could see that we know we're getting that segmentation fault so we can see that just easily Let's check out D message see where I'm at and I'm getting a general protection seeing a trap there That doesn't really help me. So I know okay. Let's tone that down. Let's go to about like 45 and Throw that at our baby boy binary check out D message one more time That's probably pretty hard to see Sorry, my face might be in the way, but okay now we see we're overriding 6c 6 1 6 1 6 1 6 B Is that actually what we are overriding though, let's I'm gonna I'm just gonna tweak this lower and lower. We'll get to 40 I'll check D message now. I get a seg fault at zero Okay, so set fault at zero means that I probably just clobbered the instruction pointer 64 bits So we're RIP rather than EIP and maybe there's just a null byte in there Let's flood that again with 41 and see if we get potentially our Last character maybe an A in there. Maybe something lowercase a so let's check our D message output and Still zero We're not fully clobbering it We're just trying to massage this input so we can find our offset is or where we can clobber that Instruction pointer because we know that's going to be overflowed And there's our 6 1 and 6 B in there, okay So that's 2 so we can assume that 40 is going to end up being our offset And we can start to build out an exploiter payload to actually work with this We don't have any functions that we could jump to like a simple like get flag or print flags or get shell so we need to be able to Probably track down the system function call within libc and then go ahead and actually call that function and We'll just get a shell. We'll run bnsh and it'll work for us. So let's check it out Let's go ahead and create a script. I'll call mine ape.py Get a shebang line rolling for us and I'm gonna be using PON tools So from PON import everything and let's grab our binary here. Let's create an elf object for baby boy and I'm actually going to want to differentiate between I'm running this locally and running this remotely because we have our connect script and That is the host name and port number here So let's say port can equal that host can equal that and let's set like a variable just a boolean test for us local equals true We're not whether or not we're actually going to run this locally or remotely. So I'll say if local then my P Will equal Elf dot process Probably that sounds weird to say sorry my I'm to create a process From this binary and I'm just going to call that variable P because that's shorthand really easy really simple if We were remote or if we were not actually using a true value of local We'll use these host import values and let's set P to a Remote session of host import. So now we're gonna we know we're gonna connect to it and let's go ahead and print sorry Let's print out P. Receive so you can see what we're working with here and I'm gonna use this in Python 2 Before it dies and goes away 2020 is coming quick note if we were to use Python 3 We return the same information I'm using the Python 3 Pone tools that you can find on GitHub I think the project isn't maintained anymore, but it's still usable. We use it for Katana and other projects So B notes it. Okay, we're receiving this information as bytes and It's actually a little problematic in the way you might normally use Pone tools Especially if you're working with a binary and trying to work with some Libc libraries, etc, etc It gives us a nice check stack output so we can see we don't have to work with PIE We don't have to worry about a stack canary or anything But we know we're working on a 64 but executable and we cannot execute off the stack So we can't use shellcode. We have to use something like Rop or the return-oriented programming language stuff to Really abuse this binary. Okay, it's giving us the system Location I said system and that was the wrong word It's giving us the location of the printf function in C in our libc library and we can see that okay That is going to change every single time because of ASLR Maybe on the remote system or even on my local system. Let's run this in Python 2, sorry But since we can know that value even at runtime because the program will tell us then we could potentially determine Where the base address of libc is we could just go ahead and work with it We could just actually subtract out we know the location of Printf so now we could find the base address of libc and because we're given the libc file We know where system is So simple ret2 libc attack because they simply just give us printf. Let's go ahead and work with that. I'm going to load just a LDD I'm gonna use LDD to find out where my local computer is actually using my libc rendition Looks like it's in forward slash lib x86 Blah blah blah. So let's say libc can equal elf of That and if we were remotely we would use the libc from That libc that's in our current directory right our libc 2.27.so whatever so let's just slap that in there Okay, so now that we have libc Let's carve out where we're receiving that printf location and let's go ahead and use that to find our libc base address. What I'm gonna do is I'm gonna say P.receive until and let's get until the here. I am Kind of syntax there here I am with a space and let's do p.receive just following that and I'll say that that is Stripped so we don't get that new line character there. Let's print that and Now let's run our script Still working locally now we can see hey, we've got our printf Address here just displayed as that variable. Let's go ahead and actually make that a number because right now That's a string. So I'm gonna use the int function to wrap around that and I'm just gonna say that's base 16 That should be inside of my int function, sorry So we don't need to print that anymore, but let's actually call that printf Now if I were to print printf Python treats it as an integer just in decimal if you wanted to see that in hex Now we just encapsulate that variable and it's a number that we can work with so perfect now that we know where libc is now That we know the printf is in libc at runtime. We can find out the base address of libc So let's check that out. Let's say libc, which is this object we created in PwnTools We can actually use libc.address and say this is where the base address of libc is going to be You have to set this when you're working with that libc object from PwnTools By default it's zero so all the offsets between symbols and things in the GOT or the PLT are just based off of zero within the file as it knows, but you can set it to something else Corresponding the libc file you're working with and then all of the other offsets Excuse me all the other offsets or the symbols you want to pull will just be the correct value So let's see that We can say libc.address can equal printf because we just got that value minus where we see the libc symbols address of printf indexing just like that Okay, so with that syntax just a little math just some quick subtraction there We can find out the base address and the offset there I'm gonna print that out. I'm gonna print out libc.address and I'll put that in hex so we can see it and Let me just add a few Display things here, so we know what we're talking about when I show this on the screen Cool printf. We know is that all of this in libc base address now that we've done that math We know is that all of this and that looks like it's paginated well That's in the right kind of area in memory. We can that makes sense to us because this starts off the same way So now we've got base of libc and that means now that we've kind of corrected our libc rendition We know where system is as well Let me show you something just real quick if I were to run that same script doing that same thing with Python 3 using the Python 3 Pwn tools This is the issue that I was gonna run into and I wanted to inform you about it Is that when you try and retrieve that printf out of the symbols here? It'll tell you hey Kier I don't know what you're really talking about because you have to index that with bytes and That's a stupid idiosyncrasy that you might trip on and run into I don't want you to have to end up falling on that Now if I had that be prefix to say that's in bytes sure it'll be able to find it and run without an error So let's still use Python 2 when I run it and that works just fine for us, okay So now we have our libc address our printf address and now we can say the real system is at libc symbols of system Perfect, so now we could call system if we were to overwrite our Instruction pointer that RIP value But we're not using regular 32-bit calling conventions now We're in 64-bit so if we actually want to pass an argument to system which we do right we want to actually run it with a Value loaded into RDI. So those are the 64 bit calling conventions It looks for arguments in RDI and I think RSI and Other locations then it gets into the R1 stuff. I Can't remember off the top of my head But RDI is the first argument that we're gonna need so we need to find a gadget or some location in the binary or within libc that we could actually return and work with that pop RDI instruction So we can suddenly fill a value inside of our Argument and give that to our system function here. So let's do that I'm gonna actually use Rop gadget and when you use Rop gadget, you need to use tack tack binary You can see zshell is trying to autocomplete for me stuff that I've already done here So let's just give it the baby boy binary because maybe we could find stuff in there that we need rather than looking in libc And we have a lot of results here Kind of hard to see on the screen. Sorry, but one of these real quick for us is this pop RDI and RET So pop RDI and return Everything will have a return at the end of it because we are using Rop return oriented programming So that way we can just jump to this position move back to where we were and that's how Rop works. It's pretty cool Let's go ahead and take that address and let's just say pop RDI can equal that And let's start to build a build out. Sorry, excuse me a potential Rop chain Let's say we want to pop RDI But what do we want to pop into RDI? What value do we need to give in there? Well, we need to give it that bin SH string But where are we gonna find that we can find it within the binary What we can do is actually use Libc because that's given to us we can use search And we're just looking for a string here as we can just pass in bin SH When you do this, you'll note that that's actually to give you an iterator or a generator object So if you want to get the first result, I just run dot next and now we have that address if we were to check that out in hex Cool. Now we have a location within the libc where bin SH just that string exists And we could give that to system because we popped it into that RDI register and we'll use that as an argument In 64 bit calling conventions. So let's say that that value is Our bin SH string or variable that we want to use here. Now, we've got a Rop chain We can use Rop chain pop RDI Bin SH and let's go ahead and call system with that. I Like to use the syntax. I found it or at least kind of like that idea Caleb my roommate uses it a lot especially He's illicit tiger in the discord server and you've probably seen him in other videos This is a really cool technique that he uses and he's much better at binary exploitation than I am If you create a Rob chain just like that inside of a list You kind of read it in a more assembly-like fashion and then we can just join it together by using p64 Or p32 on all of those and that way it's in that little endian format that we need to be able to pass to our binary So I'll just say R for R in Rob chain So now we have a Rob chain that we could use and we need our payload Which will just say a random junk random stuff 40 times because that'll fill up until we get to our return instruction pointer. I'm sorry our RIP our 64 bit instruction pointer Now that we've hit that offset now that we are flooding into the instruction pointer will pop in our Rob chain That will call pop RDI with bin SH and then jump to system So let's try that. Let's go ahead and use p dot send our payload I Think the send line is what we want. Let's find out and now that we've sent that We should have theoretically jumped to a shell or call a shell. So let's move that into interactive so we can see it work Here we go and switch an interactive mode. I'll hit enter a few times and I'll run ID And now you can see that's John So I can run who am I? I'm still John and We have a shell I can run commands. So we just called Bin SH and now we have control over that system. I'm running this locally though So all we have to do now because we've set up. Hey, here's our host and port Here's the remote service that we're connecting to and using the remote libc We can just switch that to false up top here And we can go ahead and run our script and we should be able to work with it But we got an end of file while reading interactive mode. I don't have a shell so This is what I struggled with for a little bit of time Caleb and I were wrestling with it It sounded like people even on the discord server and those that were playing seesaw CTF were wrestling with this I did not know this. This was a whole new thing that I got to learn and Props and shout out and thank you to crypto was his name and discord who Reached out to me and checked in with me and said like hey, I got this. Do you need a hand? What's up? Because my my exploit I said like I don't I don't know what's going on my exploit works locally It does not work remotely. What do I do? There's no way to research that kind of thing. I couldn't I couldn't track it down so the guy said to me The remote service is on Ubuntu 18.04 and I'm running on 16.04 locally and apparently Ubuntu 18.04 in its 64 bit sense. I don't know if it's strictly Ubuntu 18.04 maybe maybe other 64 bit distributions or things do this but Apparently it works memory the stack the whole this whole binary realm works in a 16-byte boundary So that means that our payload and things need to be aligned or within a Kind of 16-byte multiple. So what we have here for our Rob chain pop RDI We know that's eight bytes and same with penis H and all That gave us 16 total here, but system that's not So right now our stack pointer is not being fully aligned to that 16-byte boundary and We're not able to call system on the remote machine So what we could do is just filled out with a little bit of garbage or some padding just some junk with 8 bytes somewhere really just not in our pop RDI Alignment there because we need that to fill that argument and not after system because we need that filled out Before we're calling system our stack pointer needs to be set and aligned within that boundary before we end up calling the function So we could put it just before system or put it at the front here Let's do it just before system and we need just padding and junk a good way to do that is just check our rops one more time Or our gadgets here. We have one of these that is just a simple ret Command there. So let me take that and let's just create a variable for that Let's say ret can equal that value there and We have everything else that we need to build out our rob chain and let's say ret right before we call system okay, so We have some information Some testing to set up whether or not we're running this locally or remotely Maybe it would be a cool idea to do this with our parse So we don't have to just be modifying our script while we're working with it We determined the address of libc so we could get the proper system location We got a couple gadgets between pop RDI and ret and we found where bin sh is in our libc And now we built out a rob chain with p64 put it in the little endian format that we need Use the correct offset and we're sending it and we're going interactive. So now let's see if I run this working remotely local is false Will we get a shell? It doesn't kick me out whack enter a few times looks like we're still in ID we're baby boy. All right LS. We got it now We have a shell on that remote service on that remote system and we did it cat flag There it is flag baby boy Do-do-do-do. All right Let me clear that up. So it's more of the top of the screen for us and That is that so you go ahead and submit that a 50 point challenge still some hefty stuff I by no means am good at buying or exploitation This was a learning experience for me. I need to practice a lot more with this rock emporium Maybe ponable dot XYZ other resources and war games that I need to work through so that I can get better and We can get better you can get better too when it's that's the community. That's the family But right now I need to focus on OSCP, so Thank you guys for watching. I hope you enjoyed this if you did a please do like comment subscribe I would love to see you guys in the discord server There is a link in the description if you are willing to support the channel, which I am always so grateful for and so thankful for I Have a patreon account also link in the description Would love to see you on there super duper grateful and super thankful for all that you do to support So thank you guys. I'll see you in the next video