Where are we? Here we on. Okay. So this is Calling Convention Week. In Calling Convention Week, we're sort of setting up the beginnings of like how everything works in order to get to this insight. This is a diagram that should live rent -free in your head for the rest of your life in some wacky way or another. where you always have this number line from left to right, and you are filling in malicious payload on the left, and you're going to try to position an exact, like, evil address on the right. And what you're going to have to do every time you do one of these types of exploits is do the math or calculate something or look at it, and rate air two, just start to point your fingers and do some traction or whatever, in order to know how many bites of crap you fill in, in order to get the address you want at the spot you want so that you can control the instruction pointer because if you can control the instruction pointer, you've just made a nuclear weapon. Okay. So not to overstate the importance of it, but this is national security in that exact moment or whatever. That's the thing. All right. Seems like it's esoteric geek shit. That's the thing that crashes a company's stock price or whatever. And by the way, when there's a cyber attack that crashes your stock price, always buy the dip. the market forgets about cybercrashes every single time i have a ton of crowd strike now freaking doubled my money on the crowd strike thing or whatever because like oh yeah it's tanking yeah i'm sure that'll last yep buying all of that okay anyway anyway um sorry we just had a nice little chemistry there you know and so it's like ooh let me like sell you on why I think investing matters as humans, but that's a waste of your tuition dollars. So you give me nods right now if you want, like a five -minute philosophy of why I think you have to know something about investing. Okay. All right. Pausing your tuition dollars. I came of age and like I got my PhD in 2008. There was a global financial crisis in 2008. you are beg borrowing and stealing to find jobs and shit a lot like the job market you guys are entering why is your job market shitty compared to when you started your degree with like the promise of oh look at all these jobs and computer science and stuff or whatever right and they're like oh not anymore sorry um there are factors at play in the world that are outside of your control um when it was 2008 i was investigating i've always been addicted to like in the sense, like, and not, and I'm not talking like being rich. I don't want to be rich. I want to own my time so I can super auto pets or whatever the hell I want. So like, I lived in a camper with an organic garden eating edible weeds and shit, right? Like live on a thousand bucks a month, just, you know, minimalist because then I don't care, you know, whatever. So when I investigated all the things that you could do to like make it through 2008, what do you do when you like have a savings account? You get a paycheck. You earn some purchasing power that's enough to buy, I don't know, a couple of tanks of gas today or whatever, something like that, and then you like put it in the bank, you could hide it under a pillow, you could do whatever with it. If you just let it sit there as cash, the purchasing power of that cash is whimsically going to go down based on whatever the hell they're doing in D.C., which is nonsense, always. So like, since they're always doing nonsense and the purchasing power of your hours of labor goes down whether or not you do anything. That means that you are an investor all the time. I don't actually love investing philosophically. I think I don't like zero -sum games. I like to create stuff, and creating stuff makes the world better. Winning something where somebody else is losing something sucks. But you don't have a choice because you're paid in a currency and the currency is like the value of the currency. What you can do with it is at the whims of the government. and the Fed and other people doing whatever. My cynicism came from the Swiss franc. 2008, I'm like saying like, okay, what would it do, like what sort of things could I have done to not be subject to all this crazy financial ruin going on when everything's collapsing? I found this nice little portfolio where you could have like bonds and stocks and gold and cash. Maybe just like kept rebalancing that or whatever. Whatever's low, you buy more of that, whatever's high, you sell some of that or whatever. That would have like got me through the 2008 crisis, no problem. So I'm like, okay, let's get some cash in there. whatever. The most reliable currency in the world at the time was the Swiss Frank. And you know what the Swiss Frank did? They're like, dude, we can't sell enough watches. We're going to tank our currency. How? We're going to tie it to the euro instead of its own little thing or whatever. So that way, when they go down, we go down. That way, we can like sell our watches for cheaper or whatever because our currency is too strong. All of the governments of the, I watched them all water down their money. They all want to water down their money because we've got a huge national debt, right? And how do you pay that huge national debt? print more money, pay it with fake dollars. Which means, like, and what happens? That means that your paycheck becomes worthless. So I, like, just measured out paychecks of, like, how much Oreos could my paycheck buy if I had an average paycheck from, like, 1940 all the way to now or whatever, right? And, like, by the way, the value of that paycheck was the highest. You can buy the most Oreos whenever oil prices are the lowest. Which sucks or whatever, but just say, like, you know. When oil is cheap, your paycheck goes further. When oil is expensive, you get nothing in your paycheck. That's because everything is transported in trucks and stuff or whatever, blah, blah, blah, like, you know, fine with like a lagging two-year indicator. But to say, you don't have a choice because you are paid in cash, and cash is an investment, which means that, like, you're just an investor no matter what. Sorry, that sucks. Therefore, do it well. That was my five -minute interlude of why you actually have to know something about financial markets because you're paid in money and you have to store it somewhere, somehow in some way. And because they don't want anything for you, it's your job to then just manage what you have earned in some way or another. Don't be a rent seeker or whatever, something like that, fine, blah, blah, blah, blah. Like, you know, try to be worth what you're earned, but don't also just be a slave to a system that wants to have you do all of this shit and give you nothing for it, which is definitely what it wants. Anyway, okay. Cool. That's the interlude. Sorry. You know, forgive the, if you want to refund in your tuition dollars, suck it. Okay. That was offensive. Okay. We had three layers of the Shrek onion. We're calling conventions. Calling conventions. We had three layers of the Shrek onion. Please have bounced back. All right. We're here. We're here. All right, the three layers of the Shrek onion. Layer one was storing the return address on the stack when you are about to jump into a subroutine. Layer two, storing your old base pointer on the stack so you can find your variables again. when you come home. Do you guys remember that? You want to say that again real quick or whatever? We can do it with the burger. That is to say, I'm going through code, line one, line two, line three, line four. I'm going to jump into a subroutine. I'm going to store the address I'm going to come back to, which will be like line five or whatever, on the stack. Then I'm going to go do my subroutine. when I get to the end and you get to the RET command, I don't know, I put that in quotes, but the RET command will pop an address off the stack to return you back to line five. Okay, that's layer one. Okay, so his hypothetical question is like, what if somebody fucked up? Right. So what, and what he's saying is like, what if I get to that RET? And things like the stack pointer has not gotten itself back to the place where the return address is. If that has happened, the compiler screwed up or a hacker is at play. So like when we are hackers, we are going to mess with all of these assumptions, right? And so like it could be that the return address is happening and it's not at all where it thinks it should be. That is what we'll do as hackers. When everything is healthy, that never happens, but it never happens because of caution. Like, it never happens because of convention. It could totally happen if somehow the coder inside the thing added some assembly that screws the stack pointer or something like that, right? Like, it might be that I could code the program, put in a line of assembly in C. I can put raw assembly in C and just run it. I could just, like, screw with the stack pointer, and now it'll just crash the program after. So if that happens, the program crashes, that is to say, if the stack pointer is pointing at not an address and it pops it off, it will probably do a seg fold. Note to self. We need to talk about, yeah, seg folds. But not today. They're important. They're an aside. Literally, it's just saying this is not a real address. That's all. So the operating system gives you certain ranges of addresses that it will honor. Anything outside of that, it will not honor. A segfault happens whenever you try to resolve an address that is not valid. Okay. So your question was, what happens if they screw with the stack so that when I get to the end, I get to that ret instruction, I'm not pointing at the right address. No hackery or crashing. Those are the two things that will happen if that doesn't happen. Which means the compiler does everything it can to put everything back the way it left it. When I look at disassembly, you'll notice that there is a few things that happen at layer two of the onion. I'll highlight this line. The way to fix what you're worried about is the leave instruction. And this might actually make it so that if I wrote that C program, I wouldn't even crash it. The leave instruction is the way to fix that assumption. He jumped in a laptop, sorry, Google and something or whatever. Fine, you're researching, but I'm looking at your face and say, the leave instruction is the fix to your thing. Here's what the leave instruction does. It does two things. It will move the stack pointer back to the base pointer, and then pop the old base pointer. And so these three things always happen at the end of every, program, just like these things happen at the start of every program. At the start of every program, you will see it push the old base pointer. That's layer two of the onion. And then copy the stack pointer or the base pointer to the stack pointer. At the end, it will do the exact opposite. Do you guys know the Sox and Shoes theorem from math? It's like this. If I have a composition of two functions, F and G, if I invert it, I must invert in the opposite order. And that is to say, G is putting on my socks and F is putting on my shoes, I don't first take off my socks and then take off my shoes. That's ridiculous. So to say if I put on the socks, then put on shoes, I must first take off the shoes, then take off the socks. So what you'll notice here is that at the beginning, I will push the old base pointer and then copy the stack pointer into the base pointer, move the base pointer to the stack pointer. When I do the opposite, taking off my shoes first is to is the leave instruction is going to copy the base pointer into the stack pointer that is move the stack pointer back to the base pointer then pop the base pointer and so those things are the socks and shoes of the calling convention of layer two that is to say I'm going to store my old house keys and then I'm going to set up a brand new house at my hotel in Vegas do whatever crap I'm going to do in Vegas when I'm all done with the crap I'm going to come back to where I was at the base pointer, pop off the old base pointer, and now I'm ready to return. So that's the, our installation, is these four lines, or really three lines of assembly, are how we prevent the program for just crashing and always being at the right place. Let's see that with burgers, maybe. I think, where my burger go? I think my burger is a link right hidden. I always look for this burger. I love my little burger. I'm in Maine. I got like var x. I got var y. I will now push my return address. This is layer one of my onion. Then I will, the first thing I do when I get in is push the old base pointer. All right. And at this moment, I will then set the base pointer and the stack pointer to the same value. The instruction pointer is doing some crazy crap over here or whatever. And now we'll start doing normal coding. So all the normal functionality of that code is going to make local variables or whatever and things like that. This will be just like some context variable here. You know, another variable. Now, you'll note that all these other other variable here. variables, they are all at base pointer minus four, base pointer minus eight. They are all at a fixed offset from the base pointer. That is to say, the variables when I'm in Vegas are inside the hotel room and they're like, go into the room, turn to your left, you'll find a closet, you'll find the suit on the hanger or whatever. The hanger is my variable. You know, suit is the thing in the variable or whatever. And so the base pointer does not move at all. The base pointer is the function context. Now, you guys have felt this in other ways throughout your life. Like, let's just jump into Python. Let's say, like, X equals 34. Def, you know, local funk will consume something. And it will say, like, let Y equal A times two, print Y, you know, something like that. All right. And so, I'll say like let Y equals 23 or something like that. And then I'll like call a local funk on 7. Y is still 23, right? Like that Y inside of that thing has nothing to do with the Y outside of that thing. That is to say this was a local variable that was at a base pointer minus 4 inside of that subroutine. When I'm back outside of that thing, I'm back in Maine. By base pointer some other place, I can't go to base pointer minus 4 anymore. I have a new base pointer when I'm out here, outside of the function, and I have a temporary base pointer when I'm inside the function. The base pointer acts as the place where all my variables live. So the reason that you guys have always had to mess with, like, how come why isn't working this way or whatever, something like that? Or like, you might have to declare it as a global or some crap like that, you know, because everything is just base pointer minus four, and the base pointer moves every time you're in a new subroutine. You call it a stack frame, if you want. A stack frame is like setting up a new base pointer, stack pointer place where all of your stuff will live. The stack wiggles around. The base pointer is fixed. Okay? You're with me on how local variables work inside of calling convention? You can ask questions. This is like review from Wednesday, but I don't mind repeating it eight times. Like this is the most important shit in the world. I've spent a whole week on it. Coding, like interviews are about this topic, whatever, things like that. And we're going to be learning an inside note as hackers soon. Okay. Come on back. Come on back. all right okay um next up layer three of the onion is this layer three how do we pass a parameter into a subroutine okay So to say, if I'm going to call a function, I need to also give it arguments. And you'll notice that every time in assembly, we've got like a call instruction. It's never like a call with these arguments, right? Like it's just not that smart. The chip just does chippy things. So, and what I mean by that, it's like the chip just jumps to someplace or whatever, something like that. So the question is, how does assembly pass arguments to a function? okay this is the third layer of our onion the answer is pretty simple it depends okay the layer has two simple answers if you are a 64-bit binary then you use registers for the first six arguments Otherwise, use the stack for arguments. Okay. So this is something I've been hand -waving over on the diagram that I'm showing you over and over again. Until now. When you see this thing, this is the box that I've been ignoring because it was layer three of the onion. this is to say when I am inside the purple like stack frame right I'm in the callee stack frame I'm in the subroutine all my life is over here whatever things like that um the function the arguments that were passed to me if I'm 32 bits or have more than six arguments live on the stack to the right of the return address um so that is to say I'm going to do this for a 32-bit binary. We're going to go back to the beginning. I've got a base pointer, stack pointer. We just live here together. We're going through normal code. I'm going to have, like, you know, local X, push, local Y, push. Push. Okay. I'm now going to call a subroutine, but I'm going to call it with three arguments. No, not X, Y, and Z. Let's call it argument one, argument two, and argument three. I will push them on to the stack in reverse order. So here's what we'll do. I'm going to push argument number three. So I'm calling a function. It's like takes in X, Y, and Z does the average of X, Y, and Z or some shit. It's going to add them up and divide by three years. So I'm going to push argument three onto the stack. I'm going to push argument two onto the stack. Always an inverted order. I'm going to push argument one onto the stack. Now I will do the rest of the layers of it. the onion. So I have my local variables. I'm going to now put the three arguments that I need on the stack, and now I'm going to do the return address on the stack. We use the stack for every bring-in thing. Now we're inside the subroutine. We jump to the subroutine. The instruction pointer can go over here now. Whatever. The first thing of the instruction pointer will push the old base pointer. So now put the old base pointer on the stack. Okay. And And now I will do stuff inside of here. Now I can have local variables inside of my function or whatever things like that. These are like function local A, function, well, B. Now I've got other variables. The base pointer is no longer here. The base pointer is now here. The instruction pointer is doing its thing inside the subroutine. It never goes up. It only goes down. But fine. OK. So the question is, when that subroutine needs access to the argument, A, B, and C. Where does it look? It looks at base pointer plus two addresses to find this guy. So if it wants to read argument one, it'll be the only time in Radair 2, we'll see RbP plus something. So here we'll see RbP plus 8 will be arg 1, plus 12, will be ARG 2, plus 16 will be ARG 3. So again, it'll be anchored by the base pointer, but now instead of base pointer minus 4, minus 8, it'll be base pointer plus 8 plus 8 plus 12 plus 16. You with me on that? Now, that's for 32 -bit binaries. You guys are not messing with 32-bit binaries very often these days because everything's on 64-bit boxes, but often it's not. You do old stuff or whatever. You go Nintendo, your 8 -bit binaries, fine. But to say, in 32-bit binaries, each of these addresses is 4 bytes. So the reason I know it's plus 8 is here. if this were in a 64-bit binary we can still use the stack for arguments but they will always be arguments 7, 8, and 9 so here six of the arguments will just be in registers what do I mean by that? Literally what I'm saying when in 64-bit we have the extra convention of not involving the stack as much for arguments so argument one will be in the RDI register argument two will be in the r s i register argument three will be in the r dx register our cx r8 and our nine those six in that order are used for the arguments okay argument seven it's on the same stack where my burger said it would be argument eight is argument two argument nine is argument three all right you with me on that um when we get to the rate air two which i'll just start doing in a second now instead of rbp plus 8, it'll be RBB plus 16. Why? Because these addresses are 8 bytes instead of 4 bytes when I'm in a 64-bit machine. The addresses are twice as long. So you just always have to do that math. It's like, yeah. Plus is down, minus is up. I wish the burgers were left to right, actually. I always see this as left to right because I see it as like a number line. I set my base pointers like x equals 0. I'd say like x plus 4 would be here, x plus 8 would be here. Yeah. Make a kebab website. Make a kebab website. Holy shit. To do. Katina. Okay. Make the burgers a kebob. Now, I'll say this. Do you guys know flight of the concords? Do you guys miss flight of the concord? I don't know if it mattered to your generation or not. American kebabs are on a skewer. Australian, you know, Oceania, whatever. All the rest of the world's kebabs are actually like shaved from a big thing of meat in like a pita, you know, or whatever. So like, Flight of the Concordes have a song called The Pretiest Girl in the Room or whatever, something like that. And it's like, the prettiest girl I've ever seen with a kebab, with a kebab. And but like, you know, because that's like the drunken 2 a.m. food of Europe. But when they made the American version of it, like, they've got skewers, right? It's like, nobody fucking go in New York's like, let's go get some skewered meat or whatever, right? But we just don't know what a kebab, you know, whatever. So like, anyway, song written in a different country, imported here, therefore the actors had to have like skewers of meat. Anyway, so I slightly want a different word than that because I spent three years in Europe or whatever. I like normal donor kebab or whatever, but not. American kebabs are fine, but just, yeah, yeah, yeah. Come on back, come on back. I'm a little nervous that we broke through that. It'll be back. It'll be back. Don't you, yeah? Are you like parameter, aren't you that too big for the register? Okay. So Jay is asking the question, what if your parameter doesn't fit into 32 bits or 64? four bits or whatever. Well, the compiler is the one making all these choices of how this convention works. All you get is eight bytes or four bytes, which means that if you are, let's do some more Python. If I have, so let's take this exact same example I did, but now let's do it with like a dictionary. So I'll say like, you know, my object equals this thing and my name is, Andy. Okay. Now I'm going to go into local funk. Okay, I'm going to undermine myself. I'm going to pass in an object and local funk will take an object name and set it to mud. My name is mud. If I call local funk on my object, my object now has named mud. They wanted to autocomplete to name Andy, but it actually had changed to name mud. And that's because this thing is too big. It's like a struct now. It's not just some, you know, a little simple thing that's just like some address. It's like it feels complicated to it. So it doesn't pass in a fake object. Now, if I do that same thing with the other variable, let me set that back. Let's go deaf, local funk. let's just take in like a number and I in all I do inside of this is just set the number to like you know 99 if I call local funk on why why is not 99 it is 23 why would these two things behave differently sure did annoy you as freshman in 106 or whatever it's simply because of your question which is that some things can just fit in a register no big deal some things just the address here's where this lives whatever read the value fine if a thing doesn't fit cleanly into a register then i am now when i move into this thing i'm going to reference an address so if my object is more complex than what can just fit in an eight-byte number or whatever i don't pass the eight-byte number i pass an address um and so uh the object isn't what's in the register, the object lives somewhere else, and the address of where the object will be lives in the register. And so what got passed in this argument is that object, I go to that address, I edit it, because the object is a more complex thing than a string. Okay, so basically to say, it is, the compiler will figure out for fancy stuff what to do if your fancy stuff doesn't fit cleanly into eight bytes. And that's more to do with the way the programming language is set up, to say, like, what are fancy things? In C, it's not a problem because you, the coders, say, I'm using an int of four bytes. It knows that that's an int of four bytes. But you don't get multi-precision arithmetic in C. In Python, I can do this to that and just have this giant number. This doesn't work in C like that, right? And see, if I want to have a giant number, this thing's just going to overflow based on the size of the int that I'm accepting. And so I have to actually code up a whole library, which I've contributed to in the open source, you know, back in my open source days or whatever. multi-precision floating point arithmetic or whatever and all this kind of stuff like that blah blah to do high-performance you know low-level things now this is using that library right like everybody is using the c implementation of it but we don't want to have to think about it when i'm in python yeah okay so the more layers of abstraction between you and the truth the more you've got to like unpack shit down at the assembly level okay okay uh So, burgers, that's where it was. I think all I want to do now is just pull up some actual binaries that are just, here's a thing, it's calling this, and let's just look at it and see all the stuff happen the way we did, and then imagine in your hearts that you are already the hacker, because next week on Monday, we start hacking, all right? This is the last step we need before we're hackers. It's all we need out of, like, the x86 side. This is not a class in x86. This is not a class in C. There's a class in Python. It just takes a while to learn that. Monday we start Pythons. So this is our goal, is to understand this thing. Now let's look at this, see if we understand it. Again, I'll go kebab mode, but it's a little easier to read this way. When I'm inside of Maine, Maine will be the blue part. I'm in a stack frame that has my local variables for inside of Maine or whatever. I'm going to ask for some arguments. I'm going to, like, put some arguments on the stack for the subroutine. Then I'm going to put my return address on the stack. Then I'm going to put the old base pointer on the stack. Then stuff will happen inside of this in the subroutine. The subroutine could even call another subroutine, in which case it would put more arguments for the subroutine and jump into another subroutine. It can be recursive, right? I called this guy who called this guy, who called this guy, every time, I don't know how many layers deep you are, because you just pretend like if I've got a base pointer then I'm in a fresh green field I don't have to worry about anything else in the stack anywhere and so when we go to explore the stack like one of those things that happens you're just going to find all sorts of crazy shit like it's like you know trash on the side of the New Jersey Turnpike or whatever right just like all sorts of crap and all of it has a history of that person's trip to White Castle or whatever White Castle is no longer East Coasty right I don't think so Um, whatever. Crystals? All of those restaurants stuff. Anyhow, I can, inside the stack, I will find all sorts of other stuff, like way up here in these dot-da-dots. I could have been inside of a function, which called a function, which called a function, which called a function, which called a function. And I can find all the evidence of that if ever I'm free to just explore the stack, which we are every time we run Radair 2. I'm not as the coder typically. But when I'm running radar 2, I can just explore the whole stack and see the evidence of every stack frame that I've been in all the way down to where I am right now. But where I am right now will always feel like a crystal clear green field of possibilities. Or just stack point or base pointer right here, and I can make new refresh room for fresh new variables. And that's why, you know, we're always appending to the end of the stack. Like, it's always fresh at the end of the stack. Now, one of those things that's true is that if I jump into a subroutine and I jump into a subroutine, and I come back out of the suburb team and I jump into another one, that memory is actually there. So like one of those things that's true when you're coding C is they'll say, if you use un -initialized variables, your behavior might be undefined. What they mean by that is that I'm not zeroing out the stack behind you. And so when I do leave this function, you know, we saw what the leave instruction does. the leave instruction moves the stack pointer here and then pops and then it will pop again so now the stack point will be right here well now i've got arguments in place or something like that or whatever you know might have some other things i can jump into another function well what that means is that the local variables inside the second subroutine or whatever will have a memory you know sorry the example i have in my head is completely unrelatable but when i speak this language i didn't pick this language. You didn't pick this language. We all studied this language. This language has like blood in it, right? This language has the Norman invasion in it. This language has like the Germanic tribes in it. This language has like, you know, French haughtiness in it, whatever. And like all of the history of the like conquests of the English folks throughout time and when America split off from England and all of the, all of history is like inside the language that I'm speaking. And I don't even have to be aware of that, right? But it's like there, the way that I think, you know, if we want to get all like post -colonial and stuff or whatever. Just like, I've been infiltrated by the history of the conquesters, you know. The same thing is true with the stack, right? I'm reusing the space. Stuff is there from before. I can rewrite it. In the moment I rewrite it, it's like becomes my own thing or whatever, something I got, fine, cool. But if I don't, I could read what was in the stack before. So there's always this little moment where you, the coder, could write something interesting, where you're like, I want to see what came before me, you know. And so it doesn't actually, it's not actually undefined behavior. It's just like funky, you know. Anyway, so undefined, yeah, exactly. Like you, the C developers don't know what will happen, but I know what will happen, you know, right? So, like, we could make a weird little prediction like that where I could be like, watch this. I'm going to call this thing and now the variable is going to be set to 69, even though I never said it to anything, you know? Boom. You're right. Okay. Not that relevant, but to say either I'm nesting or I'm popping, nesting or popping. Nesting goes down, popping goes up, and that's it. Okay? And then the final part of this diagram is that when I am deep inside of that subroutine and the developer makes a mistake that allows me to write anything I want into the stack, I can now go and rewrite that colonial history of everything that happened before. I can sit there and edit megabytes of the stack. And if I do a good job, the code might not actually crash. If I do a bad job, the code will crash. But if I write just the right stuff in just the right way, and I'm really clever about how I little fingered my Game of Thrones game thing here, whatever, I can totally screw with it just the right ways. And that's what we're going to do in this class. All right. And so for the first argument, I actually, like, now that I'm like further along you know, like that. It's great for learning, like, in practice, the stuff we do is way more sophisticated, but it anchors on this exact concept, and it will always anchor in this kind of concept. And so, like, we're going to wrap our head around it in the right way so we can abstract into the modern shit. But here's the idea. I'm going to be controlling the stack. If I can control the stack, then I can control the old base pointer, which isn't worth much, but I can control the return address. And that's fucking worth a lot. I can also control the arguments, which is also kind of quirky sometimes. So I can like set arguments seven, eight, and nine or whatever. Okay, you with me? All right. I got like 10 minutes, I think, in order to, let's just like look at some examples. Yeah, here's a 64-bit binary. It's just going to like add a bunch of things. Here's a call me, setting up a frame. Let's just like take this link. Jump into my hacker box. Yeah, baby. We all got them. All right. This is calling conventions. Gett. CHMod plus X Admi. Okay. Admi did shit all that I could see. That's okay. It's a very simple program. Let's take a look at what it does. SeekMain. Okay. All right. It's already telling me. We are inside a main. Let's just set a breakpoint main. Screw this little pen. Okay. Now we can look at this and know everything that's going on. Step one. I am inside of Maine. Okay. I don't know what NBR64 does. I'm inside of I am going to push the old base pointer. Now, you'll note that the old base pointer when I'm in Maine is friggin' the number one. That is to say, before Maine, they didn't have base pointers. Base pointers are for coders. Base pointers are for local variables. Before Maine is something else. Okay, fine. That's like what happened before the Big Bang. I don't know. I'll never know. But here inside of this, universe, I've got physics and so. All right. We're going to save the old base pointer. There it is. You can now see it on the stack. There's my old base point. It's a stupid base pointer that we mortals don't understand that base pointer, but it's the number one. I will now set up a frame for main. How do I do that? I'm going to move the base pointer to the stack pointer. Now I've got a fresh base pointer, and it is the stack pointer, and it's right here. If Maid needs any local variables, I can just put them here at the stack pointer. Maine doesn't need any local variables, fine. And you'll note that when Maine doesn't need any local variables, instead of the instruction leave at the end, it's a pop RBP. So I'll see a leave is just the Sox and Shoes theorem. it's like two instructions in one without the leave they'll just put a pop in there. It's just slightly more efficient to do one thing instead of two things. So it's basically saying I wore flip flops I didn't wear any socks or whatever. So all I got to do is just take off my flip flops there's no socks involved. Or maybe it's saying I'm only wearing socks and no shoes and all I got to do is take off my socks. I don't have to involve any shoes because there was no local variables. Okay. Now, ESI. why is that one important that's the first argument so what is this thing going to do it's going to consume the number 420 second argument edi it's going to consume the number 1337 and then it will call ad me okay cool so 420 is now the first argument boom one through three seven will now be the second argument, boom. Now we're going to jump into ADMI. What will ADMI do? It's going to take the next instruction here, push that onto the stack so that I can return to the instruction I've just highlighted. So whenever I'm done with the ADMI function, we're going to come back to this instruction. And then I will jump into the ADMI function. Yeah. Why is it E sometimes and why is it R sometimes? It will, R means 64 bits. E means 32 bits. So when I made the C program here, I must have said int, x equals 420. Ints are 4 bytes. And so it called it E instead of R, because to almost let me know, it's like a 4 byte number, not an 8 byte number. And I said long X equals 420, then it would be an RSI either. So it's referring to the same register, but it's only using 4 bytes of it, not 8 bytes of it. That's the, so E and R just like, it's kind of like my kids call me dad. You don't, you know. It's still the same dude. Sometimes you can call me a professor, Andy, or whatever, something like that, but you're not going to call me dad, all right? That title is reserved, not for you. But refers to the same dude. Okay? We are going to push the address ending in 5F onto the stack. Let's step. Look at that beautiful stack. 5F right there. Okay? Now, we are entering into this thing. you'll note Radair 2 is telling me a whole bunch of information here in this kind of like dark blue, light blue pattern what's the information it's telling me? It's saying argument one to ADMI which by the way it's saying ADME consumes two ints it calls them 64 Ts which is wrong we just saw it at 32 but whatever it consumes two ints argument one is in RDI argument two is in RSI argument two is in RSI I. Okay, cool. So, like, I can see at this moment, that must be value one. That must be value two. 420 plus 1337. Let's find out what happens. Okay. I don't know what NBR 64 does. And my promise to you is that if it wasn't on my list, you don't have to care. So NBR 64 probably does some sort of some. I saw no effect in any of the registers. All right. So push RBP. What will that do? notice E30 is where Maine had local variable. Maine didn't use it, but we're going to remember our old base pointer. This is layer two of the onion. We're going to remember the old base pointer. So what did I do? I wrote the old base pointer into the stack. There it is. So there's the old base pointer. There's the return address. There's the main's old base pointer. But that's, you know, two layers away from me. I can ignore all that. I will now copy the base pointer to the stack pointer to make a whole new frame for inside of, you know, the subroutine. So I copied this to that. All right. This is, if we want to see it with the burger or whatever, you know, that was doing this. We are now exactly at this spot. Yep. Right below. The reason I wanted to be left to right or whatever is to the left. Stacks grow down instead of growing up. But this burger makes you feel like it grows up. So that's the only downside of the burger. It should either be an upside-down burger, which doesn't make any sense for humanity, or probably left or right. So soon it will be a kebab shop. Okay. Now we do stuff. Everything between here and here is stuff. All the other lectures, all the other weeks, I've said ignore everything that isn't here. to see what the function does. This week, I'm going to ignore what the function does, roughly, and only look at the stuff outside of that, because all I care about is the calling convention, the stuff that happens in every function. I lied. Immediately, let's just do a little reversing or whatever. Argument one gets copied into the stack. Where in the stack? Base pointer minus 20. Okay, base pointer is here. So at E20 minus 20, so at E00, we're going to write this into the stack. Let's step. Now, I can't see it because they didn't actually move the stack pointer. There it is. That is the 13337. That was from EDI. Okay, cool. Next line, we'll do the same thing. Four bytes to the left of that will be a copy of argument too. There's the copy of argument, too. You'll notice that the first thing it did is it copied from the reference registers onto the stack. That's a compiler choice. Like, it could have just used them in the registers. But the reason the compiler likes doing that is that you don't want to waste all your registers. Registers are really valuable territory. You want to be available for the program to do whatever. So it copied those arguments into a local stack frame and now can use the registers for other crap. Okay. So that's a choice the compiler made. It will now move it from the stack to the A register and then move that into another location. Okay, fine. And then remove the other one in the A register and then add those things to that location there. That was the sum of 69 and 420 or 420 and 1337 or whatever stupid numbers omit did. And now I was going to copy that back into the A register. Now this is part of the calling convention. It wasn't one of my layers of the onion, you know, but it's an important sentence. which is return values are stored in the A register. So what is the sum of 420 and 1337? 420 plus 1337 is that. Hex of that is 6D. And you will see that the A register has 6D in it. And when it looks here, it looks like DD 06 because of Little India. All right. Now back to the real stuff. You'll note, the compiler chose not to move the stack pointer. So again, instead of the leave instruction here, all they needed was the pop. They never put on their shoes. She ran around in their socks or whatever. They weren't going to go outside or something. So all it did is remove my socks then. Pop RBP. Now, what will pop RBB do? Let me put the stack back where it was. The stack register is literally right here right now. Okay. What the fudge? Okay, there we go. Good. Okay. The stack register is pointing at this thing. It is now going to restore that as the new base pointer. So it's almost like saying the moment I like close the door in that hotel room in Vegas, it's like my house, my head is already thinking about the pillow at home I will have after this plane flight. So it's like at this moment, my new base of operations is my house in Newark. I will feel unsettled until I get back to my house in Newark. That's the moment of I have left the vacation. I'm now going home. Here it is. I've now restored my base pointer. Now I say, now the local variables instead of that function mean nothing to me. If I left anything in the hotel room, fuck it, it's theirs. Call it a tip, you know, whatever. Not going back. Now look where the stack pointer is. The stack pointer is pointing at an instruction address. Which instruction address? The one I'm supposed to return to. Step. Here we are. We are at the line after ADME. What has changed? Well, a few things. One, the A register now has the sum of 420 and 13337. Hooray. Okay. Now, now I'm at the end of Maine. So I'm going to do that whole routine again to leave Maine, which takes me into parts unknown. I'm going to restore the base pointer to like some sort of weird transcendent God being. All right, fine. Ah, now my base pointer is the number one. Not even a valid address. Oh, all right. Now I'm going to return to whatever happened outside of Maine. Here. Okay. Fun. Out in the land of, this is like Neo being unplugged from the Matrix or whatever. Like, I was in simulation land. Here's your truth, Neo. There is no base pointer. Your local variables, they're all an illusion. Yeah. This is G-Lipsy -Start Main. So, like, it's where G-Lipsy is going to get your program running. It just does all sorts of crap to get ready to get into your program, loads the red address of your program into racks, and then call racks. And then just has crap out here. All right. That is all of calling conventions in three easy lectures. you know, we didn't do the 32-bit version or whatever. We start hackery on Monday. Oh, wait. Let me, let me like solicit you guys real quick. I think for assignment one, I think I want to make you do some like something creative around calling conventions. So the first version of this, I just like write me a program and assembly that uses the calling conventions, the 64-bit calling convention and uses the 32-bit calling convention. You can do that. but then you get into like how to write assembly or whatever something like that so I almost want you to make me a story that shows me that you understand calling conventions I don't know but maybe that's like too kindergarteny I don't know I just want you to be able to teach it to somebody else right so like can you explain calling conventions to someone else that's your job so like yeah that prove to me that you could teach calling convention to somebody else. Oh, sit down a friend, record the video. There you go, yeah, yeah. Sit down with a friend, record the video, whatever, something like that. I think that's what I want out of the assignment. Is that stupid? I don't know. All right. What? There you go. There you go. Yeah, yeah, yeah. Yeah. Maybe we're back. All right. Good. We'll be fine. We'll be fine. All right, just a quick question. What kind of source are you using to on the binary? Are you using a term? What do you mean source?
Calling conventions pt 3, arguments.
From Andrew Novocin February 21, 2025
15 plays
15
0 comments
0
You unliked the media.
Zoom Recording ID: 4159319948
UUID: NmiEy3fHT7qAGGMXiz4p/Q==
Meeting Time: 2025-02-21 03:28:16pmGMT
- Tags
- Department Name
- ECE
- Department Division
- Date Established
- February 21, 2025
- Appears In
Link to Media Page
Loading