 Hey folks, Adam DuPay here, and today we're really looking at the ponable.kr level unlink. So I'm super stoked. This is the last of the toddler battle challenges, and this is a live walkthrough, so I haven't, or live hacking, so I haven't seen this challenge at all. So it's always gotta read the hint. Daddy, how can I exploit unlink corruption? So when we go in here and we go to the thing, we can see that there's an unlink binary that set UID on the group of unlink underscore PON, which is how we can get the flag. So again, as always, we can't just cat out the flag. But the other interesting thing here is we do have the C file, so we'll be able to see the C code to this, which will make our jobs a little bit easier. Other interesting thing is there's an intended solution.txt here, so there must be multiple ways to break this, and so the authors felt like they had to put the actual intended solution here so that people could understand it. So I have copied everything locally, and let's get, not what I wanted, started, all right, new frame. So we're gonna open up the binary in our classic hopper, probable.kr, unlink, unlink, all right. So it's gonna analyze that, and then at the same time, I'm gonna open up in here. Okay, so, you know, since we have the C file, we might as well look through the C code, like why waste our time looking at the disassembler? Okay, ah, this is what I thought. So based on the name here, unlink, the idea is this is probably gonna be a heap style vulnerability. So here we have the inclusions, we have a tag object, interesting. Oh, okay, so it's actually not using heap operations. It is, oh, interesting, okay. So there's already a target function that is put in here, the shell of system bin SH. So here's basically where we'll eventually want to get to. So what they've done here, the idea here is they're recreating, rather than using malloc, so you'll get this unlink corruption if you have a double free vulnerability in your program. And so what they're doing here is they're creating that by creating this unlink function, which is one of the main ways that you can do a heap overflow, exploit a heap overflow vulnerability. The idea is the heap is basically a series of, a linked list of various chunks of memory. So you can see they've created this structure called the tag object, which has a forward pointer to the pointer in front of it and a back pointer to the pointer behind it, and then a character buffer of eight characters. So here we can see that unlink takes in a P and basically gets, so sets the back to be P colon back, gets the front pointer to P, sorry, not colon arrow file descriptor. So dereference that and access the file descriptor and then sets the back equal to BK and sets BK FD equal to FD. So the idea here is that we can actually, so here we're malloc-ing first 120, 1024, and then we malloc A, B, and C, so these will be malloc-ed on the heap. And the idea is these will be a linked list from A to B to C where we have, yeah, so we have A's forward pointer points to B, B's back pointer points to A, B's forward pointer points to C, and C's back pointer points to B. And this is nice, it's actually telling us an address on the stack and a heap leak so that that way it can tell us where these things are being allocated at. And then now that we have that, basically with this gets command, so when we look at the man page here, gets is one of those functions that is always vulnerable. Any time you see a use of a gets, this means that you can overflow as long as you can control that character pointer that's passed in there, or that, not even that's passed in there because the idea is you're reading from standard in until you get to either a new line or end of file. And so the idea here is there's no check for buffer overrun, which it's saying C bugs below, which is terrible, it should be don't ever use this function. Oh, and which we can see here in the description of never use this function. The idea is this is inherently unsafe because you cannot specify how many characters you want. So any use of gets is unsafe. So we can read into A, and then we're going to unlink B, which will then, and we're going to read into A buff. So we're actually, even though you can see object pointer A, B, and C are all malloc from the stack, these will point two values located into the heap. And so when we will be getting into A buffer, so we'll be able to overflow that buffer, and then we'll pass that to the unlink function here of B, which means we need to control exactly this unlink buffer. So now the question is, how is this thing compiled? Because we want to see, so we have our run file on unlink. We can see it's a set group ID, L32 bit executable. It's dynamically linked, which is not great because when we run this exploit it's our version of libc and our moon 2604, it may be slightly different. But we can run unlink here and we can see that it's giving us a stack address and a heap address and basically telling us, hey, now that you have that, get a shell. So let's just say hello, and so it should execute just fine. And now if we say hello, so how much is it alloc-ing? It's malloc-ing a size of the object. So this object is gonna be four, four, and then eight. So let's just put a bunch of hellos in here. So now we get a segfault and we should be segfaulting. Well, let's run open up gdb. So let's try to first, before we do that, do read elf on this binary. It's an S, or is it lowercase a to do all? I can never remember all these. There we go, lowercase a to give me everything. And of course, I wanna pipe that through less. So we can see a little bit more about this. It's, so it's got a global offset table, it's got a tech segment, the other thing. Okay, yeah, so we can see printf gets malloc put system. These are all inside the GOT table. See, I'm really just scanning through here, seeing if there's anything mildly interesting. We can see our shell function. So this actually, I mean, we know this is gonna be at a fixed location, so that's what we'll want to try to change our offset to. So we have a couple of really fun opportunities here. So let's GDB this guy, and I'm gonna run checksack on it, just to be, so checksack is gonna tell me that there's no canary. Yes, the stack, it's a non-executable stack, which is nice. It's not position-independent, and it's partial relocation, so, and no stack canaries. So if I run this, and then I now, I'm going to copy over a bunch of my hellos that I have. Now we've got a segfault, and we can see where we segfaulting at. So we're segfaulting, so it's saying that it's got a segfault because EAX plus four, so, so info registers EAX. So EAX is 6F, 6C, 6C, 65, which is probably some version of hello, and it's trying to change that. So what it's doing on link, okay, so what it's doing here is it's going to be this line, I believe, at setting the back pointer. So let's see, where are we? AIP, let's look at the stack. Okay, so we're at this place. So we're right before the end, moving that dereference, moving it into EDX, and so, let's see, what are we trying to do here? All right, okay, so we have our unlink function here, and it's actually very short. We can see that, look at that with the C code here of the unlink function. So we'll walk through this and just briefly go over which one's map where. So here we have pushEBP, so this is all prologue of the function. Then we're moving EBP plus underscore, underscore name into EAX, and then moving EAX plus four, dereferencing that into EAX. So EBP plus name, this must be the parameter P. So this is getting P and P plus four is going to be P back because back is that four offset of in this struct, so it's moving that into EAX, and then it's moving EAX onto the stack and local variable. So this is the BK variable, and then getting, it's called name, but we'll call it P because that's what the function originally has. And then it's taking P plus dereferencing it, and then dereferencing it again, so that's getting this file descriptor of this struct, and it's moving that here. So this is going to be FD, and then it's moving EBP plus FD into EAX. So it's dereferencing it, and then moving EBP. So is this the one that we, so here we have unlink. So this is EDX, actually I have the addresses here, 48, 521, 48, 521. So this is where it ends up crashing. So mark this, leave a comment. Great, so then we're taking EAX, so we gotta look back at what we're doing. So we've done these two lines, we're dereferencing P, getting the back element storing it in a local variable, dereferencing P again, getting the forward element storing it there, and then we're assigning FD arrow back equals to BK. So we're writing whatever is inside P back into wherever FD is looking into. So this is going to be FD EBP into EAX. So get the file descriptor moving into EAX, get the pointer that BK points to, but in the EDX and now dereference EAX plus four, move EDX what was in BK, so the back of P and move it into ED. So actually maybe it'll help to draw a little diagram very quickly of what's going on. So if we draw what's going on here, we have to remember at each of these, so I don't have my notepad, so I'm drawing with my awesome mouse. So we basically have these three objects, and each of them the first four bytes is gonna be a forward pointer, and the next four bytes is gonna be the back pointer, and forward back and then buffer. So this is same thing, forward, back, buff, and it really helps to draw these things out to understand what's going on. So A's forward is going to be B, so A forward is a pointer here, A doesn't have a back, so there's no back, and then B's back pointer points, sorry, this is the forward pointer, so B's back pointer points to A, which we're gonna point here, and the forward, and B's forward pointer points to C, and then C's back pointer points to B. So this is your standard, your standard linked list here, so if you don't know doubly linked lists, you should go study them, they're very basic data structure in programming, especially in C and C++. So the idea here is we're freeing B, we're gonna unlink B, which means we need to remove it from this linked list by fixing up the forward pointer of B's previous and the previous pointer for B's next. So the idea is we want the final diagram to look like this, and this is just going through what's the basic underlying logic behind this unlink function, so it's not just like this random black box that you're looking at. So eventually we're gonna have A's forward pointer BC, and we want C's back pointer to be A. So that way there's no more reference to B, B is essentially gone. And so we can see that the way that this happens in the code here is we create a local variable, we store this, so in this case the B block is P, so we get P's back pointer and store that as back, we get P's forward pointer, store that as forward, and then we set the forward's back pointer to be back, so that's making changing this value here to be this arrow back to A, and then the back pointer's forward to be where we point to. So this changes their pointer to point to here. Okay, so this is what normally happens, and when we think about in our diagram here, where are we actually going to get to write? So we get to overwrite here at A's buffer, and as we'll look at when we look at these variables on the stack is this will overwrite this buffer, but it will also let us overwrite this other metadata inside B. So now once we can control the values here, we can control what gets written where, and this allows us to then overwrite any four bytes in the program of our choosing because we'll get to overwrite them with whatever's in here by using these pointers here. So essentially that's what's gonna happen. So then let's look at, we'll use our handy dandy. I'm slightly worried that using our local version of GDB will be different than what they're running on their version, so we can maybe do some sanity checks, but what we can do is we can break on main, we can restart, we can call our, we know we're doing three mallocs, and now if I print out the stack, 20x, let's sign ESP, x20x, I thought I did that, right, okay. There we go, okay. So now we have, we should have on our stack, I guess we can figure out where exactly that is because we haven't looked at main yet. So we're mallocing, doing all this fun mallocing and we're moving it at EBP. So let's do EBP minus x20, or let's see, C, this is, so it's calling malloc first with, that's that first one of 1024, this is one malloc and then two mallocs, three mallocs, interesting, EBP minus, okay, minus 10 EBP, yeah, minus 10, minus C, minus 14, let's see. So these should be, and then what is it printing out to us? It's printing out the stack address is the address of A and the heap address is what's in A, okay. So I guess I can wait until I see that, or I can break on the unlink and continue a test. Okay, so then this actually tells me interesting information because it's saying that, like this bigger, so it's saying that at that memory location that I had, I need to get better at figuring out how to scroll on these things, okay. The stack address is this and the heap address is that 804. So I'm gonna keep this here in my scratch buffer just to see that, they just want to go here, okay, great. So then I can put that with what I'm looking at here so I know that at, if I don't know why that's doing that, but there we go. All right, so now that I know that I want to, FFFD1F4, D1F4, so here is A, B, C on the stack. Awesome, A, B, and C. So then we can see that they're at, so that's A, B, and C. And we should be able to notice that they are all at different areas of the stack. So let's check this out, okay, cool. So what we wanna know is basically this, I wanna know what's the delta between that, and so of course it's a negative number which is impossible, two's compliment, one. That's useless. All right, of course you have to get your signed arithmetic correct, which as everyone knows is super easy, okay. So those are 30, but obviously the order is a little weird, so let's do, yeah, okay. So this is A, and the difference between A and B is going to be, I think I already know the answer. Okay, 18, which is 24, yeah. Okay, so 24, so the question, and then it should be 24 bytes between this and 40. So let's check that, this minus this fun guy here, yeah, of course, it's always been my weak side. All right, another 24 bytes, good, this makes sense. Okay, the question is why is it 24 bytes? Because we look at the C code and we can see that, unlinked.c, we can see that if we ask the compiler what's the size of a tag object, they would say, well, it's eight bytes for this, and a pointer is four bytes and four bytes. So we'd have four plus four plus eight, which is gonna give us 16 bytes. But so when we ask these malloc commands, and we can actually see that in the code here, we can say we call malloc and we are pushing hex 10, which is 16, so we're telling the libc that we want to malloc 16 bytes, but it's actually giving us pointers that are 24 bytes apart. And the reason is because of how malloc works, and because malloc itself actually needs to keep track of these forward and backwards pointers, as probably I'm sure as this continues, we'll dig into the heap and all the stuff that's happening on there. But for now, all that we need to know is that there's 24 bytes there. So we can, should be able to check how exactly how many bytes we need to calculate this offset. So we basically, we know right now that, we know the distance between this pointer and this pointer between A and B is 24 bytes. And so we know we get to start writing in here, which is eight bytes. So we have eight bytes. So we know we have a total, so we know we have four or four, so we're eight bytes into it. So we basically need 24 minus eight, so 16 bytes. So eight bytes should get us to the end of here. Let me write this down. It's always a bummer not to have this. Bites for buff in A, then eight more bytes. This is the metadata from the heap. Then next four bytes are Bs. Forward pointer, then next four bytes. Bites are Bs, back, BK pointer. Okay, cool. All right, so we should be able to verify this by saying if we just pass in 16 bytes, so let's, we'll do this in a different window here. We can run unlinked and we can do like doing good old fashioned IPython and then print A times 16. So this can make sure that I'm copying exactly how many bytes I think I am and that should not crash it at all. But now that I have that and then the next bytes are gonna be one, two, three, four. This is gonna be the forward pointer. That will then crash it, the program. And if I go try that input on NGDB, we can see that it's gonna crash by accessing that. So, and it may be because I overwrote the zero pointer, but let's see. All right, rerun. Okay, so it's stopped because of the break point. Now it's stopped because of the seg fault. And we can see that Eax is 62, 62, 62, 62. The four B's that we had. So it's trying to overwrite 62, 62, 62, 62 plus four with EDX and EDX is actually 0804B4. So if we redo this one more time and go back here, we have this B. So basically the BBBB is what we're gonna overwrite and then CCCC is gonna be, well, as we'll see in a second. So continue this seg fault, so at the same place. So here at Eax, I'm trying to write at 62, 62, 62, 62 plus four. I'm trying to write EDX, which is actually my forward pointer, 63, 63, 63, 63, 63. Okay, so what am I doing now? Now I basically have whatever I put in for my A's here. Sorry, my four A's, I should have done something different. Whatever I put in for my four A's there, that's the address that is going to get overflowed. And then my four B's here, this is going to be what I'm going to write. The tricky part that you do have to watch out with this is that the unlinking is gonna happen both ways. So you're gonna be overriding various offsets of these forward and backward pointers. So we'll have to be careful about that and we'll have to see kind of how this goes. But let's just dive right in and see if we can do it. So now that we know how we can overwrite because we already have input then to overwrite, the question is what do we want to overwrite? So we already know we have this beautiful unlink function that's already created this, sorry, the shell function that's already created for us. So if we can get somebody to jump to this awesome 080484EB, then that would be great. The question is, okay, so then the idea is where do we, what do we overwrite? So this is our target, is this, all right. Okay, so I've been thinking for a bit and I realized it is gonna cause a problem in the fact that we are, so basically what I wanna do is overwrite something either. So because I know this pointer on the stack, I can completely break the layout of the stack and know exactly where saveDIP for main is so we can get it to jump there. We could also calculate the saveDIP of unlink. The core problem though is that the value that I want to write is this 080484EB, this is going to be not writable memory because it's gonna be in the text segment. So if we look at info, restart, info mem, ah, I don't remember how to do it. Okay, so the, oh, we can just go and there we go. So the text segment is 080483F0, 282, 080484EB, I mean it's definitely within there. So, and that's where we wanna go. So if we try writing that, so actually, I mean we can demonstrate that this is not going to work properly if we, let's see how I wanna do this, gdb run, oh, there we go, the input to that. Let's see, standard input, I can't remember how to do it, the results from a file, I think it's like this. Okay, that's not it. I'll just do it really quickly. Okay, so Python, hc, so we wanna print A times, times eight plus B times eight plus. So let's say I just wanted to like, I don't know, overwrite this, so slash xEB slash x84 slash x04, slash x08 times two, because I want two of these. So now when I run that and go output continue, continue and we can see that I got a seg fault because I'm trying to overwrite at EAX0x4, which is this memory address. So even if, let's say, what I want to do, so if we look at unlink, I mean, there's a lot of targets that I can do. I can overwrite the, I can overwrite the, let's say Finney at register, where actually is that? Is it at 0804, 8674? But the problem is, even if I do that, I thought these were just the symbol table, SIMTAP contains 75 entries. Yeah, so for instance, okay, interesting, these are all the symbols. Yeah, so the Finney is the list of all of the functions that should be executed after the program terminates. I believe it's used by libc, and so what we could do, basically, if we can write to the Finney and write out this shell function call, it will start executing there. But the problem is it's a two-way write, so the thing that we overwrite, we're gonna have to be okay with writing to it. So that's where I'm kind of stuck right now in figuring out, actually what? So Finney, no, because this is not writable, but the Finney array is writable. So for instance, let's see, dynamic data, it's writable but not exploitable. So I could make it do this, right? So this is the Finney array. So I should be able to write to those addresses. So I should be able to write to 08049F, 9F0C. I did get a segfault, okay, cool. And why is that? Continue, continue, segfault. So Eax is this value. Why does that not work? If Eax is equal to four. I'm not examining this, what's going on? Yeah, so what can I write to that? 0484A0, hopper, where's my hopper? All right, there we go. Know this, I know it's crashing here. Eax, I should have just be able to set this. Maybe not, can't remember how to do that with debugging. Brickpoint, segfault, okay. Eax is that same value I know because I put it in there. And I get a segfault when trying to move that into Eax plus four. I mean, I can examine that, why can't I? Yes, the great Google has all the answers, GDB, oh. Okay, so I need to figure out why that's not working. The other thing I need to do is to figure out, okay, so that, there we go. That show, man. Info proc mappings, that's what I want. Sorry, okay. So I have, where's my pointer at? My pointer is at 08049F0C, 0804, but it doesn't have the permissions, maintenance info sections. Yeah, okay, cool. That's nice. 08049F0C, 08049F0C, yeah. Alloc load data has contents, to F10. Like why would that load data has contents? Hmm, I don't understand it, but let's, and we can do C minus four, eight. So we can do 0808 plus, 0X08, 0X, oh no, I want OC, 0X9F, 0X04, 0X08. Okay, restart, continue, continue segfault. Now moving EDX, which is 08049F0C into, so now I did bypass that other line, into EAX plus four, why does that fail? Still doesn't make any sense, but this one did work. No, there's just on the same line, dereference EAX plus, take EDX. Yeah, 080484A0, why? Got to get to the bottom of this, okay. Breakpoint one, two, should be breakpoint three. All right, so now EDX should be this. So we want to move that value into EAX. So this is EAX, so examine 20X plus four, which is that thing exactly, not above Googling, folks. Got to, there we go, cool. Set int 67, segfaults plus four. I don't like this, let's see, okay, now. I guess the question is, is this my version of what's going on, or maybe there's something else on the real machine, or maybe there's something else on the real machine that would be different in a good way. So let's make a directory, tab, AdamD, AdamD unlink, coma unlink, unlink, pass. All right, let's GDB this, EDX, and we print out P20I dot sign EIP. Of course, I want to examine. Yeah, we move EDX into EAX plus four, dereference. Oh man, okay. Well, that is what I wanted to target. Apparently I can't write to that. I'm not sure why I'm clearly doing something wrong. Okay, so I'm gonna pause it and do some digging. Okay, I'm back, so as much fun as I know it is to sit there watching me, thinking off into the distance which I had to do for about a half hour, 45 minutes, and do a bunch of reading to figure out what I was missing here, and trying some experiments out. So one thing you can see maybe here that I just tried out was, because I was thinking the key problem is I can over, so I know the location of the stack and the location of the heap, but I can over with this unlink function, I can overwrite something, but the thing that I overwrite that with has to be writable the other way too, which is the thing that makes this so difficult is that we can't just overwrite, let's say, the finny array with the address of shell because we can't write to the address of cell plus four because the address of cell is in the .tech segment. I was floating around trying to experiment with other ideas like what if I, because I do have a stack pointer leaked, or I do have a stack pointer leaked on the stack, so I know the location of everything on the stack. So I thought, well, maybe what if I changed the saved EIP on the stack to then go to my shell code because I, sorry, to go to my buffer that's on the heap because I do could put shell code on there, but of course, as I know, already new from looking at the permissions there, the heap is not executable. So the fact that this is not a non-x stack doesn't make this a little bit more difficult, which also makes it more interesting, but I've come up with a new hypothesis that I'm gonna try out, and I think this is promising, so that's why I decided to turn on the cameras. So basically the idea is I thought, well, what are the other things I could overwrite with the stack? And I know that I'm in here in this unlink function, and I know that right below the stack pointer, so there's the saved EIP on the stack, we know there's the saved base pointer for the previous function frame, which means that this unlink function, if I overwrite the saved base pointer in unlink, when unlink calls leave, the leave instruction, it will set up the base pointer for main to point wherever I want, and since I know what's in the stack and what's on the heap, that I will be able to essentially change the stack, so the base pointer of the stack, to be on the heap, which I control, which means I can put the return address of main, basically essentially create a whole new function frame for main, and have that base pointer be, have the saved EIP of that frame be on shell. So this is gonna be pretty complicated, but it's actually pretty exciting. So let's start writing the exploit. So this was just an idea I just had two minutes ago before I started recording, and so I thought it'd be good to start trying that. So, okay, good. So process, that's what it's doing 24. But I can't remember what all these arguments are about. I think that's just what I want is to do that, and so I want to start executing this, and I want to extract the stack address and this heap address from my connection, and I can't remember, I'm gonna have to look up PwnTools, PwnTools and see where they had to capture values, documentation, so the docs here are pretty good, as we know, we've gone through them a whole times. Receive, I think, tubes, there we go, and then let's see, receive, return when a regex matches the string in the buffer. I think that's what I want is receive regex. That's weird, this highlighting is done by here, which is super annoying, so. Okay, so we have receive, why is that not, because of course, why would it have an underscore? Receive until the delimiter is found and will it return receive until, or receive repeat, receive regex, yeah, okay. All right, it's been too long since I did the last one of these, so I don't know exactly what's going on, but I think I should be able to do A through F, zero through nine plus. I need a heap line, this here is heap address leak. Okay, now receive that until now you've got leaks get shell. Cool, okay, so then we're going to extract from this stack link and the heap link, re.match, my ipython, import re, re.match, it applied the pattern to start the training, returning a match object, okay, and the pattern I want is, maybe I want find, okay, here is, let's do that on, we already have an execution of this, we can go here, we go here, we can call this stack link and assume that that's what this is going to return, like it's technically that I think should have the new line and then we go back and we copy this in just to see what this object looks like, so it's a match object and I don't remember how to interact with that, but I have this nice help function which write group match should be group zero, wait, group one, why did that match just four? Well, because I need that inside, there we go, all right, see, this is why you test things as you develop them, of course, I guess I don't need that in here, but I'm going to fix it for this guy as well, all right, match.group one and then I think we should be able to say int this 16 to say interpret this number as base 16 number, so stack leak is going to be int this 16 and of course I don't care about what happens if there's not a group or whatever because who cares, I'm just trying to get this leak just for this, so this one and similar thing here and since I already did this, heap leak equals int group one 16, so now I can do print hex stack leak, hex heap leak and I should be able to, oh, good, and I didn't do my connection.interactive come on, I didn't get, oh, because I didn't do regex receive, that helps if you use receive regex, the right functions. Again, this is why you develop things piecemeal because you make tiny mistakes and okay, I see, I mean I see the problem is that the problem on both cases is I don't have anything, I mean I can specify I guess exactly how many characters I expect rather than just a plus, but so the problem was that regex was matching on not all of the input, ah, there we go, okay, great, so now I'm parsing in both of them, here's the stack address, here's the heap address and now we got leak skit shell, cool, okay, so that I, oh, and I also wanna verify that's the number, that's the number, that's the number, that's the number, but I've got these all in integers now, so I can do integer arithmetic on them, great, okay, so what I want to do is I wanna fire this up in GDB and I wanna figure out for this value that it prints out of the stack leak, what's the offset from that and we actually know what that value is because we have the C code, so we can see that this value that it prints out is A and what we wanna know is what's the difference between A which is the location of A on the stack and the thing that we want to overwrite, the saved EBP, so, and we actually do know what we want to send because we've been messing with that in the scratch buffer, so basically I'm gonna make my payload, I'm gonna have eight A's for filling up the buffer of A and I'm gonna say that I want eight more B's and then P plus equals this gonna be CDEF, this is gonna be the four bytes for B's forward pointer and then P plus equal to FGH, IJ, this is gonna be the four bytes that are BK's pointer and then any other, so this will be then, hopefully, our rock payload, so the idea will be I'll add this all up and I'll make it so that the rock payload is the P's next thing and we will do cond.sendP and make sure that's what I did in the other one, yep, okay, cool, oh and then we'll need to append a new line to P, P plus equal because we know that gets will keep going until it gets a new line, cool. All right, so it got a second ball, good, that's what I wanted, okay, so the question is when I execute this, let's restart this, I think it's with me having nothing in there, so I want to continue, okay good, so this is my stack address leak, this is exactly what a scratchbuffers for, this is my stack address leak where that's what it gives me and now I'm in the unlink function, so if I do x20x$esp, so look at the stack with the save stack pointer, so I know I actually just, so I missed the prologue being executed here, the pushEVP, move the stack pointer to ESVP, move the stack pointer down 16, so it's gonna be, so this should be the saved EIP on the stack, 080485F7, which should be x5i, we can look at that real quick and we can see that this is the end of main and I think if we go back into hopper, we should see that at that location in main, which was what I say it was, 080485F7, 85F7, this is right after the call to unlink, so that means on the stack, this is the saved stack pointer, the saved, what am I talking about, the saved instruction pointer where we're gonna go, but this is what I wanna overwrite, this is this FFD208, this value here is actually the base pointer of the main's EBP, so whatever we overwrite here, this will actually get used as the base pointer for main, so when main calls leave and return, we can actually completely control where it goes to, awesome, this is a very cool challenge. I always like when they, but the question is we need to figure out that address, so the stack leak is there, the saved EBP that we want to overwrite is here, and so we need to calculate the difference between them, let's see if this guy will do it, I don't know if it'll do hex math or I guess we could use something like, oh, all right, Python 28, so 28, so saved EBP is equal to stack leak plus 28, is that correct? No, it's gonna be minus 28, so at the stack leak minus 28, that's gonna be the saved EBP that I wanna overwrite, and we kinda simulate what we want to have happen here because we don't have any kind of overwrite here, but basically if I want to change, let's say that value, and what is it printing out in unlinked.c, it's printing out, the leak we're getting is the heap address of A, the very first one, so we have A plus 24 is B, and plus, well, going back to our picture, we actually have this, so A is here, plus 24 is gonna get us here, plus four, plus four, so plus eight, so that is gonna be the address we're gonna want to jump to, so this is going to be, so this is going to be, so saved EBP is there, target on heap is going to be the heap leak, let's see, I think it should be plus, but let's, how can we test this? Oh, we know the address that it popped out, and then we know this is the stack pointer, then this is going to be the pointer B, so we can see this is B, and the thing that it printed out should be when we go to the top, let's see, B is here, A is there, so yes, we're gonna have to add on to that, so plus, so the heap leak is A, so it's gonna be A plus 24 to get us to B, plus 24, plus another eight offset, and that would then be, we may have to do it more, actually we will definitely need to do it more because of the way the EBP works, yeah, so this will be, we need to be four, eight gets us off here, then plus another four for saved EIP that we want to then control, and then another four with the saved base pointer, so that what we want to do, let's see, is we want to, I think what we're gonna do is, so we want this calculation here, and I think we want P to be the saved EBP, and then target on heap, and then this is going to be mains new, mains new saved EIP, and then mains new saved EBP, which is something that's not used, and so here we can say our target that we want to get to is, I think it's P32 is the way to do this, zero X, and this goes back all the way, the reason why we're doing this is because we want to execute this target, yes, the shell command, and that should work there, and then mains new saved EBP, we can do CCCC, and now I don't think this is just gonna work off the bat, that would be insane if it did, but you know, I mean, there's sometimes where you just want to see what happens, so four, there we go, cannot concatenate string and int objects, because we need P32 for each of these, P32. All right, well, something happened, now we'll need to debug exactly what happened and exactly how we went wrong here, let's see, I'm trying to remember how did I use PwnTools and debug PwnTools, and there's a really great way to actually use PwnTools with your input that you're giving it and debug it at the same time, which is awesome, PwnTools, GDP, I can't remember exactly which one of these things does what you want, but attach, I think is just what you want. Oh, yeah, that's right, and you get to specify the mode that you want, but so I think we could just do this, GDP, yeah, so gdb.attach to the connection and just continue, I think this, let's see, oh, that's right, and it knows that I'm using Tmux, so it's knowing that that's what I want to do, and so although the problem is I don't know how to switch between up and down, it looks like, okay, reason stopped, so, okay, all right, that's useless, okay, so we want to break at, we know what memory address we want to break at, sorry for that, we want to break at, I mean, this is where we normally crash, we want to see what happens here, and break at star zero x and continue, okay, backtrace, interesting, it's stopping at, do we have our new line in there anywhere? Oh, U plus equals new line, of course, or I can use the handy-dandy send line, which will send a new line, and I may not need this breakpoint, let's see, okay, kill that, that kills that, that kills that, go here, okay, great, ah, segfault, segfault, in libc start main, okay, interesting, so something happened, I definitely overwrote some stuff, let's figure out what we overwrote, so now I do want to add back in my breakpoint, and then I'm going to kill this, pop it up again, and so now I can walk through and see exactly if my payload is what I want, so, and I don't have all my screen because I've split this Tmux terminal into two, so I need to do info registers to find out what's going on, and we know that it's going to, and we can look at the hopper code here too, so we can know that, okay, what's going on here, so ebp into eax plus four, right, so ebp is, ebp is ff816408, so if we go and examine that, x20x, we'll see minus eight, so this should be the address we want, I guess I should have, oh, ff, oh, okay, so this edx must be our, the value that we, ah, yes, yes, so we know that that is ff816408 here now is our stack address that we want to overwrite, so this is doing the one way overwrite, so then what we're doing here is then overwriting the, and what are we gonna overwrite, eax, which is ff816408 with edx, wait, wait, okay, so I had that backwards, so edx is nine fd8438, this is gonna be, that should be this location into the heap if we did our math correctly, it should be here, I believe, and so ecx, let's think, okay, so eax, okay, so this is going to, okay, so this is going to overwrite this plus four, which is of course going to be the saved eip, okay, so the way this is going to work is it's going to overwrite that, which will work with edx, but then it should crash when we return there, because there's no way we could do that, but let's see, walk through what happens, okay, and then we're going to move eax into ebp-4, okay, and then we're going to move ebp-8 into edx, and now this is where we get to write whatever we want, wherever we want, so now into eax, which should be into eax, which is nine fd8438, okay, I definitely want to swap the pointers then, that's, what this is making clear to me is I want to and I could have kind of figured out exactly where I wanted the things to be, but hey, whatever, so let's do that, obviously that didn't work, let's do this again, and then now the first thing that I'll overwrite will be the target on the heap plus four, which shouldn't have any effect, it is the, yeah, it shouldn't have any effect, and then here I should be overwriting eax, which is my value on the stack of the base pointer of main with edx, this value on the stack, and so let's do a next instruction, so we have a no op, we have a leave, so this will then set up and should, you know, should put my value o8f3b438 into ebp, the base pointer, so do that, and then the base pointer is now 8f3b438, and now we return, which is going to return back to where we were in main, so this is fine, but now what's happening is now we are, we've essentially, even though the current stack pointer is in, is on the stack where it was, the base pointer is now pointing into our memory, it should be pointing right here into our memory, so we'll see we're going to add 10 to the stack pointer, move zero into eax, so this is in the prolog, we're going to move the base pointer minus four into ecx, which is fine, now we're going to do a leave where a leave instruction, it's important to remember this, a leave instruction is going to do the opposite of the last two instructions of the prolog, so a leave instruction is basically a set this, I think it's essentially a move the stack pointer into the stack pointer, so basically reset the stack to wherever it currently was, and because we currently control the value of the stack pointer, this will then cause the stack pointer to point to where we want it to, and so we do next instruction, and then let's look at this, why does main have this weird this, and then this load effective address into ESP, oh interesting, so now we should have controlled the stack pointer, but now it's going to load ecx minus four into the ESP, what's ecx? That's weird, okay, I wonder why it does that, let's see ecx 43, 43, 43, 43, 43, okay well at least that's a value that I control, oh because it put the value that we had after that on there, that's so interesting, okay, so it's going to then change the stack pointer now to point to something garbage, and it's going to try to return from there, so for some reason, and I'm not 100% sure why, is you have this weird instructions here at the end of main, so what we really want to do is we want to change, so the cccc, that would be 43, is that right, c is 43, yep, so we want this to be the same target on the heap, I believe, because for whatever reason sets that up and then calls a return, so now we should, now we're getting much closer, there we go, I killed that, okay, yes, you got it in the file, let's do it again, next, next, next, next, step through, not believe, return, add this, do this, do this, do a leave, and then load back that address into there, and now do a return, but the question is where am I returning to, so x20x, dollar sign ESP, so the stack pointer, so now I'm at this address so is that stack pointer minus four? Okay, so I'm four off, I need to do basically, let's say minus four here, I wonder if that's extra stuff they added to make it easier, I'm not sure, okay, next instructions, good, good, good, leave, ret, and now, boom, executing bin bash, so now of course the key question is does this actually work with what we want it to work, so I'm gonna do a poor man's copy, and I'm going to comment out my debug code, and then I'm going to do a cat there into exploit, boom, Python exploit.py home unlink, unlink, unlink, unlink, oh yeah, all right, so I can do ID, show me I'm unlink pwn, I can do LSSLA, home unlink, or unlink, I can do cat home unlink flag, conditional write what where from unlink exploit, man that was a tough one, there's no way I'm still authenticated, yeah, because they like to time out a server unexpectedly drop the connection, I can't believe that failed, login, login okay, that's what I was hoping for. All right, get that unlink, and now I've got to satisfy my own curiosity and see what that intended. All right, let's see what do they do from prompt, arch process, receive until shell, yeah, get that, get that, get the shell, pack, the payload is shell, what's shell, oh, that's the address, key plus eight, new return address, yeah, okay, that ret, yeah, they basically did what we wanted it to do, so yeah, we did find the expected solution there, so awesome, all right, well, there we go, we got to the end of Toddler's Battles, and that last one was a little bit tricky, but learned a lot in the process, I hope you did too, and next week we'll be back looking at rookies, so thanks, take care.