Hack The Box - Introduction to Binary Exploitation - BatComputer - [Walkthrough]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and welcome back to this new video today we're going to be talking about another challenge from the intro to binary exploitation track from hack the box this is bad computer last time with the chiefs where we explained it in a very low level way but with bad computer this is already a little bit more difficult challenge so let's jump into it we get a file that we can download again so if we take a look at that file so we take a look at the file we see okay it's a binary it is stripped this case which means that all the symbols all the function names have been taken out of it um and all right so like last time we are going to jump into ghidra to take a closer look because gitra can generate pseudocode for us so that's this here so we have four functions that have weird names they start with fun and then the address where they occur a couple of these are nothing this one is like an initialization function for setting the buffers but then we have this main function here which is going to do the main bulk of the functionality so first let's look at what this binary actually is what does it do so if you run it it says welcome to your bad computer what would you like to do and we can either track the joker which is then going to print an address for us or we can chase the joker that's going to require us to enter a password so all right i entered a random password and the password is wrong well let's check what the code does so this pseudo generated c code is generated from the assembly because i don't know assembly that well so i like having this it makes it way easier so this function is going to be in an infinite while loop so i'm going to print as the prompt and it's going to scan f this a integer that's why it says percentage d here and it's going to put that into this integer variable okay it's then going to check what that value was so either a one or a two if that's a one then we quit this first loop and we jump to the password nope that's not there it's not if it's not a one we skipped it to do um the other one but if it's a one we print this string and this printf has a um a p in it here for formatting so it's gonna print uh this stack this buffer i guess it is yeah it's a buffer of size 76 it's gonna format that into the string now what does this formatter mean well we can easily find that on google and here we see okay the p format specifier what does it do it prints out a pointer so what we saw earlier here when running it is a pointer and this is a pointer to a certain buffer on the stack okay so that that's already great because if you have a stack address that means that later you might be able to jump to your stack address to run code but that is only possible if the nx bit is disabled so i'm going to run check second on this checks it takes a little while and that's going to tell us what kind of security is set on this binary so we can have pi we can have nx we can have all these different kinds of things and what i'm looking for here specifically is to see if nx is set why well we have a stack address so we have a place that we could possibly jump to and this nx bit as we can see it's disabled if this were enabled then that means that memory can only be executable or readable or writeable so you can either write to memory but then that memory won't be able to be executed anymore so in that case for example we wouldn't be able to upload uh shellcode on the stack which is occurred on the stack and then jump to it to run it but with nx disabled that means that we can actually push shellcode on the stack if we find like i prefer overflow somewhere and then jump to the address and we know we have a relative address here on the stack that we can calculate other addresses using so so we can then jump to that child code and actually execute it because this bit is disabled so that's great um let's keep looking in the code here so that's the first option gives us that so then we have the second option here which is going to ask us for the password it's going to scan let's see what this is this is a string i guess sophie yeah this is a string of length 15. so it's going to scan that into this other one which is 16 of length so we had to end up for overflow there and it's going to compare that to bad passwords so we actually have the password here so i'm going to copy that and i'm already going to put that in python so here i'll say the password is going to be equal to that just so we have that for later all right so if that is if we enter the password correctly we are going to it's going to say access granted and we can enter navigation commands and for those navigations commands it's going to read 137 bytes into this buffer and that's the buffer of which we have the address and but that buffer is only 76 bytes big so we have a buffer overflow here um okay so that's really cool we know okay there's a buffer overflow because we're reading more bytes in and we are getting out and it's the buffer overflow is really easy to access because we have the password here so let's actually see if we can put that in in practice see if that works so if we run this bad computer so first we're going to change the joker i'm going to enter the password okay then we enter the navigation commands and here we want to enter a hundred and thirty seven something because that's a max that we can enter so if you go python c we can print a times 137 okay let's copy that paste that in here and we actually see that currently nothing happens now why does nothing happen we over we have overflown this buffer right why doesn't it work why doesn't give us an error well that's because it hasn't tried to uh do something with it so when does a buffer overflow occur well when we try to return when is the segmentation folder writer well when we return and we're trying to jump to an address that it's just not shellcode that is just not code that's when it happens so we want to get to this return now how do we get to this return let's see so if we enter option two and we do a wrong password to exit if we do right password we just loop back up but what if we enter a three as an option here when it asks us to chase it to chase the joker or to do something else if we enter a three then shoot this if should make sure that we break out of this while loop here up top and that would cause us to return so let's try entering option three here and as you can see okay we returned and we got a segmentation fault so that's perfect because we know that we have something that we can input that's going to overwrite the return address so that's so then we can jump to a place that we want and we also have this first option with tracking joker that's going to give us an address to the stack so if we jump to that address and uh upload some shellcode there then we know okay we can have action some code execution here we can maybe run some some commands so that all sounds great and let's put that into practice by starting to write our program here so this program is going to automatically do this for us and so we're going to import obviously pawn tools so i actually have to do from pawn import everything and then at the top here we're going to say our i o input output is going to be able to the process of this bat that computer binary so this is going to open the bad computer start it as a process and then we have an input and output here that we can read from and write from so we have a couple of steps here so the first step is it's just the enumeration of the binary which is what we've been doing so far we found this password and this i just this place i use for storing all the things that we have found in the binary okay the second step is to get the leaked stack address so leak stack address now how do we leak the stack address well we do that by entering option one here and then we get a stack address perfect so let's write some code that's going to do that first so we're going to first send a line after the symbol because if you look here you see okay when we receive this with a space then we have to enter input so after we got that we're going to send a one then we are going to say okay our stack address is then going to equal to the next line but we are going to strip that from all new lines and stuff we're going to split that and then take the last of it so why do we do that well the line that we get is this so we if we split that on spaces and take the last argument here we have this hexadecimal string here okay so that's the first part of of it however then we obviously only have a string with the hex hex address and well we would rather have um it as a something that we can use um not a string but a bytes stuff like that that we can use with bond tools in our in our payload later so for that what we are going to do is we are going to turn them all into into hex so how do you do that well we're going to loop over this so let's see loop over every character no we want to we're going to what we want to do is we want to take the first two characters turn them into uh hexadecimal because then they are a string but then we want to take their value in hexadecimal and use the and do that for all sets of two so that means that in our range we're gonna start from the second one and because this zeroed and the first are these and we want to get rid of those we're then gonna go over the full length of this stack address and with a step size of two so that means we're gonna use grab this then grab that then grab that and then grab that and so on until the end okay so that looks good what are we going to do at the beginning here well we want to grab the integer off okay now i have to think here because we want to grab the integer of those values in our stack address so um we have from i from that index till i plus 2 because we want to take 2 and okay so that's going to take that but we don't want to integer we want this in base 16 so we have it in hexadecimal all right and then we want to turn that into a character again okay perfect so that's gonna be let's let's actually run this and print that see what what it returns us because that was kind of extract and hard to explain so i hope that by running this this will make more sense so as you can see we have strings now representing the bytes that actually occurs for example the first one is always going to be the same 7f we have the string here that represents the byte7f the next one is this and and so on so okay then then we can join those together so we have one string so we can join those together perfectly and then we have the stack address however we want to make sure that the stack address is eight bytes in length why is that while we're using we're working with a 64-bit binary and so if we're going to jump to addresses we want to make sure that they're always eight bytes because that's what's being pushed and popped so to do that we can simply use we're gonna take our stack address and then we're gonna our justice with eight bytes and if it's so r just means okay make sure that the length of this string is eighth eight else add to the right following and we're just going to add a null byte to the right okay so then lastly what we want to do is we want to unpack that at 64 bytes so take our stack address and okay that sounds good so this unpacking here what it's going to do it's going to take this string and put it as an integer so now if i print the stack address here you see we have it as an integer now why did i do that well later if you want to work with the stack address for example say we calculate that our shellcode is 20 bytes from this stack address then we can easily add and remove from it if we want to use the stack address again then we'll do a pack 64 of the stack address again okay hope that makes sense uh let's actually add a nice lock line here so lock success and say okay leaked stack address is at and then we'll print this nicely as bytes okay so if we run that we have the stack address boom as you can see they are adjusting that at these no bytes so these are eight bytes long now perfect exactly what we want so that's step one leak the stack address step two is to do our actual buffer overflow okay so for our buffer overflow what do we want to do well after we got the stack address we want to switch to option 2 to chase joker so let's run that to see what we want to do so we went to chase joker then we want to enter the password which was this and then here is where our payment payload occurs okay perfect so let's write that in code here so we're again going to send a line after receive this again we're gonna send option two we're then gonna send a line after we receive password with our password that we supplied earlier and that's that and then after we receive commands we are going to supply our payloads and our payloads we'll make that a times one three seven because that's the max length that we could use okay perfect so knowing that we can run this see what happens at the end here i'm gonna do an io dot interactive to make sure that doesn't shut down and it's going to show us what happens afterwards okay so run our program here we see okay we leaked the stack address and now we are back at this option so now we haven't gotten a segmentation fault or an end of file so the last step that we needed to do is to trigger the return so we're gonna do step three it's gonna be to trigger the return and how did we do that well we sent three instead of two here which is going to end the while loop and gonna make sure that we return okay let's see if that gives us a segmentation fault now and it did end of file if i now exit this we can see okay we get a code minus 11 which is a segmentation fault great so that's exactly what we wanted now we need to work out how we can actually use this to jump to any address that we like now the first thing that we need to know is we need to find the offset uh of we need to find the place that we need to jump to to uh to overwrite the return address where we're going to jump to so how does that how are we going to figure that out well we know that this number has to be below 137 137 and above 76 because 76 is where we are over flowing the buffer and then 137 is the maximum and below that is where we were able to get the segmentation fault well you can do this like manually try to figure it out but we can also create something that's called a cyclic string so let's do that and a cyclic string is pretty much going to be um let me run this first from pawn import everything and then we can create a cyclic string and we created of this length so this is a string and what we are going to do now is we are going to debug this binary we are going to use this string as an input and then we are going to see where it crashes and the address that it tries to jump to is going to be four bytes here or yeah four bytes here or eight bytes here and those are going to be shown to us and then we can say okay hey find these bytes in this string and tell me what offset they were found at and that way we can know okay we need to add so much betting then we add the return address so that we always jump to that address so let's uh do that so for that i'm going to open it with gdb so we're going to do that computer go we can then run this so first we're gonna chase joker we have to enter the password okay enter the navigation commands this is where we input our cyclic string here and then we enter three to get the return okay and now we see we have an issue or not an issue we triggered a segmentation fault here which is perfect which is what we want so now we need to look at what we were going to jump to so as you can see the instructure pointer endpoint pointer currently is pointing at return so what is the return going to do it's going to pop something from the stack into the instruction pointer and that's where it's going to go so the value that it's going to pop is the following here because this is the sp is a stack pointer so it's going to pop from the stack v triple a okay so let's then use that into a cyclic find here it's going to tell us hey the offset is going to be 84. so okay that's cool we have enumerated that here so the return address offset is 84. cool perfect so now we know that our payload is going to consist of a padding this padding is going to be times any any character times our return address offset following our padding we are going to have our actual return address now our return address is going to be the p64 of our stack address so we're going to pack that integer that we had up here i'm going to pack that again um well actually that's not entirely true yet because we don't we don't have shell code yet because we are still going to have to write our shellcode so our shellcode is going to be something here and we add our shellcode at the end of it so our address that we want to jump to is this shellcode so what we have to do is we have to pack our stack address and that's going to jump at the beginning of this padding so then what we have to do is we have to add the return address offset to this and add another eight bytes to be jumping to this shellcode okay perfect so now we need to generate our shellcode so for that i am simply going to use shellcraft from pawn tools here so shellcraft is amazing there's some documentation up here but it's pretty much just going to use assembly or you don't have to write your own charcoal you can pretty quickly grab it here we are going to take a look at the shell code however let's actually do it right now so for that i'm going to go into debug mode here so context dot log level equals debug okay so then we can exit out of this quit oh okay we've already exited exit out of there then we can run this file and with that mode you see we have a lot of debug statements here and this is where i try to assemble our shell code here so okay our shell code is going to do the following it's going to run bin sh but how is it going to do that well it's going to call this it's going to do a syscall here which is at the bottom and the cisco is interesting because it needs all kinds of certain variables parameters to work correctly and for that if you want to write your shell code manually there's this very cool linux cisco syscall table so this is this is going to specify all the kinds of parameters and arguments you need to supply in order to do this cisco so for example this first value here is the rax so for us we're doing in an exact c an exact ve so the rax needs to be set to 59. now if we look in our shellcode here at the bottom we are um pushing i would expect this to be pushing 59 here um but we are not did i write my shot code correctly shellcraft.sh okay that doesn't seem right for me and actually i know what i forgot i forgot to set the context and this context is gonna make sure that it knows that pawn tools knows what is happening so we're going to set the os to be linux and the arch to be amd 64. and this is all stuff that you can get from running file on that computer i see 50 64 bit here so we we that's the contacts i'm going to set and i think that's going to fix that okay yeah so right now here we see at the end we push 59 to the stack and then we pop our ax here and what does that popping mean that popping means we're going to take whatever we just pushed on the stack so 59 is going to be in rex perfect so then the rdi is going to be the file name of what we are going to execute so let's see what we push in rdi so in here we are moving rsp into rdi rsp is a stack pointer so we're moving a pointer that's on the stack enter into our ai or we're some the stack is pointing to something and we are putting that pointer into rdi what is the stack pointing at well we just pushed rax and in rx we have this hex and this hex is is bin sh so that's how we put the file name on the stack there's some more stuff here that's important for these other variables but i won't go into that um but i hope this kind of explains the basics of this shot code and what is happening here however we are running this and we seem to be getting an error we get an end of file error so let's quickly disable this debug mode again so we don't have a lot of output here and this end of file error happens okay we stop with an exit code of zero let's see what we do wrong here oh okay so we are inputting this here our payload but then it says okay roger that and then it repeats the prompt and this is where he would output three however we know that it hasn't output three it's it has just continued for some weird reason well why is that reason that is probably because my payload is too long if you recall here we were allowed to input 137 bytes into this buffer but my payload might be longer so let's quickly add a search statement here so that we get notified with a something nicer than that error that's clear so the length of our payload smaller than and up here we're going to say okay max payload length was one three seven okay so now we can use that max payload length here and say okay well if it's too long i'm gonna say payload let's make this format string and too long okay so we're gonna show the max and then in here we're just gonna show the length of our payload as well so that we can see what we're working with okay let's run that and see what happens now so it's again a an assertion error and says okay payload of length 140 is too long so we have three bytes too much in our payloads so that's that's a bummer would have been really nicely if it just fits snugly but it doesn't in this case so where are we losing space well we're obviously losing space up here where this padding is is long and it's just using space that could be used for the shell code so let's actually rework this and we're going to say okay our shellcode is going to be at the top so here as well we're going to have our shell codes that also means that our stack address is not going to have to be changed because the stack address points the beginning of that buffer and the shell code is going to be at the beginning however we still need some padding in the middle and now for the length of the padding that's going to be a little different because it has to be this but minus the length of the shell code that's already on the stack okay so does that look right that looks right to me let's see what happens this time okay so we see that we don't get the assertion error anymore so our payload is now long enough but we get an end of file and if we we still get a segmentation fault so something still went wrong and now this is very hard to know what went wrong in this case so i am going to jump into ida and we're going to attach the process so we can see exactly what is going going to go wrong and we can run through it dynamically so in order to do that i'm going to put a statement here just an input statement that's going to stop execution so that we can connect to it in ida so if i run this and say ida okay so now we can connect to it in ida so in ida we can say and i'd have also opened the binary and i've set a debug point at this return statement in the main function so now we can go to debugger not there go to debugger attach to process find our process here which is gonna be bad computer here okay you can open it and now it's gonna attach to this process as to do some moving here and we are gonna be able to pretty much dynamically run through this so currently we are here i'm going to say play i'm going to continue there so all right now we have in ida we have stopped on this return statement can i put this in graph here we've stopped on this return statement here on the stack if you synchronize with it yeah we see here we have our padding here we have our shellcode here so that all looks nicely let's see where we are going to jump to if we go in this return so we step in this return and we immediately get a segmentation fold okay so what does that mean that means that we probably have to take a look at what we were actually jumping into so let's see where are stack addresses stack address is there and that is synchronized with it again that is right here so that is what we were jumping towards now does that look right well from here that might look right but however the stack is kind of strange and then i always advise to look at the stack view here and we can see okay this is backwards so what does that mean well that means that we have our endian wrong like um endian kind of you can have little or big endian and i'm not going to go into explaining that but if you want that i will explain it in another video but we should probably here when we unpack this we should say okay we want the endian to be big now i believe that you can also see that if you run file file oh that's the wrong one okay file bad computer yep there we go okay so we actually can see the endian is here so if it says lsb that means it's the least significant bit um so what does that mean well the ordering here is going to be with the least significant bit first and in this case we put the most significant bits first on the stack so we used little endianness but we wanted to use big endians so if this has msb then then you should use little but uh for this case where we set we want big because this is the least significant bit is going to be first okay so let's rerun that with our correct endiness so we are going to have to connect to ida again stop running this attach to the process all the way at the bottom here bad computer okay right so we're gonna move the segments again and we're gonna have to press play here get that going and then we get back to our return and now if you look at the return address on the stack we notice that okay the least significant bit is first here and then we look in the stack view we notice okay yeah now it is correctly here because this stack view edits it so it's a in the viewable version okay perfect now let's step into this return and we notice that we jump somewhere and this is our shell code if you remember so let's jump through our child code so we're going to jump through it because when we correctly jump to our shell code however our code still gives us as a segmentation fold so what goes wrong well here in green on the stack you can see what we are executing so this is our shellcode and past that is just our stack that we're not executing however pay close attention to this blue character here which is where our stack pointer currently is and as we jump through it notice that with every push it it's gonna it's gonna jump closer to our shellcode and it's very close now and we're gonna do this last push here and that's going to overwrite some of our shell code here so now we've overridden written some of our own shell code by running the shell code and that is if we jump next it's going to give us the segmentation fold okay so that's an issue we need to we need to make some more space on the stack we need to make some more space on the stack so that we don't overwrite our own code now how can we do that well if we saw earlier that pushing removed space from the stack removed eight bytes uh with each push well what if we try to not push but pop so that we create more space so yeah we'll have to add some shell code for that again you don't notice by heart but if you just go onto the documentation for pawn tools and then shellcraft and you do pop you have this pop id here which is just going to pop all the registers on the stack so okay before i shall craft here before or sh we want to do a shellcraft dot pop and this is gonna pop all of the registers we'll add that turn into assembly that's going to be your cell code now so let's hope now that that isn't too much um because if if this pop id is too long then we're going to violate the length again but then we could simply just pop one uh address instead of all of them of pop one register instead of all of them which would also be fine but for this case let's try this first so if we run this now okay we're not connecting to ida now but we see okay we don't get this end of file and in fact we have code execution now so let's uh quickly put this debugger on here so you can see what this pop 80 actually did so okay as you can see this shellcode now contains a lot of pops which is going to make space for us on the stack to get over that issue that we saw earlier where we were overwriting our own shellcode on the stack which is why it couldn't execute so now we have a working thing here but this is working locally now often there is differences or slight changes with with how things work on the remote so let's make sure this also works on the remote server here so we are going to make a remote connection to the hack the box server which is running this binary so if we copy that okay take this and let's see if that works on the remote as well okay so let's also quickly remove that idle line since we don't need that anymore and we see we go into interactive mode here and if we type id we see hey we are root here ls and we can see okay there's flag.txt so we can so we can cat flag.txt and get the flag that way so that was it for this video this was a the second pawn challenge in the intro to binary exploitation series here i want to do all of them if possible um for me as well this is kind of a bit uh still a learning experience because i don't do binary exploitation that often um i'm trying to explain things here and there but if you have anything that you were like okay this you went over quickly i i'd love to see that like kind of featured in the next video say something say hey do that explain that fully in the next video and then i'll make sure that i do um but yeah if you enjoyed this video make sure you leave a like subscribe and i hope to see you back for another video
Info
Channel: PinkDraconian
Views: 3,597
Rating: undefined out of 5
Keywords: ctf, pwn, python, pwntools, 64bi, bit, bytes, byte, stack, overflow, buffer, int, pointer, paint, hack, hacking, hack the box, hackthebox, htb, HTB, bianry, binary, exploitationb, exploitation, binary exploitation, PWN, NX, Shellcode, shellcode, shellcraft, sh, pop, endian, execve
Id: 3Snd6A_duSQ
Channel Id: undefined
Length: 36min 11sec (2171 seconds)
Published: Sat Dec 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.