 Hey folks, Adam DuPay here and in this video we're going to be doing a live hacking of the Ponebles.KR challenge UAF. So looking at this challenge we see it's named UAF, it's 8 points, it says mommy what is use after free bug, SSH UAF at Poneble.KR so we know it's on the site. So this presumably based on the name of the challenge and by this description here it's clearly going to have something to do with use after free which is a type of heat bug. So let's look at the challenge. So we get in here and we can see again we have a UAF binary with set UID group of UAF underscore Pone and see CPP code so here we have C++ code that's interesting and the flag. So let's look at this code. So class human private virtual void give shell, well that sounds interesting that sounds like maybe that's where we want to target protected age name public virtual void introduce my name is name and I am age years old class man subclasses human I guess I should preface this while I'm reading this is I it's been it's been quite a long time since I've had to deal with C++ code so I'm definitely much more of a see guy than a C++ guy so we'll this will be interesting. Alright so the class man which subclasses humans has a public man string name in age sets the name in the age and introduces themselves so that would mean what every human has a function give shell okay we have a man I'm a nice guy we have a woman which introduces themselves and outputs I'm a cute girl why does the guy have to be nice and the girl have to be cute I think that's silly okay so it main we have a human so we're so the important thing so now we know when we're reading this we need to think about we kind of already have a goal state so we need to call this somehow call this give shell function or trick the program to call that and what we have here is we have we have new so we know that because of the name of the function that uac you use uaf use after free is going to have to deal with things on the heap so from what we know so in C malloc and free are the methods that actually will allocate things on to the the stack and then sorry onto the heap so specifically not on the stack so there's a point so an interesting thing to note here so all this data this size length this character pointer data this op all of this is stack allocated data the new keyword in C++ causes this to be allocated on the heap so this is going to go through the heap allocation so it's going to allocate the new man name of Jack age 25 a new woman name of Jill age 21 and is going to so give us a menu so it's going to say use one use two after three free okay so we have so we're just going to keep doing this forever so this is an infinite loop here and it's going to say switch on the operator case the operator is one the man the m variable introduced themselves the w variable introduces themselves and then break so we know that introduce gets called here and so outputs the name and the age and the little something about them based on the inheritance here output to it's it's calling the after okay this is pretty easy okay I think I mean not easy easy but this will be interesting so we know we have to do a use after a free so one uses the variables M and W case 3 is the free so case 3 is actually deleting M and W and an important note is that this doesn't change these pointers so remember looking here so M is actually the type of M is a human pointer so it's a pointer to a human object and we delete M what the heap does is it frees that memory location that is there on the heap and it's going to free that memory but not change the pointer so this pointer this human star M this is actually still pointing to that memory location that's on the heap and then if we look at case 2 so case 2 is going to read a length from our V1 and it's going to create in data so it's going to allocate on the heap a new character array of the size of the length that we want and then it's going to interesting it is going to read it's going to open argv2 read only it's going to read that data okay so what is this doing so basically argv1 is going to be the length of data argv2 is going to be the name of a file that we want to read from and that's going to say your data is allocated otherwise break great okay so the idea is what do we want to do so what we're going to want to do here question is can we actually call this give shell not sure but what we know is this give shell function should exist somewhere in our program and this is when I'm going to probably have to learn about v tables and everything to be able to do this so essentially what we want is what we want to do is have it when we call this M introduce we actually instead of calling the introduce function we want to get it to execute system bin SH so the other thing let's do let's open this up in GDP the other thing I want to find out is I want to figure out what kind of operating system they're running so it's for blah blah blah and actually what I really want to do is figure out what libc version are they using like what's the malloc operator but that's okay we could do this and let's also boot up in our hand dandy hopper let's open this assembly file in hopper so we are at UAF great so what I'm looking for here basically what I'm going to want to do is I'm going to want to look at we go to so what I want to do is I'm going to look at this code here and I want to find out where's the code that's calling this case one where it's going to M introduce and what I'm going to want to do because that's going to dereference the M pointer and then it's going to go to some offset and then it's going to jump there and what we're going to want to do is within our input we want to create something that at that offset will have a pointer to go to this system bin SH so here we can see it's actually pretty easy they at least the binary here I haven't like I said I haven't spent actually any time really looking at C++ assembly code so this will be definitely a bit of a first for me so we can actually out there we go we can we already found it here so it's dereference dereference variable 38 which is probably the m variable plus 8 so go 8 from that dereference that and then essentially call that as a function so let's look for that actual code so this would be you know change it into this mode so this should be able to tell so this is compare if it's 3 if it's oh interesting it it does this that's interesting that's calling the destructor function interesting okay compare it to one here's the code we want so this is so I'm going to rename this to M to know that that's our M variable and I'll rename this to W I don't really care about W really at all because we should get that get to that function here so let's walk through what this does so it takes M so remember M is a local variable that's on the stack that is let's see if this will tell me exactly where it is it's at well I can find it out it's some offset of EVP or RBP in this case since we're 64 bit so it's going to move that into RAX it's going to dereference that pointer so now it's going to point to memory that we control it's going to move whatever's in whatever's at that current location into RAX it's going to add 8 to that so it's going to move 8 bytes down it's then going to dereference that move it into RDX and we can see here it's going to then call RDX so here it's setting up the parameter that it's passing to RDX but it's going to jump to this function so we want the variable that's going to be in this call RDX register we're going to want this to be that system and we can actually easily find where this is so we can go to system we can do a cross reference and we can see here is the function for human give shell so if we get here then we will and we can make this nicer by telling hopper that all of these things are strings I think there we go alright great let's save this UAF hop okay great so we know that this give shell so essentially when we think of it this is the address so this is our target address so what I'm going to do we're going to start creating an exploit for this and again we're going to use Pwn tools and again I'm going to steal some exploit that I've already written and this should be process and you know what we'll do we'll actually rather than specifying it we will do sys.rdv1 and so this is what we want to jump to right this is 0x so if we can get so think about it this way if we can get the control flow to execute here we will call system bin sh which is exactly what we want and we know so basically what we know is that going back to this code what we know is we can actually completely control the heap so we can make it so that the heap value so I guess it is a question of whether we'll be in the first whether the pointer that we'll have will be the first one or the second one but we can actually debug that and test that fairly easily so we're going to delete W, delete M this new allocation the other thing we need to do is we need to figure out what's the doing to that the size of W and M maybe I think we may be able to just do this by giving it input of let's say we need 8 bytes off the start so 8 bytes and then another 8 bytes with this pointer that we want it should be yeah we're 64 bits so it should be 8 bytes here that's the pointer that we want and that's what we'll end up jumping to I wonder if that would work let's see all right let's see that the input here is interesting because it's going to read from a file so we'll actually need to in our exploit create a file in maybe slash temp or something like that but let's what we want to do so we already know what we want to do where what our target is so we know where we want to go let's look at main and let's look at yeah so W's at minus 48 and M's at minus 56 so let's see it is going to allocate it's going to call Jill let's see man this code when you look at it it's pretty complicated okay so new man Jack so where is we want to know where is M used because that's the thing we're going to want to so move RBX into so RBX okay so this call this function call looks like the constructor yes we can see man man string it says the constructor that's getting called so that constructors getting called and then the constructor for woman is going to get called so at this point the stack should have so if we break point here the stack should have for M and W the pointers that we want or the should have for M and W the values the stack values that we want so let's break on this value let's run it and let's see I don't know exactly what I want to put in so and we'll just do dev I guess I can use dev standard in use the proc files system proc self fd0 so read 10 bytes actually I want 16 let's just try that again that'll read 16 bytes from standard input okay so now we're here so we can actually look so we're seeing some of the stack here but we're not seeing necessarily enough what we want to see from the stack is we want to see from ebp or RBP minus 56 so and it needs to be like really wide hex because we're using 64 bits so pointers are now 64 bits so actually don't remember the syntax to do that but we will find it out okay so let's see RBP minus 56 okay that's not I want I just keep putting W's no apparently not gdb output 64 bit format okay so while this is going debugging with gdb output formats yeah there we go yes that is what I want but I want also Matt yeah a G that's what it is giant 20 giant numbers in hex so why did I do minus 46 I think that's because that was wrong we want 56 all right so this pointer so now my pointers here so I have a 614C50 that would be M and 614CA0 this is going to be 48 and so what this is going to do is it is going to yeah so so these are the pointers that I care about so these are pointers onto the heap and if we look at this we'll see that at plus at this memory reference so we dereference it and then what did that code do let's look at the code because I want to see where it actually calls on one I was looking at that that was right here okay so it takes this it dereferences that it dereferences it again so there's a pointer in there then there's a pointer into here interesting okay so it's going to take that it's going to dereference our pointer into rax it's going to dereference it again so our input okay so this is when we need to make nice diagrams for what we want to happen so the current thing is so in the variable M there is a pointer onto the heap and at that memory address we will then dereference that so that would be this nice person 20 gx there we go and that ah so that's going to be the virtual table for what we want oh okay this is actually I think easier than we think because it's going to take that and then it's going to add eight so that's going to be here so this is going to be this table I believe these are all pointers to all of the functions in man human so this is the virtual table of where it figures out who to call what so I believe these are all at fixed locations in the memory and I think we could find these in hopper if we wanted to so we go here and it's not going to take this first element it's going to add eight to it so it's actually going to take this next element and that is going to jump where it wants to go so actually all we need to do is put eight bytes in here and we need to have that value so we want M because we're going to be overriding I think where M is going to be but this value we want to put in here so this is actually a pointer to let's see plus eight so if we do X 20 bang yeah this is introduced so this is int what we want to have happen so this is essentially going to all go away so this is going to be freed and we will be able to overwrite this value so the goal is to overwrite this value to a chunk of money so actually our our destination was not correct we want to overwrite this value so it points to some memory that has already the value that we want into what do we call that guy has a name into give shell I'm gonna call it GS so give shell so that's where we want to change this to and so the way we can do this we can do this pretty let's see easily so we know we want this and we can look at where here it is so we can actually see at so at this memory address so at yes okay but we want minus eight so at this memory address 401588 401588 so at here plus eight so if we put this value into here we will now be pointing to a memory region that 8 bytes offset is the give shell function so that's what our target is so let's continue oh the other place I want to put a break point okay so this is actually the target we want to jump to this to do that we need where m or w points to to be that location all right awesome so now what I want to do is I want to debug that I want to set a break point on the hopper I want to set a break point on the free so I want to see what happens on the free to show you that the stack variables are not going to change and then I want to set a break point on the read because that's I think going to be pretty interesting so this is the delete so that is interesting it's calling the delete okay so this should be the delete right here right after delete and let's go to here yes that break point and then the other break point I want is on after ah here we go so this is all this pointer fun stuff see what's the C code of this thing like length data see out your dad is allocated okay great so right before the see out call I think it's gonna be right here is what we want I don't want that I want here to get this address okay alright and continue so now we have the menu so we saw we've already allocated those so we can use them and we can see it says my name is Jack I'm a 25 year old guy I'm a nice guy we have my name is Jill I'm a 21 year old I'm a cute girl then we're going to call the free to get rid of them and we should be able to see at there we go so at RVP minus 56 we have the two values here and if we inspect 5gx at that memory location so right now there's nothing there right so that data has actually been cleared that's interesting but but we still have this pointer here so let's continue and now we'll call after use yes after and now it's waiting for input from us because remember we gave it 16 bytes so it's going to look for 16 bytes and let's see print 8 times 16 okay so and because we passed in the parameter slash what was it we did slash proc self fd0 so it's actually going to read from standard input rather than a file so now it should have just copied 16 a's on there and let's do why did it continue let's let's just break it now and let's go up up up up up up okay we're in main now and let's look at the RVP there we go cool so we still have these pointers here hanging around and if we look at this pointer we okay so here is where our values are so well then what's W RVP so that's why you always want to debug things because you never know how it's going to go okay so the woman the problem is going to be that the problem is going to be that if the let's see the let's see what where are these laid out on the stack so M is the one we were using in W the problem is M is being dereferenced first so we'll get a null pointer exception because we're trying to dereference this null parameter so let's continue it's waiting for input from me I want standard input don't to I want to use so yeah it should blow up because it should say that rax print this x rax p slash x is 8 so it's the value 8 so it's a segmentation fault here why did that actually work p slash x x 20 x yeah okay so it should take this so it should take that minus 38 it should oh right because that is an average address and then it should add oh it adds it do you it takes that puts that in there it then dereferences this and puts that in there but with this yeah it should be there not exactly sure why this didn't blow up I've got to debug this a little bit more okay so it's interesting so there's a slight wrinkle from our plan oh okay so deep so it moved that into there so dereference it one time okay I'm getting okay so it dereferences ah so it's moves that value into rax here it dereferences this to get this value here it adds 8 to it okay so this actually then we'll need to change our exploit so because the success that we wanted to go to was in I need a calculator guys give me a calculator should be very easy okay oh yeah this is what we want because plus 8 from this is 401 1 1 590 is that correct let's see x 20 g no this is the value that we want so we want this minus 8 because it's going to do 8 it's going to do an arithmetic operation so rather than get the thing that's after it I believe where are we all right we're gonna have to debug this a bit let us do here okay so we know we can control w the problem is so what if we allocate more memory so what if I allocate so what's the size of these objects so we should be able to find out by looking in here and go into the let's see where's the allocator I wonder if we could just do it by running maybe L trace you a f so it's calling start this after free z string traits basic man this is super annoying oh I'm gonna guess it's 24 I'm gonna guess that this function is the allocator maybe yeah c15 yeah because it's giving different values every time because of the SLR changing of the heap so I think what we want to do let's restart this now we want 24 bytes which should have the allocator then should put us right back in the same position that we were in or maybe yeah let's try this and then we will continue let's look at the stack RBP minus 38 so we can see that remember when you're executing things in GDB GDB disables ASLR by default so these memory locations are fixed so then let's all right so let's continue here we will use to show that we can do that we will free and show that we're still here we still have these memory addresses we will continue we will call after so now it's waiting for bytes from us and last time so the problem was I gave 16 and then an enter which means when it hit that breakpoint it hit enter to continue and so since I asked for 24 I'm gonna do 23 a's and then my new line character should count as an a there we go so now we'll actually stay and now what we can do here is examine the heap and say okay x 20 gx what does this heap look like okay so it's definitely putting our data inside the other heap address and I'm sure this would make sense if you looked at it about why it would do this so now the interesting thing would be what happens if I ask for 48 ideally the allocator should say hey yes look I have a ton of space this should definitely work so we'll see if that's the case let's free it let's look at our heap same values good and we'll call after and now I need 47 a's so many a's all right and now look at these values and now show me 50 so I did not get any of that interesting oh I know what I can do I know what I can do so so I think it's probably doing it let's look at the sorry if we look at the code here we would see that your data is allocated so we can keep calling this so we can allocate yeah this is great so now we can allocate 24 bytes and basically just completely overwrite what we want so we'll do this three times so let's restart with our 24 because we want to completely control and make sure we get in the proper spaces so it's going to do everything else let's free everything let's continue we'll call after once so now I need 24 I need 23 plus an and bang we get there your data is allocated now let's do it one more time and let's do we have this and then a new line and now let's examine the stack make sure these numbers are the same and let's get c 50 so now we can see that our data got allocated exactly where we wanted so we're able to overwrite and control both things so the idea is because the heap is allocating space on the on the heap for 24 bytes and then 24 bytes and then when it frees it it says hey these member regions are free so if we then reallocate and say hey we want one byte and one byte or we want 24 bytes and 24 bytes it'll actually put it in exactly the same spot so this is great so I think here we definitely have an exploit so what do we want to do we want to go to let's see okay at least we can set up now the what we want to actually be our thing okay so we actually want connection process how do I pass in argv's to connection process I can look for pwn tools and look at process and it will definitely tell me tubes gotta process the tubes all right process ah there's nice and argv list there's an example process oh you can just pass in arguments here great okay so plus space always on reading 24 bytes from proc self fd0 so this will actually give us the ability to if we wanted to now we could change what values we actually write in which is pretty cool I don't think we necessarily need that but hey it is pretty cool oh you know what let's do it like this this will be a little bit nicer 24 that bang now we got a connection connection all right so let's play this game uaf 24 there we go and it's connection dot till 3.3 it's always just good to get into the habit of making sure that you're synced up in what you're sending and what you're receiving so we wait until free we con dot send line we are going to send a free and then receive until we get the free so great it'll tell us that hey we so we will do three enter it will give us this thing it will then we want to say two two and then now send our payload and then after we send our payloads right now we'll just do send a let's say pay p or for our payload is going to be equal to a times 24 so we want 24 a's we're going to send p that will send all of that and then we will so now we should receive until free again connection send line 2 so now we want to we're going to allocate another 24 bytes onto the heap we're going to send p and then we're going to call let's see we want to receive until send line use and after that let's turn this baby into interactive and we should be good okay now the trick is going to be setting up this payload so right now this should crash the program so now got into file in interactive mode because it should tell us that yep ended with a six so we were able to send we sent 24 bytes so at least our interactions now are all good and what we want now is what value to write in so let's go back and review that line the the overwrite so we can know we kind of know what we want but let's make sure we got that so this is the value so then here this is the value then that we control so it's going to take in the value that we control it's going to add eight to it and then it's going to dereference that and then jump to it okay so this is where understanding your point is is really important okay so it's going to take this value so it's actually going to add eight to it and jump there okay so i think we actually have had the right value in here so what if we send let's see p 32 p 64 so this will turn this value into the proper end in this 64 bits and we want 24 divided by 8 i will send that that many times rather than me having to do math hey why should i do that oh there we go that worked awesome all right man it's always super good so was so yeah so that's because we know that at this memory location so if we go into hopper and hopper is here and we look at this code and we navigate go to address we're going to go to this address let's see these are all function pointers i wonder if there's a way there's probably a way i can tell it that but i can look at it in in the debugger that will be nicer so x 20 wide gx bang so what that's going to do is add eight to this value that's in there is going to jump to that it's going to execute that so now all we got to do is take our exploit and make sure any temp out of d uaf python exploit and we want home uaf uaf is going on is it just slow is it going i mean the output that i need is pretty easy so i can actually just do let's see where was my local copy so what is it sending and that is crazy why that's not let's print our payload representation of our payload this will actually there we go so now we can tell python to output this to a file so let's do python dash c print this nice perk thing and then now we can we should be able to just do home uaf uaf uh with 24 and uh so free after after use interesting okay cat uh let's run id cat home uaf uh flag there we go you're a flag after poning this is interesting i don't know why pwn tools wasn't working there in sending the data to and from uh but uh you know that's all right we got the solution um and so that's all that matters so we will log in so that was actually really fun i i it's been a while since i've done heap style vulnerabilities and it's definitely been probably many many years before i've actually looked at uh c plus plus code and looked at how the object orientation is actually implemented in c plus plus so uh i really enjoyed that level i thought that was super interesting and was a really fun level to do so uh thanks everyone hope you enjoyed the video keep hacking