 Okay, so on Monday we talked about buffer overflow vulnerabilities, specifically we saw how we can use buffer overflow vulnerabilities to first control the save construction pointer which then allows us to start executing any code we want, right, and then we saw how shell code is code they can use to basically do whatever we want, right, and so we saw that we can use a knot sled to be able to allow us a little more leeway and where we jump and that address that we overwrite in the save construction pointer. And so very broadly, right, so why why does a buffer overflow work? What's what's kind of one of the key problems? The size of the buffer is always fixed, yeah, but if the size of the buffers were fixed, would that necessarily mean the buffer overflow problem? Like in Java you can create arrays that aren't that are fixed size, right? The fact that it's enclosed proximity of the buffer, right, that's the key thing, right, so should your program ever write to the save base pointer and the save instruction pointer on the stack? No, right, that is not there's not those those variables are in your C program, right, they're not variables that you the program declared hey I want to write to and change this value, right, these are just implicitly there based on the side effects of how x86 and how C does function calls, right, the calling mentioned. So more generally, right, so it's very tempting to think of buffer overflows as this very specific buffer and it's on the stack and you overwrite the return address on the stack and that's security vulnerability and that's a buffer overflow. And that is a buffer overflow, you know, at the coordinates and bolts, but really if you want to think about it a little bit more abstractly, really the problem is that the adversary can write to memory in our process space that they weren't supposed to. And so I gave you the ability to just write to any memory location in my program, you could effectively carry out a buffer overflow attack without necessarily overflowing the buffers, right, and you use the same techniques you use the shellcode techniques and you would use you would overwrite the save instruction pointer in order to do whatever you want. So there's an entire class of vulnerabilities that are more broad than just buffer overflows that kind of generalize this concept of essentially memory corruption, right, because the problem is an adversary can alter memory content in our program, right, and so we think about this in a few ways. So one is, so what is being overwritten, right, is it the return address or even the frame pointer, right, so in this case we'll see a little bit later if we can overwrite the save base pointer and the save return address, we can control the execution of the program, right, but that's not our only target and that's not, this isn't 100% required for taking control of the program, right, we actually saw in testing the shellcode that you can declare variables and you can have function pointers in C, right, and so if one of those are, we can overwrite and control a pointer to a function but when that function gets called it basically jumps to whatever is inside that variable, so by controlling this we can control where the program goes. We can even change pointers to data, right, if we have a pointer to some character string, right, and that character string is the program to be executed and we can overwrite this pointer to point to our data and make it execute our program, right, so it's not just the control flow or the control of the program like these two that can be corrupted, right, but changing the pointer to data can alter the execution flow of the program to get it to do whatever we want and even as simple as a variable's value, right, there may be one variable that says if the user is an administrator or not, right, if we change that one value to be one instead of zero, just that one bit that's the only bit we need to write to the program and now we've taken full control over it. The other way to think about it is, okay, so this is what are we overwriting or what are we writing, what are we correcting in memory, then the question is so what causes the overwrite, right, as we saw unchecked copying can overflow, right, and allow us to overwrite and write into memory that we're not supposed to. Also array indexes, right, so what's an array index in C, how is that actually done? Isn't it just taking the given integer and multiplying by the size of each element or something like that? Yeah, so it doesn't have to be exactly an integer, but yeah, the basic idea is, right, so you have an A bracket B, so it's actually under the hood does pointer arithmetic so it will move it, increment that address that's inside there by the size of whatever it is, but effectively all that it translates to is the A plus B dereference, right, so you can actually write your, it's completely valid C to do, oh I don't know if I want to get the risk of a crash again, right, so it's completely valid C code to write if I have a character pointer B I can write B 10 equals A, right, B like this, right, what this is doing under the hood, right, that's all this array index operator is syntactic sugar for this, which actually means you can write your array accesses like this, it's completely valid C code, this will compile 100%, and under the hood essentially what's happening is it's taking the address of B adding 10 times the size of whatever B points to in this case a character, right, and then it's dereferencing that, so is this array access here let's say with 10 is that in the bounds of B, just by looking at this we actually have no way of knowing, right, what if you know B could have been the string hello in which case it has three, four, six bytes with the null byte, right, and array access because it's just a simple arithmetic operator, right, there's absolutely no checkings to see if we're inside the bounds or where this result currently is, so that's another way that we can access an overwrite memory, looks like we're looking, also so sometimes so it's an integer overflow there's kind of 32 bit unsigned, signed integer contained in C, right, 26, 232 minus B, right, so that means 2 to the 31 I think, right, I get 2 to the 31 to 2 to the 31 minus 1 somewhere in there, right, so what happens if you're at 2 to the 31 minus 5 let's say you're almost at the border you add 20 to that number, yeah it'll actually go around and go negative I don't know if it's exactly that's a look at how exactly that number is going to turn out but it's going to turn into a negative number, right, so in this way we've overflowed the integer the same thing even with unsigned integers, right, so 2 to the 32 if we add you know 2 to the 32 minus 5 if we add 10 to that we're going to roll around and get number 5 again and the same thing with subtraction, right, so if we take 5 and unsigned 5 and we subtract 10 from it that number is now going to be a huge number not a negative number because this is an unsigned number, so these can lead to problems especially if you're using integers for array indexing, right, if we can cause an integer to overflow and either become negative well now you're going to go in a different direction from the array you're definitely going to be out of bounds for an array access, we can also make it more larger than it thinks it should be all kinds of fun stuff we can also so loop overflows this is one where if we can control the number of iterations a loop happens as we can maybe make it right more than it should, right, like if we can control that index or that size or however many it's doing right so this is kind of a think about a custom copy overflow right where we can try to influence how it's going to copy so the other question is where is this data that we're overriding right is it on the stack as we saw or is it on the heap or in the vss segment or in the data segment right and each of these can have different security implications depending on the information the other thing that's very fun to play with so the global offset table remember we talked about dynamic loading in x86 and on linux and c so what is dynamic loading me yeah so the basic idea right is we want to call a libc function or some other function right but we don't want to compile a libc into our program so we say our program says hey i'm using libc functions printf and so at runtime when we call the printf function what first happens is we go out and the system will go look for printf loaded into our process space or libc library and then link up our program and say hey printf is at this offset so as we'll see later the global offset table actually is a table that contains for every dynamically loaded function that you call it has a memory address that your code always jumps to to try to call that so it's a little bit of an interaction to do this this setup but as we'll see if we're able to overwrite that we can get our program to jump to wherever we want and the beautiful thing about the global offset table is it never changes it's always constant because your program needs to know where to call right but printf could be loaded at any place in memory so that's why I use this global offset table to know first where to go and then something else happens to that do this dynamically so looking a little bit more about what we can overwrite in general any if we're over if we're able to change any value in a program that could represent a security vulnerability right and this is kind of the critical thing we've been talking about security vulnerabilities are application dependent right so if we can overwrite that it may be a security vulnerability or it may just be a bug right it may not actually allow us to do anything uh so we can change the value of a variable so if it's printing out some some uh what the name file it's turning out some file based on a string and we're able to change that string to point to the string etc shadow then we'll output etc shadow for us um if we can change integer values then that integer value is passed to set uid to change its to change its id to the user id that's given usually if root wants to then execute as a root program for a little bit and then change its its privileges drop its privileges to a lower one if we can change that we can force it to stay as root we can change the value of the saved base pointer so what's the saved base pointer used as yes every function has its own base pointer right so when our function gets called we save our caller's base pointer right so that way when we return we put that base pointer back into ebp but what does the base pointer use inside of a function yeah all the local variables right so if we can let's say we can't change the instruction pointer but if we can change the saved base pointer now when this function returns all local variables and everything will be offsets from this base pointer that we control right so we can actually make this program think that it would completely change the local variables in that function and we'll see later we can actually completely control then once we control that we can make it do whatever we want and control the just like as if we're controlling the saved instruction pointer and the idea is every function before it before it returns in the epilogue sets the stack pointer to the current base pointer right and then calls return which jumps to whatever is on there so if we're able to control the base pointer point it let's say somewhere else where we control it's going to move the stack pointer to the base pointer right and then it's going to jump so it's going to return to whatever address we put in there so that's how we're able to control the instruction pointer through the base pointer and so by changing function pointers right so we can change in the so in the global offset table as a list of function pointers so we can change a global offset table entry and we write to it to point to our code then whenever it calls printf it's actually going to call our code because actually kind of fun game you can play you can change the functions that are going to get invoked at certain times so maybe you can call have them call system instead of printf it's a very cool technique other things we can overwrite that's really cool is long jumps so what are long jumps really long jumps what do we use long jumps for very close so yeah so the idea is so how far can you jump in actually maybe that's the wrong way to phrase it actually i don't know the answers to that so let's ignore that for now how do you do so what happens in java when you have some error right let's say you try to open a file that file didn't exist what happens an exception gets thrown right so then who handles that exception any function on the call stack right that has an handler for that so you can think about the control flow is jumping from one invocation of a function all the way to a completely other function higher on the stack right and you can't really you don't really just want to do a regular jump right you think about x86 and c because you have you know you're not uh that function is not clearly on the stacks you need to change the stack you need to do a whole bunch of other things right so long jumps are a way to do essentially exception handling in c so you can jump all the way from however many functions down you are back to your original function and the environment's going to be the same as if you never left so it's similar in some sense to a go to or a jump but it restores the program state at that point so you normally only go to one function right because otherwise if you try to go to another function what does that even mean what's the state of the function at that point what are the values in the local variables so you use this set jump call as we'll see it's going to save the context of that function at that into a data structure and then so we'll see it's kind of like fork in a sense so it's going to save the context at this point and then when you call a long jump when you call a jump to jump back to it it's going to be as if this set jump returned a different value so yeah you can see here that so when we save it when we initially call set jump it's going to return a zero so we can branch on the return value of set jump if it's a zero we know okay this is our first invocation of this function but if somebody else calls a long jump with this environment then our program is going to be essentially rolled back and reset to as if set jump returned something that's not zero something that was ever passed here so we actually use this as an exception handling mechanism yeah long jump you could do from different function invocations so no matter what the state of the stack is at that point you can call long jump to go back to essentially unwind everything to where what the stack was before you went right when you called set jump so choose as the exception handling right so usually in C you do exceptions by checking return values right but this is a way that you can do exception handling by literally jumping back into the code that called you yes yeah you have to set it up right when you think about that saves the state of your program at that point and then later on when you call long jump it reverts your program back to that point but with the change of the return value of set jump such that you can tell which thing happened right am I calling and I'm calling set jump to set it up or did I actually come back here and you can use that x that value that got passed in here to pass some information back so you can tell them what exception occurred and what problems happen I'll show you so we'll get some code that uses this so we have our main function so we have to declare a jump buffer right and so set jump is going to save our current environment right at this point and if it returns zero then we know we didn't have any errors right or not sorry not that we didn't have any errors return zero the first time we call set jump so we call set jump it's going to return zero so this branch isn't going to happen we're going to print out the value of I which is going to be garbage we should have set I we're very bad people then we're going to call some other function f1 and pass in this jump buffer this environment so then f1 is going to take in a jump buffer and do some calculations so this is like pseudocode right so it's going to do some calculations it's going to check if there was some error condition then it's going to long jump using e with error code one then when it does this long jump actually jumps the program jumps back to here with set jump as if I was never set and this return value returns error one and then it will exit the check went fine let's say there was no error here it's going to call f2 right so now our call stack is main f1 f2 and now f2 is going to do some computations and if there's an error it's going to long jump back all the way to set jump right above the two functions and it's going to be as if set jump return error two actually pretty powerful technique right that we can do this in c which is a language you wouldn't think has sophisticated like you know exception handling yeah how far can you jump up is there a limit to that I don't think so because of the way it's implemented as we'll see I think this is perth process only you can't jump to another process right really makes sense yeah you're trying to test the limits so then the question is how does this work right under the hood it seems kind of like magic well it's actually pretty straightforward so jump buffer is just an array and basically what happens is we're going to save inside this jump buffer we're going to save the base pointer and the stack pointer and register values we're going to save all the values of the registers and so when we call long jump we're going to just change everything back to where we were so that's how we can get back to where we were but if you notice something very interesting here PC so that'd be program counter or instruction pointer right so we're actually saving on the stack the instruction pointer at that point so if we look at how the long jump is kind of done we move uh I put these backwards we're moving I whatever whatever the value is passing the long jump we move that into eax because that's going to be the return value of a long jump call then we're using this jump buffer and getting the base pointer offset to set the base pointer and this is kind of pseudocode too right you can't really do end dot underscore jump buff right but uh to show you the thing right so here now we change the base pointer back to our original calling function now we change the stack pointer back to our the original function not the calling function sorry with a function that called set jump right we're setting the base pointer and stack pointer there and then we jump to whatever's inside the jump pointer PC and that's going to be the instruction that's directly after set jump so it's going to be just as if we called set jump here and all of our local variables are actually still on the stack because they're offset from the base point on the stack yeah it's the return so it's if as if set jump return which would be set jump returns when the next instruction after it is executed but we're setting the eax we're setting the return value to be whatever i was passed in here so this means as we saw a jump buffer is storing this program counter on the stack which is where our code's going to jump to right so by overwriting this jump buffer we can control where the code jumps to because on jump buffer is going to store this program counter which should be the next instruction after the set jump call and so using this we can modify the control flow of an application so we need something that where they call set jump on an environment we have some overflow attack that changes the that we can overflow environment right so either directly access or change and then exactly what we want to do right so just like any other buffer overflow or any kind of overflow we want to change that PC in that environment structure to have the address of our shellcode so that that way oh and you yeah you want to make sure that the base pointer and the stack pointer are pointing to valid memory right because we may i think we're going to we may dereference those right so we want to make sure that the stack and the base pointer are valid but they don't have to be exactly where they need to be and then we need to cause the program to invoke this long jump right just doing the overwrite isn't anything if they don't use it to jump so this is just trying to show that i really like this because it shows so it's a cool feature in a cool library that you can think of using right but you wouldn't necessarily think of the security implications of well what if they overwrite my buffer well that's fine because i'm using stack protection and my safe instruction pointers protected but here your code is essentially jumping to something that's on the stack that an attacker can write what do we learn from this x is the return value of you think it has the return value of long jump it's going to be the return value of set jump yeah so so ideally we are changing that value right no we need to change e and v that e and v is a structure that's on the stack so we need to change e and v to point to uh we need to change the value that's inside e and v which is a program counter value in there we need to change that so that that way when it's restored and it tries to jump there it'll jump into our shellcode so right here on this fourth line it is jumping to whatever's in environment at offset jb underscore pc so that's what we want to control because it's essentially doing an indirect jump right it's taking a value for memory and jumping to it so if we can overwrite and control this e and v dot underscore underscore jump buff then we can get the program to jump wherever we want so essentially i doesn't play around in here who doesn't i no i we don't care about we just need to be able to invoke it yeah so what do we learn from this and in general from this example low control yeah so actually there's a few ways to think about the lessons learned right so you can think about it from the attacker's perspective right in place in the program that control flow mysteriously changes we should probably try and investigate how we could overflow that yeah because without knowing exactly how set jump and get jump you know set jump and long jump work you know you have to dig into this the code to see exactly how this is done to see how you control this yeah so from the attacker's perspective anytime control flow could change funny like that is a place that we could attack so is it enough to to say let's protect e i the saved eip on the stack let's protect that then are we done and never have any but for a little more ability he's pointing to you could still create instructions at that look instead of changing the eip you just changed where it's pointing to and changed yeah so um if you think about it so in general like with this we're talking about what type overflow right so here it's a jump buffer it could be like we said just a boolean value it could be a string right so there's all kinds of sensitive data structures right that are security sensitive to our program and so you need to be extra careful to make sure those can't be overwritten right it's not enough to just say okay they're gonna come in through it's like um i don't think i've told it here so one of my favorite stories uh professor at ucsv did camera told me that uh they got hired to do rent teaming on e voting machines so the secretary of state came to them and was like you know we want you to test these voting machines to see you know to see what you can do to break in and so they go to sacramento and their inside this basement because this is the only room where they can have unlimited access to this voting machine and so dick gets in there and the guy's talking to them he's like look at this lock like on the front of the machine you know it's just a pc but they do a lot of machines like look at this lock it's i'm gonna make up words but it's diamond coated double encrusted it's like only this it's a special key that has like special bits and nobody could you can't even make a key like this nobody makes keys like this like there's absolutely no way you're ever gonna break this lock this is the best lock that has ever existed in the history of the world and digs just like okay cool you know this is you're trying to learn all you can so he's learning and then he said the guy leaves right and he looks at it and he goes yeah that looks like a very fancy lock right i will probably not try to break that lock but then he looks at it some more and he sees that there's some screws that are keeping the hinges on the machine on the other side so they take a screwdriver and then the door comes off so this is about the point is thinking about ah they're coming after the instruction pointer we have to save the instruction pointer right we've got to make sure they can't do anything the instruction pointer we're focusing so much on the front door that maybe don't think about the hinges right or even the back side of the door what about the back side is there a fancy lock on the back side probably not right so so yeah so this i want you to think about right because attackers are very lazy right they're going to try to find the easiest way into your program possible so if you make very difficult for them to go this way they say well let's try a different route right let's try the back door let's try it with them okay so let's look at more about what is over so looking at what can be overwritten so let's look at this super secure program so we have a character array of usernames character array of passwords and we're doing string and copy so how many bytes are gonna be copy and from where to where where's the source in the destination from rv1 into passwords yeah uh then we're doing copy 512 bytes from rv2 into username then we're printing out hey that we're checking this password for some user and then we're going to call the check password function passing in password so inside check password we're going to copy do string copy from p to my pwd to create a copy of that we're going to check it and say hey we're checking this and then we're going to return the overflows here so let's think about it like this can this overflow the saved instruction pointer or the saved base pointer this line right here yeah no right only 512 bytes that's the only thing it's going to output right in the password what about this line same thing right only 512 bytes so we look at here we think string copy well a so which should be thinking hmm they really should have used string and copy here yes right but they did not but why not argue for the developer why did the developer not do a string and copy here yeah it's 512 bytes and he argued that a string and copy in the password of 512 bytes right so in the developer's mind he or she is thinking that p is only ever going to be 512 bytes right i just did this copy so what are the exact semantics of string and copy this is one of the things you should do whenever you have an unknown program right and it's using library functions if you don't know exactly the semantics of how it's doing and operating you should look at it again because it can give you ideas right this is something i do all the time when i'm looking at unknown binaries so we have string and copy so we first need to verify that our understanding of string and copy was right about who's the destination and who's the source right that's that's step number one uh so we see yes source destination length so we see that okay the string pn copy and the string and copy functions copy at most length characters from source to destination right so we know it's only going to copy 512 characters from the source to the destination so if source is less than length characters long then the remainder of destination is filled with zero characters what was this last thing mean otherwise it stops copying right it only copies 512 bytes but it does not guarantee that it puts a terminating zero byte at the end of the buffer so let's go back to our example it's getting better i think we're getting better at recovery okay so let's look this string and copy right so let's say we copy let's say the attacker passes in 500 bytes for the password right a string of 500 bytes and what is the password buffer on the stack going to look like after that happened based on what we just read from string and copy yeah 500 bytes the password plus 12 zeros so what's the string length of that buffer then what happens if we pass in 511 bytes for rv1 and what does the password look like password buffer yeah be 511 bytes followed by one zero what happens if we pass in 512 bytes yeah it's gonna be just 512 characters no zeros right because it's not exactly what it's gonna do because say only in the case that it's less will it put zeros in there so let's say we do that right and then we put i don't know 200 bytes into username so then what's the string like the password okay so let's say that the stack layout is exactly like it is in this example so that you first have password and then above that you have a username so the stack is exactly like this username plus yes right so if we pass 512 bytes for password and then we pass another 200 bytes for username now when we calculate the string length of password it's going to go okay keep going until i hit a zero byte and we'll go past those 512 bytes all the way up those extra 200 bytes for username until it gets the zero in username so now if we think about this string copy now what could the size of pv yeah in that case 700 we could make it all the way up to yeah was it 1024 is about as hard as you want to go because if you did username 512 bytes too then who knows when your string is gonna end right it's until it hits the next null byte on the stack right so we can overflow the my password buffer by passing in a password that has the exact length that has 512 bytes so that way the resulting password string is actually bigger because of how these are laid out on the stack yeah so if you go bigger it's also not going to be null terminated right it just won't copy that the last if you do two if you did 512 and 512 no i said like password is 513 it just will cut off that last yes it will cut off that last byte so you don't have to do 512 exactly but so yeah so you can think of this kind of as like a null terminated string overflow right the problem is that string did not have a null terminating character in it so that way when we use it as a string it can actually overflow onto the stack and be more than the programmer expected it to do this also drives me crazy that here we have this quote quote safe function right which actually can so this is especially tricky because you're looking at this code you think okay you store in your mind the you know string and copy safe string copy unsafe but really if you use this incorrectly string and copy can be just as unsafe right and also notice how this was kind of a cascading problem right if that my password buffer was 1024 bytes or maybe even larger then we may not be able to overflow it and control everything depending on what's on the stack above username that would be a little bit weird no because the next thing is going to be the same base pointer so oh that won't have zeros and then the same instruction point and then above that's going to be argc and then our v1 or v2 yeah actually it would probably be pretty big maybe yeah so as an attacker i wouldn't have access to this code right so but just by looking at the object i'm how can i determine like 512 is the number i want to know something more than 512 right yes so i would so you can well you can still use object up to look right because you'll know that at some point in the program it'll be call string and copy right so you know that at that program point the stack must be from the bottom up password argv1 512 or past sorry you don't know this yet so you'll know that the first thing on the stack is going to be the destination the next thing above that's going to be the source and the thing about that's going to be n and then you can trace through the code to see what gets put on the stack eight above and that will give you the n the other thing you can do is you can run ltrace because ltrace will trace all the library functions and it will output exact it does that conversion so it will show you hey the program called string and copy with some buffer with some other buffer with the value 512 so that's when you should start thinking about trying to do some 512 stuff yeah and that it's calling string copy afterwards so yes that's the other thing right if it never called the other string copy so this kind of that would probably focus your attention first right so you see this string copy and then you start salivating you go okay how can i make this p how can i make p more than 512 bytes right if i do that then i know i've got the program and then you look at all the calls to check password in the program to see what's being passed in and if you can influence the size of that buffer and then that's when you look here and see its password then you start maybe trying to understand this program for various reasons we'll actually look at that a bit later but SLR defends against you where your buffer is going to be so you don't know exactly where it's going to be right but as we saw right you could make a knob sled pretty much as big as you want right and it's 2 to the 32 really a big number no right it's not as i wanted you to do the last assignment right you just break hash functions 2 to the 32 you can calculate that really easily and that's you have to be exactly right here with your for every knob that you have it's 2 to the 32 basically divided by that size of your knob that you have to test so if you use a kind of one gig knob you're going to get it very soon right you can even make this even larger so yeah so that's one reason and we'll see another reason with return-oriented programming it completely bypasses a SLR with no word i just used no knob no knob okay yes so could you create have another program running in a separate thread even a separate process that has a huge knob sled that does what you want and then reference send the eip to someone no because each process is in its own address space so you can't jump to somebody else's address space what you can do and what happens with your browsers uh so remember browsers the attack model is really crazy right because you have javascript code that's running on the browser and the javascript code can do stuff right so what the way they get around SLR with browser-based exploits is they create a bunch of knob and shell code they allocate a bunch of those and basically the heap of your browser and then they just try randomly jumping there so it's called the heap spraying so you basically like spray your knob and your shell code everywhere all over the heap and then you try your exploit and then hopefully sometimes you'll be right right because you put so many of those throughout the stack so even asl or whatever you've done this so many times you're very likely to jump to one of those locations it's kind of similar thing but it's in the same process space is the big difference those kind of exploits are super crazy because okay so in general right so this is so this is kind of a different type of overflow here we're not actually overflowing any of the buffers really right we're staying within the bounds of the buffer but we're not terminating our strings and that allows us some kind of overflow so yeah some functions like string and copy which we assume to be safe are actually not because they don't include that terminating zero and so this way if you have some adjacent buffers or you can control that data that's after it you can get it to copy more information so what should we do here what what should we learn from this yeah so that's one way to do it right is pass into string and copy the length minus one honestly string and copy should do that by itself like it's crazy that it doesn't do that the otherwise always make sure your string is null terminated right so make sure after you do a string and copy that you set the buffer bracket 512 no 511 to 0 right so yeah you want to make sure that there's a null by the end of all of your character yes okay so index over flow so we're gonna go over this quickly and then i think we're done for today so index overflow so this is if you're able to control the index into an array right because we saw using the bracket notation or any kind of array access in c does not check the boundaries of that array to see if this array access is inside the boundaries um and this is actually if you can absolutely control the index of that array it's kind of nice because you can over you're more of like uh as buffer overflow you're like the whole you're just like smashing everything right i'll just smash a bunch of stuff right with this you get to precisely control one thing of memory you get to say exactly where you want it to be based on this offset of the buffer so it's a little bit it's much more precise not quite as precise as some other attacks but it requires some precision and so depending on this type of the array can change what you can do or not do because you have to be careful about what you're doing so if you look at an example here we have an array we have an index we have some value we are taking in our v1 interpreting it as a base 10 number and copying that to index and then we're copying as base 16 a value into rv2 into value and then we're setting array index equals value and then we're returning right so what can we do so what can we control here so we can't overflow the array right this is part of the thing about this is you see the buffer anything overflow that buffer right but if we just control this index here because we control the value we can control index which we obviously do in a simple example then we're able to write wherever we want based on the offset of array so we can write up down however we want and index can be a 32 bit number so we can go as high or as low as we want to do so we can really overwrite any memory in reference to your array so if we overflow 11 so why 11 here it is greater than eight yes it'll do a core down but why specifically 11 so at array uh yes so not quite so you have so it's actually going to be it should be well so you have to look at the at the object down to see exactly how the stack is laid out right but assuming it's value index array eight right so eight above array is going to point to the end of the array i will point to save bbp and 10 no that's not right yeah it should point to eip but why no but won't they want the arcs beyond the stack arcs are above the saved eip that's local variables save base pointer save eip arc c arc v yeah okay so it will automatically sort of like that because gcc hates me oh no no it would have been 12 right but you have eight lines there instead of yeah so it should be like this okay so we ate nine we get you to value let's say 10 we get you to index 11 we'll get you a base pointer so that's why it's crashing is because it's overflowing the base pointer right so when it's returned setting the base pointer and then something else is doing something so it's crashing there should be 10 12 probably if you want to do an overflow you have to look at the example so uh you need to check array indexes right to make sure they're within balance that's up to you the programmer to do and something you should look for when you are exploiting these programs cool all right thanks for that