Uniformly a random and then you get a random variable, which is the length of this longest increase in subsequence of your random permutation. In a theorem that Big Dave's and Johansson proved is that after you look at large n, you subtract twice the square root of n and you normalize by n to the 1 over 6. And then the limit you get was called tracividum distribution. So that's the limit for the largest eigenvalues of the Gaussian union transform. That's another appearance of random matrix object in object built out of the permutations. Now, why do I mention that? Well, I mentioned that because, well, original proof was of course different, but if you look at one of the modern ways to prove this theorem, maybe the shortest way to prove this theorem, then the proof would proceed through four steps. First, you will use some combinatorial algorithm called Robinson-Schanstedt bijection, which will map your problem of computing long increase in subsequences to some object, to some problem of computing the asymptotics of ensemble of, you know, planche or random young diagrams. So you reduce to young diagrams by these Robinson-Schanstedt correspondence. Well, then you have young diagrams with n boxes where n was the size of your permutation and you really don't want this discrete parameter n, what you do was called Poissonization. So you replace this discrete n by continuous parameter theta by sampling n according to Poisson distribution with this parameter theta. Now you will have some ensemble of random young diagrams at this point, which you will treat as a determinational point process. So you will manage to compute something as minors of some matrices. And finally, this determinational point process you will analyze using double contour integral representation for the kernel of this, of this determinational point process. So that's how you would prove this Big-Difte-Johanneson theorem. Well, on the other hand, you know, in the random sorting methods, it turns out that you can find analytics of these four steps. And that's how our proof with Moustasi works, actually. Well, all of them are somewhat different. So, you know, Robinson-Schanstedt is different, contour integrals are different. But conceptually, you know, these are the same four steps that we find after proper modifications. Okay, so what are these four steps? How does it really work? Well, first of all, what replaces this Robinson-Schanstedt algorithm? There is a very nice bijection which was developed by Edelman and Green in 87, which maps sorting networks that we are interested in to another interesting object which is called standard staircase shape young tableau. Well, first of all, what is this standard staircase shape young tableau? Well, staircase shape young diagram, this is this young diagram of this shape. So, this is just a collection of boxes in rows where in the first row you have n boxes, in the second row n minus 1 boxes, et cetera, up to 1 box. So, here is one example. So, it really looks like a staircase, and that's why it's called staircase shape. Okay, now that's a young diagram, and you fill it with numbers which are integers from 1 to n in a monotonous way. So, the numbers will be growing along the rows and column, like this is one possible filling. And you will fill with numbers from 1 to n where n is total number of boxes. So, all the numbers will appear, each of them will appear exactly once, and they will be strictly growing along the rows and columns. And that's what is called staircase young tableau. Again, there are, finally, many of these young tableau. Turns out that their number is precisely the same as number of sorting networks that are already Stanley proved. And what Edelman and Green proved, actually, they constructed an explicit algorithm which provides a bijection between these two objects, between sorting networks and between these random, you know, young tableau. Now, while there are two ways in this bijection, you can start with a sorting network or you can start with a young tableau. So, if you want to start with a sorting network, then the algorithm is really a version of this Robinson-Chanson-Kleuth correspondence. So, you modify the rules of these Robinson-Chanson-Kleuth correspondence a little bit, and that's, you know, what you get there. So, I don't want to get into that. In the opposite direction, the correspondence is a version of so-called Schuessel-Mangerz-Zhodotaka. And then it's closely related to this algorithm that we saw in the limit as well. So, what are these versions? It's very easy to explain. Again, it's related to some slidings that you do. So, okay, so what we want to do, we want to start with a staircase, young tableau with filling with numbers. And what we want to get as an output, we want to get sorting network. So, how do we get it? So, we start with our young tableau, like this one. You locate the maximal entry of your young tableau. So, here it was six. That's the maximal entry. Now, you write down the column number of this maximal entry, so it was two in this case. Okay, since it was two in your sorting network, on the first step, two will be swapping with three. Okay. Now, after you've located this thing, you can compute sliding path. So, the sliding path is a path which locates your maximum with the origin, so with this point. And the sliding path goes to the left and up, to the left and up. Now, how does it choose whether it goes to the left or up? Well, the choice is very simple. When it needs to choose between two numbers, like starting from six, you need to choose between two and three as your first step. You always choose a larger number. You would choose larger numbers until you reach the origin. Okay, after you computed this sliding path, you really do slide it again. So, you shift all the numbers toward the border of your young diagram. So, there's one, three, six. So, six disappeared, and one became here and three became here. And that's the new diagram that you get. And here in the corner, you actually don't care what will be there. You can just put zero. It is irrelevant for our procedure. And then you repeat. So, you again locate the largest entry. So, that will be five now. And the column number of five is one. So, because it's one, the second swap will be a swap of one and two. And here is the swap.  And you again locate the largest entry that's four. And it's column three. And that's the next swap. And then you do the slide and get the largest entry that's three. And that's in the column two. And that's your next swap. And then three. That's your next swap. And that's one. That's your next swap. And what Edelman and Green proved that it is indeed a bijection. We sorted networks. Well, our priority is not even clear that you get a sorting network. Why is it the shortest path which, you know, connects identity to reverse permutation? But, you know, with some combinatorics, you can prove that. That's true. So, that's the first step. And this step reduces our problem of starting a sorting network to starting these, you know, random staircase young tableau. So, that's the thing that we now need to study. Okay. Now, the second step that would be an analog of Poissonization in Big Dave Johansson theorem. Really, what it now does is a bit different, but it still moves from discrete setting into continuous setting. In this way, it is similar to this Poissonization. But there will be actually no, you know, Poisson random variables, but I still wanted to keep the name. Now, what we want to do, we want to change from this feeling with integers, which is our standard staircase young tableau, to feeling with real numbers. How do we do that? Well, we just say that, okay, we have inequalities, that the numbers should be growing along the rows and columns. Well, first we will have an integer subject to these inequalities. Now, let's have real numbers from 0 to 1 subject to the very same inequalities, that they're still growing along the rows and columns, like here. Now, of course, you know, if you know this thing, then you can reconstruct this thing. Instead of looking at the numbers, you can look at the rank of these numbers, and you are back to your integer picture. You know, how is it good? So why is it good for us? Well, first of all, in our limit transition, if we want to find some information about sorting networks, say near the border, through this correspondence, what we need to do, we need to understand what's happening with your random young tableau near the border, near this staircase. Now, when you switch from the discrete entries to continuous entries, it turns out that this local limit that we're interested in is just the same. So it doesn't matter. Some version of low-fledged numbers will show you that the limit is just same, so we don't care about that. Well, on the other hand, while the first object is hard to analyze, there is no exact formulas for that. For these objects, there are nice exact formulas, because it turns out that you can encode this object as a certain determinant point process. And that will appear in the next step. So what is the determinant point process? So we need, again, to make some identifications to see this determinant point process. So we have this filling of the table with real numbers. That is our Poissonized Standard Young Tableau. Now, we treat this Poissonized Standard Young Tableau as a growth process for young diagrams. So how do we do that? We just say that young diagram lambda at time t, this is the young diagram of this table, which is spanned by numbers, which are at most t.  And when you get t equals to 1, then you get an entire thing, because all numbers are smaller than 1. So in this way, your young diagram will be slowly growing in this continuous time t. So the boxes will be added one by one when you reach the time that you see the number corresponding to this time in your young tableau. Okay, so now you have young diagram. You have growth of young diagrams. In order to see the determinant point process, we will also identify these young diagrams with some particle configurations to some more standard way that is done by rotating your young diagrams by 45 degrees. So you get this kind of picture. And then projecting the border of your young diagrams onto horizontal line. And when you project, there are two kinds of segments, like down pointing and up pointing, and depending on which segment you have, you either put particle or you put a whole absence of the particle. And in this way, now, young diagram is encoded by the semi-infinite particle configuration. By semi-infinite, I mean that it's infinite to the left, but it's actually finite to the right. Just because to the right, you know, you will get these kind of up steps after a large time. Okay, now you have some particle configuration. So in this way, now your Poissonized standard young tableau is encoded by the collection of paths. It just shows how your particle configuration moves. So you start with the so-called step initial condition when your particles are all densely packed to the left, which correspond to this picture to the young diagram, which is really kind of a wedge. So you go like that and like that. So that's an empty young diagram we should start from. And then, you know, boxes will be added one by one, which means in this picture that the particles will be jumping to the right until you finally go to your staircase, which is the diagram where, you know, you have particle, hole, particle, hole, particle, hole. That's because in the staircase, well, you really go, you know, up to the right, up to the right, up to the right. That's the configuration that you have here. Now, you know, it turns out that this kind of object, this non-resecting path, this is a very nice object. It's really analyzed through determinational point processes. Yeah, because this, you know, this RSK version was mapping us to the uniformly random young tableau. After we did putonization, it's still uniformly random. There's nothing changed. Oh, you know, here's a theorem, again, in our article with Muster-Zirachman, which says that if you look at this non-resecting path and if you look at, you know, we don't care actually that at the very top you end up with this particle configuration. The theorem will be all the same. Well, a little bit different. The formula will be a little bit different, but conceptually, it will be the same theorem. Now, no matter what you end up with, the collection of the jumps to the right of your path, this forms a determinational point process. And we have a double contour integral for the kernel of this determinational point process. Well, it is written here. Well, it is, you know, quite a complicated formula, but the most important thing is some explicit formula. Now, when you have explicit formula, no matter how complicated it is, you know, you can start working with it. And that's, you know, what we do here. Now, this kernel, actually, this, you know, can be found as a limit of certain object which was in the literature before. So, the kernel, as we find in our determinational point process, that is the limit of the kernel that Leonid Petrov, who I think is sitting somewhere here, obtained five years ago in his study of uniformly random laws and stylings of specific domains called trapezoids. And why that relation? Well, that's because there's actually a relation between laws and stylings and between what we are doing. So, if you look at the laws and stylings pictures, well, something like here on the top, so you try to tile, you know, with these lozenges, which are these rhombuses of three types, like this is one type, this is the second type, this is another type. You try to tile some specific domain like the one which is drawn here. Some people call it solitude domain. Some people call it trapezoids. So, essentially, you have, you know, straight line on the bottom and on the top you have some, this teeth. And you try to tile it with these lozenges, with these rhombuses. You choose one time uniformly at random. Then it turns out that out of this model of random timing, there is a certain limit transition into our model of non-intersecting paths.  Now, our paths, this is semi-discreet model because the particles are still there in this direction, but in the vertical direction we now have continuous time. There is some transition between, you know, discrete time and continuous time, which you can figure out here. And this kind of limit transition is similar to the limit transition that Alex Saberadine and Grigory Aschansky had four years ago when the article called, I think, Young Book Care or something like that. So, there is some limit transition which works there. Okay, now why is it good for us? Well, it's good for us because it's now well known that the lozenge tiling is a determinantsal. There is a general theory called Castiline theory, which tells that no matter what domain you are tiling, you always get detrimental point process if you look in the right way on this uniformly random tiling. Rick Canyon, for example, developed many things based on this observation. This is just, you know, an abstract theorem guarantees that this is a detrimental point process. Well, we want more. We want some control on the kernel of the detrimental point process. And here, you know, the article of Leonid is very important for us because he developed, you know, based on some formulas of inner meta for the measures given by products of determinants, he found double contraintical formula for this precise model of lozenge tiling and then we can do our limit transition to our non-resecting paths and a kernel for these non-resecting paths and then we can, you know, make our limit transition, you know, first link into sorting networks and then make an appropriate limit in sorting networks and then in the very end, after several steps and after some massaging, we will arrive at the limited objects that we want. Okay, so that's a summary. So what we saw, we are looking at this uniformly random sorting networks of large rank and we saw two kind of limit results. First of all, if you just look at the spacings between two swaps on the same level then after proper rescaling these spacings turned out to be governed by the universal distribution of random magnetic theory, this Godin meta distribution, which is bulk spacing of, you know, eigenvalues of symmetric matrices, or as Wigner says, model for energy level spacings in given nuclei. And if you more generally look not only on one spacing but on the whole local picture then this can be identified by an algorithm, Giordateca, applied to the universal object from the random magnetic theory, this time hard edge of eigenvalues of anti-GUI corners process. And the main tools how we get it is to Edelman Green bijection with young diagrams and then some double contour integrals which we managed to understand after poissonization. And that's it, thank you. Well, it gives partial indication. So what we established in particular that the limit object is the same modulo, this semicircle scaling. Now, of course this is, you know, if you believe that it doesn't matter which wires go near your point, that local limit is kind of completely decoupled from wires, you know, analogy in random magnetic theory will be that maybe eigenvalues and eigenvectors are decoupled. If you believe in that, then our results will tell you that okay, the spacings, you know, they are spacing, how do they change? They change just as one over square root of x times one minus x. Now, the spacings change like that and you look at something like let's open the picture.  So the spacings between the swaps go into the slope of this wire. And really, when you integrate something like one over square root of x times one minus x, then you immediately get arc sign. And that's the indication that you get, you know, the sine curve there. Of course, for that you need to believe in this kind of decoupling, which, you know, we cannot prove rigorously, but at least, you know, that's some indication that, you know, the sine curve appears. Well, our results do not say too much. Well, the original conjectures they say a lot about the permittahedron. So where are these conjectures? Yeah, these conjectures are implied by the general conjecture that the same authors made, which is the following one. So if you look, if you embed everything in the permittahedron, so you just treat permitation as an n-dimensional vector, then, well, this permittahedron really the sum of the squares of these numbers is fixed. So all the permittahedron lies on the sphere. And what's really the conjecture is that, is that this shortest pass between these two points on permittahedron, they're close to these circles just on this sphere. You have just n-dimensional sphere and you just have large circles on this sphere. So there are many of these circles, so there is some randomness which remains, but the sine curves on this circle, this, you know, circle which you observe here, that is just indication of this more general conjecture, that the shortest path is close to the circle. So this is related to that. Now, in our asymptotic results, again, this fact that you need to rescale by this semicircle density, this again relates to the same circle, we see these randomative distributions. Well, I'm not sure what it says about permittahedron. Yeah, that's true, that's true. Yeah, so this circle is precisely some slice of this permittahedron, that's correct. But the swaps, that's kind of how locally you move in this permittahedron. And it's something about local geometry, that's true. Like, when you look at the uniformly random, maybe, not really uniformly random, I'm not sure how to say. Yeah, yeah. I know about that result, but I can't say I fully understand that result as well. I mean, it's some miracle. High swap, like these... What does it mean? High swap, because in each vertical line there is only one swap. But that is just the same swap process, I don't fully understand. Because each time there is only one swap, so there is no really well defined the top one, that kind of all the same. Yeah. Well, there might be... I don't think that anybody looks into that. But, you know, there might be a nice approach. I don't know, unfortunately. That's a good point. Maybe it better explains what... Maybe, yeah. I will look carefully on that, thank you.


You know I definitely take pride in it. I take pride in having a role in this team and you know that includes having to know you know a bunch of different positions. And what it takes is really just you know beating your playbook and paying attention because you know at practice you're not going to get every rep but you got to be locked in and see the adjustments and corrections you know and meetings after and be ready to apply them even if you haven't actually done it on the field yet. Yeah it can be tough but you know it's a challenge that we have to take you know we got a lot on our plate and that's what it's expected of us at receiver and you know just in the NFL in general. So you know I take that I don't take it lightly and so you know I try to do my best to be able to step up and play fast you know at whatever position I'm at. How different are the positions? The three different positions that like the difference between shortstop and second base or something like that? I don't really play baseball so I don't know but I mean it's all receiver at the end of the day it's more just you know understanding the concept you know the big picture what's going on in every play and that can really help out a lot. If you just know what the big picture is and you know what the goal is that we're trying to accomplish with every play you can you know plug in in different spots and be able to make it work. Yeah it's huge you know seeing how excited guys get you know when I am able to make a play you know it feels great. I feel like you know it shows you know how you know some of my teammates feel about me and how coaches feel about me and it's just it's a confidence booster no doubt being able to see guys get hyped up and excited for my own success.  A little bit of both you know I wouldn't say comfortable but you know I feel good about my place on the team and my role and what's asked of me but I feel like I have to have the mindset you know that you know nothing's promise nothing's given I gotta go you know earn it every time I'm out there. You know really throughout the week is just you know building that game plan you know we'll figure out you know what we're going to be running. You know towards the end of the week once everything's kind of in brought together we've been able to look the film and you know lock down you know what our plan is but you know how our mindset is it doesn't really matter you know what the play is it's about the players and them executing the plays. Yeah I mean I guess it's something we should could definitely improve on you know that just something to work on from there and we're going to try to improve in every aspect of the game. Yeah definitely I was I was hype after that play on that block you know it's that's what's asked of us here you know at Tennessee is you gotta be able to block and I feel like that's pretty cool thing you know to still be able to do in the NFL. With a lot of you know teams you know passing a lot more and you know we definitely take pride in being able to finish finish runs and finish our blocks and let Derek get out there and score. I don't know anything about Lucy but I'm a huge you know dog fan I got my own dog I rescued him about five six months ago. He's about to turn one in November so definitely go out there adopt dogs rescue dogs because they need it they need families you know that care about them and they need you know people are going to take care of him and treat him right. Yeah I mean I just when I was out there I was really just thinking I got to execute and that's the biggest thing is you know I did have another opportunity and you know just you know what was asked of me I knew what I had to do to make those plays and you know Ryan gave you know good passes good balls and I just I feel like it's not really more like rise to another level as much as you know I'm just trying to be there to help the team win. Yeah I mean you know it's a big part of just being in this league I feel like you got to be able to do add value in so many different ways and that's something that you know I want to be able to do and you know I do take some pride in that and being able to be reliable for this team to have a direct impact on the game and you know help the team win that's kind of what my thought was coming in to the NFL coming here to Tennessee is just being able to have an impact on winning games and you know I'm glad you know I had an opportunity to do that this past week on Monday and looking forward to doing it again.


In a legal filing Thursday night, the Biden administration sided with this man, even though its own office of the director of national intelligence previously wrote, quote, we assess that Saudi Arabia's crown prince Mohammed bin Salman approved an operation in Istanbul, Turkey to capture or kill Saudi journalist Jamal Khashoggi, unquote. At issue was a 2020 lawsuit against 37-year-old Mohammed bin Salman or MBS and 28 others in D.C. federal district court, accusing them of, quote, acting in a conspiracy and with premeditation to kidnap, bind, drug, torture, and assassinate Jamal Khashoggi, a resident of the U.S., who wrote for The Washington Post at the time. The 2018 murder took place at the Saudi consulate in Istanbul, Turkey. Khashoggi's body was dismembered with a bone saw, one source told The New York Times. His remains were never found. Now, MBS denies ordering the murder, but then candidate Joe Biden did not believe him, saying it shocked him to his very soul and would change how he as president would treat the Saudis. Khashoggi was, in fact, murdered and dismembered, and I believe in the order of the crown prince. And I would make it very clear we were not going to, in fact, sell more weapons to them. We were going to, in fact, make them pay the price and make them, in fact, the pariah that they are. But as president, Mr. Biden did decide to sell more weapons to Saudi Arabia, $650 million worth in 2021, and then earlier this year met with and fist bumped MBS. Biden said he brought up the murder in their meeting, but it clearly annoyed him when we in the news media focused on this. I keep talking about something that matters. I've been asked a question that matters. This week, the Biden Justice Department says it sided with MBS against the lawsuit because MBS is now prime minister, quote, the sitting head of government and accordingly is immune from this suit per precedent and international law. But that promotion to prime minister by his father, King Solomon, who would normally hold that title. That promotion came last month, just a few days before the Biden administration was supposed to weigh in on this immunity issue. As Fred Ryan, the Washington Post's publisher and CEO noted in a statement Friday, quote, while legitimate heads of government should be protected against frivolous lawsuits, the Saudis decision to make MBS prime minister was a cynical, calculated effort to manipulate the law and shield him from accountability. Ryan says Biden was essentially, quote, granting a license to kill to one of the world's most egregious human rights abusers who was responsible for the cold-blooded murder of Jamal Khashoggi, unquote. It is worth noting, though the court did invite the Biden administration to weigh in on this issue of immunity, the Biden administration did not have to do so. They could have stayed silent. The U.S. has a long and shameful history when it comes to American presidents going along with Saudi human rights abuses, because they control so much of the fossil fuels to which our country is so addicted. But there's only one politician who promised he would be different, who pledged that he would make this thug a pariah, who made his stark morality on this one man such a vivid campaign issue, and that's Joe Biden. You just listened to a very powerful rebuke of the Biden administration after they decided to kowtow to the murderous Saudi Arabian regime. And I don't usually say this, but good job, Jake Tapper. You actually crushed it there. And this gets even more embarrassing for Joe Biden when you consider the fact that, according to the Wall Street Journal's Middle East bureau chief, Michael Amman, Mohammed bin Salman privately mocked Biden and made fun of his gaffes and even questioned his mental acuity. And yet the Biden administration literally lets him get away with murder. Refusing to do even the bare minimum, just staying out and letting Khashoggi's family potentially seek justice legally or not selling weapons to Saudi Arabia. None of us are advocating that we go to war with Saudi Arabia. That's not what we're asking, but we're simply calling for the bare minimum so we don't further embolden this murderous regime. But we won't stop doing that, even though Biden said he wouldn't sell weapons to Saudi Arabia. He's doing that because, well, they're used defensively and not offensively, which is something that you can prove. And given how Saudi Arabia has used our weapons and training to do a genocide in Yemen, I'd argue that I don't believe what the Biden administration is selling us. As the Washington Post reports, as global attention focused on Russia's invasion of Ukraine earlier this year, the Saudi-led coalition carried out more than 150 airstrikes on civilian targets in Yemen, including homes, hospitals, and communication towers, according to the Yemen data project. It was the latest uptick in bombing during a grinding and often overlooked civil war that has appended the lives of Yemeni civilians for the better part of a decade and spawned one of the world's most severe humanitarian crises. Hundreds of thousands have died from the fighting or its indirect consequences, such as hunger the United Nations says. The devastating air campaign alone carried out by a Saudi-led coalition has killed almost 24,000 people, a number that includes combatants and nearly 9,000 civilians according to conservative estimates by the armed conflict location and event data project, which monitors war zones around the world. A new analysis by the Washington Post and Security Force Monitor at Columbia Law School's Human Rights Institute provides the most complete picture yet of the depth and breadth of U.S. support for the Saudi-led air campaign, revealing that a substantial portion of the air raids were carried out by jets developed, maintained, and sold by U.S. companies and by pilots who were trained by the U.S. military. But yet Joe Biden won't stop selling them weapons, won't stay out of it so that way Khashoggi's family can seek justice, and he has the audacity to fist bump this dictator who is a murderer who makes fun of him behind his back. It is so embarrassing on so many levels, and it's so bad that fellow corporate Democrats like Tim Kaine are calling out Joe Biden. In a press release, Tim Kaine writes, as disappointing as it is that the U.S. has been unwilling to hold MBS to account for the assassination of a U.S. resident journalist last night's announcement by the State Department is even more egregious. The case is a civil suit filed by the friends and family of Khashoggi in the hopes of acquiring even a modicum of justice from the Saudi defendants. The U.S. is not a party to the case. The Saudi defendants have full opportunity to defend their own actions and the federal proceedings. The court offered the administration the option to express an option on the question of whether sovereign immunity doctrines protect MBS from the suit. The administration had no duty to take a proactive position and could have simply refrained from doing so. Instead, it has chosen to take the side of the party that our own intelligence agencies have concluded is responsible for the murder and is standing against family members seeking recompense for this gross injustice. And also something that I don't say very frequently, good job, Tim Kaine. I agree with you. So the Biden administration has done something so egregious that individuals who don't usually call him out and criticize him this sharply are calling him out. That is genuinely beyond reason. And I just I don't know what to say, honestly. I guess the silver lining is that perhaps this will renew calls for Congress to use the War Powers Act to end U.S. complicity with Saudi Arabia's genocide in Yemen. And as Common Dreams explains, in June, 48 bipartisan U.S. lawmakers introduced a War Powers resolution to end the nation's unauthorized involvement in the Saudi-led war. The following month, Senators Bernie Sanders, Patrick Leahy and Elizabeth Warren proposed a measure in the upper chamber. Interviewed for an intercept article published on Monday, U.S. Representative Ilhan Omar, one of the 48 co-sponsors of the House resolution, asserted that our foreign policy should not be based on a dependence on oil or the geopolitical whims of foreign despots. It should be based on the rule of law and human rights. Yeah, very well said. And let me remind you that last time when Congress passed the War Powers Act to end the U.S. support for Saudi Arabia's genocide in Yemen, it got the Trump's desk and he vetoed it. So we have now another administration refusing to stand up to this murderous dictator. And again, we're asking for the bare minimum here. Stop giving them weapons that you know they're using against innocent civilians. But we can't even get that. Can't get justice for Khashoggi. Can't get justice for the people of Yemen. And it's all because of oil, essentially. It's just so disgusting and beyond the pale, but very predictable for U.S. presidents who have been too afraid to stand up to people who are supposed to be our allies.  Hey listen up, before you purchase gift cards for your family members from Netflix or Amazon, why don't you support a streaming service that doesn't exploit their workers? I'm, of course, talking about Means TV, who's having their annual Black Friday sale where you can get one year of Means TV for 50% off by using the code comedy is illegal. For those of you who don't know, Means TV is the world's first worker-owned streaming service featuring anti-capitalist documentaries, shows, news, and independent content creators like myself. Here at Means TV, we don't have some corporate overlord telling us what we can and can't say or do. We own the means of production. The content is ours. We are a democracy and therefore to support us, you're supporting a worker-owned co-op. So if you want to sign up, that's means.tv slash join and enter the code comedy is legal for 50% off of an entire year subscription. Listen, leftist propaganda is the gift that keeps on giving. So by enlightening one of your family members, you could be changing the world potentially.


Think climate, think change. Every second, every minute, every day, our world is changing. Hey all, Scali.p here, and this is what I have committed to do. I've committed to taking a reusable bag to the supermarket whenever I go shopping, thereby using less plastic, which, as you know, is very harmful to the environment. This is my answer to the question, climate change. What can I do? What do you do? Think climate, think change. A message from the government's information services and the Ministry of Sustainable Development.


I want to do a little review on this 24 karat gold colloidal water aka colloidal gold Not that many people know of colloidal gold and colloidal silver and I would say colloidal silver is probably more well-known Versus colloidal gold of course the only thing that shows up in the news about colloidal silver is a man taking way too much And he turns blue. I think they actually might be trying to scare people away because colloidal silver is supposed to be very Very very very good for you. It's more of an antiseptic. Apparently it's a natural antibiotic that your body doesn't build resistance to I can't prove that but anyways colloidal silver is much more well-known But colloidal gold is a lot different not really something you use to kill germs to help you come back from sickness to clean out Your body. It's more of a kind of like a supercharger giving you energy. It's also supposed to be a new tropic


All right, so we need to dive right in and make sure so where we left off a week and a half ago was on buffer overflows, so we covered a number of attacks and your next homework assignment you will be trying to find more and really some programs. We'll talk about that on Wednesday, so sit tight. That will be an individual homework assignment, so and part of this assessment is studying one of the most classic security problems today, which is a buffer overflows or overwrites, so it's actually an incredibly common vulnerability, so we're going to kind of look at it historically and look at the progression of buffer overflows and specifically not only how to find them, but how to exploit them to gain code execution inside of a process, so and as we'll see, we'll then kind of ratchet up these security mechanisms, so we'll say, okay, what about the SLR now? How do we get around that? What about a non-executive people stack? How do we get around that? For now, so we're taking kind of a historical approach here, but there's still, you know, even though we're looking at binaries without all of these fancy protection mechanisms, hey, there's a lot of binaries out there that run on routers or other embedded devices that don't have these security mechanisms, so these are incredibly common, and be even most of the heap overflows, all of these memory correction style vulnerabilities all stem from the same idea of overriding bounds and memory.  So I feel like I already did all this. Okay, so, yes, okay, so but in order to understand what a buffer overflow or overflow overflow, sorry, is, we first need to completely understand the stack. All right, so a stack is essentially a scratch memory for function, but more specifically, what is the stack and how does it differ from a stack? It's memory, right? A stack is a data structure, abstract. Yeah, so a stack is the abstract data type of a stack. What are the operations you have on a stack? Push it, pop it, what order do things come out of it? Before it gets out, it laps out, right? You want to push things on, you pop things off, right? As long as you get the order straight in your head. So the stack and program is specifically a memory location, so it's going to be actually a segment of memory that's defined in the Elf header sections, which we saw that allows a program essentially to scratch memory. So why does a program need scratch memory? In other words, why don't we know in advance exactly how much memory a program uses and just allocate that and use it? Dynamics of the input data could vary, right? Depending on if you're parsing a one megabyte file versus a gigabyte file. What else? What if your data size is completely constant? Why do you need scratch memory for function calls? It does that. Do you need a scratch memory location to do that? You don't know how many function calls, right? So you've got to remember every function call that we'll see has to execute, and then after a function is done executing, what happens? Does the program just terminate? No, that'd be a horrible way to program. What happens when a function is done executing? It returns where? To the function that, or specifically the code that called it. So right after it gets called, that's where it returns. A function can be called from a hundred different places in a program, but when it returns, it only returns to that specific place where it was called. And this changes depending on the runtime of the functions you get. And then you can also, when you think about starting from the beginning of the program, all the functions that execute, can you have multiple instances of the same function on the call stack, i.e. can you have a function call itself? But you need memory for all of those things because each of those functions, if they have local variables, have their own local memory. So the stack is the answer to all these questions. It's essentially, it's actually a very basic component of low level architectures. And it starts at a high memory address and grows down. And we are going to draw the stack like normal people, or we're going to start at all f's at the top and go down to all 0's, yes. I would say the stack, that's architecture dependent with respect to the starting from a low memory i.e. when we go down. Yes, that part is how the stack operates. It needs to start one way and go one way, right?  But yes, definitely architecture dependent. And it's architecture dependent on how, what the ISA like R or X86 or MIPS gives you in terms of manipulating the stack. So for instance, X86 has a built in push operation, which takes the value of the register, pushes it on to the stack and decrements the stack pointer. So there's a dedicated stack pointer register. Whereas other languages, you have to manage it yourself, but you can still do it. It's the same idea. So, and this is super important. So in X86, the registered ESP holds the address of the stack. Right? So these ideas are very closely linked. You can't, the stack doesn't exist without whatever values inside ESP and the value inside ESP dictates where the stack is. So if I tell you the stack is at location 1,000, then you know that inside the ESP register is the value what? 1,000. Yeah, it has to be. Otherwise, it doesn't make sense. So the, so there's two basic instructions here, push and pop. They have very specific semantics when you do a thing that you just drill into your head because it's, you know, it's not hard and stuff you guys can all learn and remember this. Push the ESP means to decrement the stack pointer. So change the ESP register, then store the value inside the registered ESP onto the stack. So pop does completely the opposite. So pop is going to, working backwards, takes the value off of where ESP is pointing to, copies it into a register, so for instance, pop ESP takes the value where ESP is pointing to, puts it into EAS, and then increments the stack. Good? Stack experts? Can you say increment because it's building down on the stack? Increment, yes. Increment going down, so when adding things, you're decrementing the stack, and you're incrementing going up the stack. We'll see examples like this. So stack example, all S at the top. Clearly you could draw this either way. You could start at zero. It makes a lot more sense going down. I don't know why, I think I just looked at it so much. Any time I look at it the reverse way, it just looks wrong. And I've even heard of some monsters who start the stack on the left and it grows to the right. So the idea is, just like we said, if the stack pointer is pointing somewhere inside the stack at memory location 10,000 hex, this means that I must have, okay, well, I guess I don't know about that. This means that the stack pointer must have the value 10,000 hex inside there. So even just off of this point of having, okay, the stack pointer is pointing, has the value 10,000 hex, which means the current top of the stack is at 10,000 hex. What do we know about the memory addresses that are greater than that? What was it? It's fair to say the function calls are probably used data, right? It's used data because we know that anything that is 10,000 hex is the quote, quote, top all the top here is tricky because it's keep going down is the top of the stack. And if we add things by decrementing and going down the stack, then if we increment going up the stack pointer means that we're now into memory that is being used, right? These are things that are going to push onto the stack. So conversely, what do we know about the things that are lower than 10,000 hex? Garbage, right? This is, can there be, is it all zeros? No, not necessarily. We actually don't, as we saw the pushing and popping things off the stack only changes, changes the stack pointer and maybe puts values on there. But when you pop things off, you don't erase what was there. So you have garbage, which could be, in some cases, it could be useful garbage, depending on what you're trying to do. Listen up, we'll get into that later. So if we have the instructions, push ex and then pop ex. And so then if we have our registers, we think of, okay, what's the value inside ex? Let's say it's the value xa. We have ex, it has the value, let's say zero. And we know, because we talked about it, that the value inside the ESP register is 10,000 hex. If that's not the case, we've completely messed up. So when I'm going to put an arrow on push ex, this means that essentially you think that the program counter, or in x86, it's called the ex, the extended instruction pointer, is pointing to that value, which means the next instruction to be executed is that value. So if you're doing gd, you put a break point there. It means that when you do si for step instruction, it's going to execute that one instruction and stop on the next instruction. So it's going to do push ex. So what's going to happen? It's going to be hex, well, that's not right. I was going to say nine, but that's wrong. Four bytes? Why four bytes? The register is four bytes large. The register is 32 bits, which is the same as four bytes. It has to store onto the stack enough value for ex. So it has to decrement the stack pointer by four. So this will be fffc, which then moves our pointer down. Our imaginary, remember, this blue pointer is just imaginary. The blue pointer that was at 10,000 hex now moves down to fffc, because that's what's inside ESP. Then what happens? So are we done executing this? I'll store it. Yes, we need to store. So we only did half of our push ex instruction. We decremented the stack pointer, and now we need to copy the hex A, which actually we just talked about. It's four bytes, so it's going to be 0, 0, 0A, or maybe with the end in this A, 0, 0, 0, I don't actually know. But when we look at it as an integer, we'll interpret those four bytes as OXA, which is 10, 10, yes. Okay, now we're done. Now we've executed that instruction. Now we pop EDX. So what happens? Increment it. What do we do? What was the order that we did it? I'm going to push. We moved it to store. We moved and then stored. So when we pop, we need to do completely the opposite. Copy it into the register. So copy whatever's at FFMC, and copy those four bytes into the register EDX, which will change that to XA, and then increment the stack pointer by four. So now the stack pointer is going to point up at, yes, up at 10,000 hex. And just like we said, does anything, so that memory that we put onto the stack still remains in memory, that XA at FFMC. But in our program's mind, it's considered garbage, right? We can reuse and overwrite that address at will. So what was the equivalent? What essentially did I do semantically here with these two instructions? Copy speed. Copy what? You copied a kind of swapping. So you moved that from A to B. So, tricky that it's not a swap. I think swap would actually switch both of them. But yes, we essentially moved EAX into EES, right? So, and that's the stack. So this is the basic idea. And if you really understand this and centralize this on a deep level, you will find all of these stack-based, and actually all these memory corruption at overflow vulnerabilities a lot easier. So the main, one of the main uses of the stack is what we talked about of having function frame. So somebody was taking the piloter to refresh us. So what is a function frame?  Yeah, it's essentially everything that a function needs to execute, right? And so when you're writing C code, how do you, so if you want memory, how do you get memory? So if you want, let's say, 10,000 bytes of memory, how do you get that 10,000 bytes? Maloc. So you can call Maloc. And then what do you have to do with those 10,000 bytes when you want to free them? We call free. As we'll see, these are libc functions you're calling into, Maloc and free. But, so how come when you declare in your function, so you're writing a function in C, this is your function foo, and then you're declaring a character buffer of 10,000 characters. You put care, bracket, 10,000, bar. Do you have to Maloc that? You have to free that? Why not? Yeah, so we've asked for this as a partner, so it's a local variable of the function, which means that variable, the lifetime of that variable is only during that function's execution. When that function returns, that data is already not used. When we Maloc 10,000 bytes, we're specifically telling the computer, I will worry about how long this memory is valid for and I will be responsible for freeing it after I'm done. Because maybe you return that 10,000 bytes with that pointer to the 10,000 bytes from that function, which gets passed to another function and another function while you're using it. If you only need that 10,000 bytes for one function then why use Maloc? The reason would be if you don't know the size in advance and if you can't actually get the size, but that's another issue. So, yes. One of them goes in the stack and the other one goes in the heap as well. Yes, essentially that's the main difference. And the key reason is understanding that local variables don't need to be on the heap, but are on the heap for essentially performance reasons, as we'll see. It's incredibly easy to free these variables, whereas the heap has to do a lot more damage. So, the idea is who do you use, let's say the stack pointer to say, okay, the stack pointer. Well, another question is, so okay, we can say we can use the stack to store local variables, but when I write a function and I have my local variables of int a and character b and my queue deraille that we just called bar, right? How does the compiler actually compile that out so that every reference to a, b, or c grabs that local variable from my stack?  You are seeing that I have this function defined that I have variables a, b, and c. And local, local variables. And you see that I have a is equal to a plus b. How do you translate that out into assembly code? Yeah. It would be offset from like, be allocated at by the compiler or ESB. Yeah, so one thing is I could try to use the stack pointer as an offset, right? I could say, okay, this, so I'll know ahead of time exactly how many bytes so each function uses a different, but known at compile time number of bytes. For instance, like with an int, we know there's four bytes. I mean, you can just run sidewalls on all of these data structures to see what you need. And so you could maybe change the stack and then just say, okay, fix offset from the stack is always a, and here's variable b at a different offset. Why is that not a good idea? Because it doesn't change when you push and pull. Exactly. The stack changes during program, during function execution, because of pushes and pops, right? Because how many registers roughly do we have? Or does anyone know exactly the answer? That's the same question I know the answer to. It's like, general purpose registers. Six. Six. So what am I doing? This complex calculation that involves multiple, say 10, intermediate values and variables, which is more than the registers that I have. I just give up. No, I store stuff on the stack, right? On the compiler. I can store temporary variables on the stack. I know exactly where they are. I can pop them off when necessary. So for this reason, we don't want to use the stack pointer, an offset from the stack pointer, because the stack pointer is possibly changing. So this is where the idea of the base pointer comes into. So it's called base pointer in x86. The other way of thinking about it is the frame pointer. So it points to a fixed location inside the frame of the function. And then each local variable will be different offsets from that frame pointer, if I would say. I know that a will always be at ebp, which direction would it be? Down. It should be down, right? We'll see y in a second, but it'll be ebp-4 will be a. And ebp-8 will be b. And ebp-10,004 will be my huge buffer r. So this value, ebp, just like the stack pointer, dsp, it holds the current value of the current function's function pointer. So now we're going to go through a, actually, real example of a c program, a small c function that I've compiled, so you can see these different things. So here I have main, I have in a and b float c, so these are all local variables declaring this function. I'm going to set a equals to 10, b equals 100, c is equal to 10.45, a is equal to a plus b, and return 0. So we got through, and we're a compiler. So we need to basically calculate fixed offsets for a, b, and c. So I'm going to, and can we have, let's say if we have a and b, which are both ins, can I have a at ebp-4 and b at ebp-6? Why not? There's four bytes, those would be overlapping bytes. That should be an interesting problem, but yeah, that would be very bad, right? You have, I mean, that would cause massive problems. So I can say that a is at ebp plus a, and as we'll see, it's going to be a negative number, ebp plus b, ebp plus c, and then I can easily translate each of these instructions. I can say, well, set the memory at ebp plus a to 10, right? Rosalie, this is pseudo code, not real assembly code. Similarly, set the memory at ebp plus b to 100, set the memory at e, whatever, and then, so on and so forth, set the memory of ebp plus a to ebp plus a plus the memory of ebp plus b. And then when this gets compiled out, this actually is very straightforward. So the compiler and depending on your compiler options, depending on the compiler version, depending on, I don't know, the cycle of the moon or something, you'll get different results for the x86 assembly here. So for this example, ebp, it said a is at minus c, so minus 12, b is at ebp minus 8, and c is at ebp minus 4. Just where I decided to put things. So I'm going to ignore the prologue for now, but the exact code of this is a move constant a into ebp minus c, right? This is essentially the x86 assembly instruction that's exactly equivalent to the pseudo code we have. And similarly, move x64 into ebp minus 8, which is b, and move, what's this crazy value? It's x41273333 into eax. Yeah, it's 10.45 and actually flowing point format. So then we move eax. So why is this two instructions and not one? The second instruction is move eax into ebp minus 4. Why two instructions? The other two instructions are just one instruction. Move 10 into ebp minus c. Try to figure out the value from that progress, which is no d reference. If there's a d reference around eax, then we have that. So there's no d reference. So it's moving literally x412733333 into eax. And then that value is then moved into ebp minus 4. So no d referencing of that value. Good guess, yeah. Is there a limit to the size of obedience when moving into memory? Yes. So actually the real answer, well, the answer of anyone asking why a compiler does something is because the compiler decided to do it that way. And so we'll see many examples of that when a compiler chooses one instruction over a semantically equivalent instruction. And the answers of why this is why things change over time. The reason in this case is because you think this instruction has to be translated out into x86 code. So there's a limit when you want to use an immediate instruction. If you want to use an immediate move instruction with an immediate value of like, because that a has to be inside your instruction, right? So move that into ebp minus c, you know, you have to specify that it's a move instruction. You have to specify the immediate value to specify that you want ebp with a minus c displacement. So if you want to specify the whole 32 bits of this x412733333, that's already a long instruction. That's already four bytes of your instruction plus the move and then the target register. So you can't actually move a huge value directly into memory location. So yeah, but you know, the compiler could choose to do this in a hundred different ways. So it just chose to do it this way. All right. Oh, okay. So then we can see that move. So ebp minus four into eax. So that's c move eax into ebp minus eight. So that's doing it the other way. Yes, it's the other way. Move eia, sorry, I got those confused, right? Okay. So take b, move it into eax, add eax to ebp minus c and store it where? Then ebp minus c, yeah, onto onto the a value. That's it. That's the body of our function. So, so, and then we can step through this. I'm going to do this pretty quickly because I don't want to get too bogged down with the details here, but feel free. You know, you should be able to walk through each of these instructions and then draw and think about how the stack is changing. And it may seem silly, but this is something that I do on almost every like CTF challenge where I have a stack and I need to figure out, okay, where am I and where am I overwriting and what else is above me, like drawing it out really helps me every single time. So, okay, so the idea is, so this function starts executing. So, we know the stack pointer is at 10,000 hex because I told you that it is, and it is in this diagram, and we know it is because 10,000 hex is inside the registry ESP. What's currently in the ebp register? How do we get here? Not here in this room, not like don't rethink all your life choices that brought you here to this room on this Monday, but how do we get to start executing this move instruction? Yeah, somebody else called us. So, even though we're the main function, if you look at this, there's actually a lot of things that happen in your binary before you actually get to the main function. So, somebody else called us. So, what's inside the ebp? The previous function that called us base pointer. So, yeah, okay, so before, sorry, this booker is not working though. Okay, so before we get here, right, we don't know what's inside the ebp. Maybe it's something above us. I'm actually missing all the prologue here, and I'm upset about that, but we'll get to it later. So, what we need to do is set up our pointer, our base pointer, because we need it for all those offsets we just calculated. So, we know right now the top of the stack is free, so we set, we're going to move our stack pointer into the base pointer. So, now we're going to just copy the value that's in the stack pointer and copy it into the base pointer. So, that's going to put 10,000x into ebp, which means now we have two blue arrows, one at 10,000x to the stack pointer, the other at 10,000x to the base pointer. Was this in any way involved in any of the instructions that we actually wrote? No, did we say we want the base pointer? No, we just said we want a to be 10 and b to be 100, and a to be a plus for c to be that 10.45 and a is even a plus b. But as we'll see, the program has to have this prologue in order to set up the stack correctly so it can execute. So, the next instruction is a sub x10, so 16 from esp. So, it's going to move the stack pointer down 16 bytes, essentially doing what for our function? Space for local variables, exactly. It's essentially allocating 16 bytes on the stack for this function. How does it know 16? Well, the compiler decided that it needed 16 bytes. So, it needed, so we had a and b, so our both four, so eight bytes plus c is a float. How many is that? Another float is four bytes. A double is eight, I think. Pretty sure. Whatever, we'll say it's four. So, we have four, four, four, 12, so we're at 12. So, how do we get a 16 bytes? A is equal to eight plus b. What? The addition and operation. Well, we store it onto this, we store it directly onto the stack where a is. What was that? The compiler decided. Yeah, the compiler decided. So, it's actually a, for historical reasons, some architectures couldn't access or execute memory or something on a non-four byte boundary. And so, the compilers usually try to make sure that these things, like stack pointers, end up on four byte boundaries. So, I don't know. But it's not necessary. I mean, you could write a compiler that did this or your compiler could decide that that variable c that we have is never used, right? We just set c to be 10.45 and never use it. So, it could completely optimize that out. So, there could actually be less space on the stack than we think based on looking at the c code, which is important as to why we always look at the assembly code, like the c code could lie to you because you can think, though, that things are on the stack this way, but the compiler ultimately decides what goes where. Okay. So, we subtract then 10 in hex, which is 16 for the stack pointer, which means that ESP now points down at f, f, f, zero, while the base pointer still points up at 10,000 hex. We then are going to move 10 at EVP minus c, which is going to be at what, f, f, f, four. And then we're going to move hex 64 to EVP minus eight. We're then going to move that crazy 10.45 and floating point into EAX and then move that from EAX into EVP minus four. And then, okay, so now on the stack we have, we can see the exact memory locations of our local variables, A, B, and C on the stack. And now we actually do the calculation. So, then we take EVP minus eight, which is the B variable, which is hex 64. We're going to move that into EAX. We're then going to add EAX, which is 64, with EVP minus c, which is going to be f, f, f, four, which is our variable A. And so, that's going to add 64 to A, which is going to be whatever x 110 is. And we're done executing. So, you should be able to take this code and draw the stack. And I say, what's the stack like at this location, or this location, right? This is a key skill. All right, cool. So, review for some or introduction to function frames. But as we talked about earlier, function frames aren't key. I just wanted to ask, don't you know the time frame for the exams yet? No, that's a good question, but I'll decide very soon. Not before frame rate. I'll say not right after. We'll see. That's a good question. Okay, yes. So, we talked about this. So, we need local variables which need to be stored on the stack. What other information does a function need when it gets called? Arguments. The arguments to the function. How does the function return its value to the function that called it? Right? What was that? Yeah, so we need a return value. We need parameters. We'll need, as we see, well, we need, first of all, we need, the other thing we need is a breadcrumb. We need the return address, right? Because every instruction essentially you can think of it has complete exclusive access to the CPU. So, the CPU does not know that it's inside of a function executing. Right? That's just an illusion that we've created. All it knows is I'm going to parse that next instruction. I'm going to do whatever it says. I'm going to execute it. I'm going to go on to the next one. And I'm just going to keep doing this over and over again because that's what I do. That's my job. So, when we finally get to the end of a function that we talked about, there's a hundred invocations of the function through the program. Which is the function that we actually return to? So, we need I think of it as a breadcrumb or some way to say, hey, this is where you go after you're done executing. So, the return address. And local variables and temporary variables, as we saw so stacked, is super handy and used all the time. So, this is all in an abstract way. This is all information that a function needs in order to not only execute properly, but to return to whoever is calling it and give those values. How those values are passed and expressed, do you push the arguments on the stack? Do you put the arguments in variables? I'm sorry, not variables, they're not variables. Do you put the arguments in registers? What does a calling function guarantee about certain registers? Does it say that it won't change certain registers? Does it say that registers can be changed when the function is called? All of this is, there's no technical reason that one is better than the other. I mean, maybe they were back when things were first assigned. But essentially, this is why the important part here is the convention. It's a convention that, if you follow this convention, you could call a C program. Which is actually how you do super cool things, like call a C function from Python code. Because Python knows how to call into that C code and it can do that and then transform the values back. You can do the same thing as Java. You can call from Java into C code because of this calling convention. So, this is also something you need to burn into your brain. I mean, don't hurt yourselves, but this is something that is incredibly important is this calling convention. And so, actually, the must be stored on the stack is actually a misnomer. It has to be stored on the stack, the calling convention that we're talking about will. And the important thing is the convention varies based on the processor. So, different architectures have different calling conventions, x86 versus ARM, different operating systems. So, you have the same. So, x86, the calling convention is different on Linux than it is in Windows. The compiler is kind of the type of call. So, when calling, even in Linux, so, Linux x86, if you're calling another function, you use the Cdeco calling convention once we're looking at, but if you're calling into the kernel into a syscall, you use a different calling convention. I think it's called a syscall calling convention, but I actually don't know. So, these are all different. And so, you need to know what the language essentially that you're speaking is, otherwise you can't call a function. So, this is the main one we're going to look at is the Cdeco calling convention. So, the caller has to do these things in this order, otherwise everything burns. And this is again arbitrary, the ordering, all this stuff, but it's, it is the, it's like learning any kind of standard like IP or TCP that you learn. Like, it's not given down to us on high. People came up with this, decided, yes, we'll use this. So, the caller pushes the arguments onto the stack in right to left quarter. So, think of the stack moving down. So, the right-most argument would be the first argument pushed onto the stack. The next argument underneath that would be the second to right. All the way to the left-most argument is the last argument pushed onto the stack. So, this allows you, so the nice thing about this is it allows you to have functions with any number of arguments, right? Because you could just keep pushing, as long as you got the memory, you can keep pushing arguments onto the stack. So, why right? I mean, there actually is a good reason for right to left, but I don't want to get into it now. So, think about why right to left as opposed to left to right. So, the next one is they push the address of the instruction after the call. So, this is used as that break-crone. So, this is when the function that we're calling is done executing, it knows where to jump to after it's done. And that's it.  You just do this stuff, bang, call, good. The call lead, the person who's getting called, or the person that's a function, but the function that gets called has to, as part of its interaction here, has to save the previous frame pointer because they're going to create their own base pointer. So, they just save the base pointer of the person before them because we can see in this calling convention, the caller doesn't have to worry about the base pointer. The caller doesn't have to say that the call lead has to. So, the call lead pushes the previous frame pointer into the stack, then creates space for all the local variables, and then after program execution ensures that the stack is consistent upon return. Why is that important? I don't want to care anything about the implementation details of your function. I don't care if this function uses 10 memory bytes on the stack versus 1,000 versus 1,000,000. As long as you get it back to me, the stack in exactly the same place as when I left it, then I'm good and I'm super happy. So, yeah, this is actually a lot of interesting kind of design decisions at each of these levels about abstraction and how much, if you want to call a function, what information do you need? And puts the return value into the EX register. So, this is how a function returns a value from one function to the next. Cool. Questions? Yes? The all the registers that are stored in the stack are stored in the stack before it is called? The register values? That's, honestly, the answer is I don't know. There's a contract with each register value. So, clearly, you can see that the callee is going to clobber EX, right? So, before you call a function, if you have any important data stored in the EX, you've got to move it because it's going to go away. The other registers, I believe, yeah, I think it depends. Every register, I think it's defined whether a function, before it uses it, will store it and then use it again. So, that I don't know. As long as we, so as we'll see, we have to do the same thing we did with the frame pointer. We have to store it on the stack at the beginning, use it, and then before we return, put that value that's on the stack back in the register. So, yeah, you didn't think of it like your, I mean, I don't know, the registers are basically like cubby holes or something and they already have stuff in them and you want to put stuff in there. So, you take them, you put them on the stack in a certain order and that way when they're done, you put them back on the right location so that it looks like you were never there. There's instruction, push add and pop add and then push all of the six GPRs from the stack in case, you know, but the color must be used and it depends on information. Yeah, the compilers are, I was going to say the compilers are very good about optimizing this kind of thing. So, they will, if they can use only the EX register, they'll only use that so they don't need to store any other registers or, which you can actually see in our little snippet, right, because we don't use any registers besides the AS. But, yeah, there's also, there's all kinds of functions and all that stuff. ESP is for the compiler then, we're using the frame pointer all the time, right? Sadian? We're not using the stack pointer at all, we're using the frame pointer. We use the stack, we're, so for referencing our various, our local variables and as we'll see our arguments, we use offsets of the frame pointer. Yeah, but not the, not ES, correct. But there's weird things, compilers will sometimes like optimize, I don't know, I don't want to get into it, but sometimes you'll see weird things. You think before you call a function, you can see a bunch of pushes, so you push the arguments onto the stack, but oftentimes they move onto the stack because they have a pre-allocated space on the stack so they know they can use that to push values in there so they don't actually push anything, it's like a move into the variance. Yes. All right, so we can look at this, so we will look through this, so we have very short C code, we have int main with a local variable in A, we say A is equal to call E, which is a function called passing parameters 10 and 40, then we return A. Then in our call E function, we have int call E, int A, int B, and then return A plus B plus 1. So this is just our simplified, our very simple function just to show exactly what happened. So here I'm going to show the main, you know, the all the assembly code for main and from call E from what I did this, whatever I did this. So the main function is push EVP, move stack pointer into EVP, subtract 18 hex from ESP, move hex 28 into ESP plus 4, move 10 to ESP, which is actually an example of what I was just talking about, whether or not pushing, then call call E, then move EAX into EVP minus 4, move EVP minus 4 into EAX, leave and then return. So we can see that the first three instructions, push EVP, move stack pointer to EVP, subtract 18 from the stack pointer, these are all the function prologues, so almost every single function will have, unless the compiler can optimize these out, will have essentially these same three instructions. So what's the very first one, what's push EVP doing? Okay, why is it doing it? That's my test. So it's saving the person who calls its base pointer onto the stack, so it's going to return it later. Then the move stack pointer into the base pointer is setting up its base pointer for its function and the subtraction of the stack pointer is allocating memory on the stack for local variables and as we can already see, it's essentially preallocating it for future stack operations to call functions. So we also have an epilogue, so to leave and return at the very end here, you can think of, we'll go into exact details of what they do, leave essentially is a move the base pointer into the stack pointer. So put the stack back where the current base pointer is, which completely does the last two, completely reverses the last two instructions inside the prologue. So because after this instruction, the base pointer and the stack pointer are going to be at the, oh, and then it does a pop EVP, that's right. It does a pop EVP, which then actually does all of these. Yeah, that's right. It completely does all of these. So it puts the base pointer back, what was on the stack at the previous time. We'll look at it in a second and return as we'll see transverse instruction to the function that called it. So call these similarly, push EVP, move stack pointer to the base pointer. Interestingly enough, so why, so it doesn't have a subtract whatever from ESP. Why is that? What was that? There's no local variables. We actually don't need any local variables here. So why allocate, why do the instruction go after it? So then we're going to move EVP plus C. So EVP plus C, then what is that likely to be? So if EVP minus something was what? Local variable, then EVP plus something. Arguments. Yeah, it's going to be arguments. So move EVP plus C into EAX. Move EVP plus 8 into EDX. And then this is where what I said, you sometimes see weird things. This is a load effective address, EDX, EAX 1 into EAX. What is that doing? Yeah, so it's essentially take EDX, add EAX to it, and then add 1 to it. So if you do that base displacement offset nonsense. So this is literally just like add EX to EAX and then add 1. So it's like combining that all together in one instruction. And then, oh, sorry, sorry, your, I was wrong. Okay, so this one is, you're right. You were all right whoever said just add EDX to EAX and stored in EAX. So like why is it not add EVX, EAX? That's a good question. I tried this in a newer version and it did compile that out by myself. Who knows? Systems are weird. So then we have like add constant 1 to EAX and then pop EVP and return because we're done. So again, this is the prologue at the top of callee, push EVP, move ESP into EVP and the epilogue here is pop EVP and then return. We're going to walk through it. Yes, so why not a leave instead of a pop? You could have a leave, but leave essentially the stack pointer, the base pointer at the same location. So part of what leave does is move the base pointer into the stack pointer to get rid of the subtraction of the stack of the allocation there. So they're already at the same location. So all you need to do is pop EVP because that's the other part you want from it. Okay, so what based on this optimization point, you've done two lines of the load function and it tries to return to EAX. It just tries to exchange the stack from one place to another place and then return. So the last two lines, I mean, move the last two lines all the same. Oh, yeah, yeah. So this was not compiled with any optimizations or anything. So hey, if you compiled it with that O3, it would probably compile out a lot of these things. But that is some kind of optimization that the compiler decided I can do this because my guess would be because it's not actually also our code at all. It's not optimizing our code, it's optimizing essentially its code because it controls the prologue in the Avalon. So if it thinks, because hey, this function uses zero local variables, then I can do my shorter prologue in Avalon. That's my guess. Cool. Okay. So let's look at this. We have, and these are all, so we know these instructions are all going to be at fixed memory offset. So you load this program in GBB or you can use object dump to see because we know the elf header specifies where all the instructions will load into memory. So if you look at the file, I'll tell you exactly each memory location inside the program where all of these instructions are. So here I've essentially laid out instructions all by each of these, sorry, addresses by all the instructions that Colleen made. And you can see if you're super detail oriented, you can start calculating deltas between them to see the variable lighting architecture here. Okay. So then we have our beautiful stack. We have our registers. So we actually use five registers in this whole program, EAX, EDX, ESPE, BP, EIP. And let's say we're at some, I think I actually tried this in a real operating system and I was at FD2D4 when I did this. So this was the stack one here. So so now we just started executing main. So main just got called from somewhere. So the first thing it's got to do. So the the other thing, this EIP instruction will constantly change based on what we're going to execute just to be completely consistent. But I'm not going to talk about it anymore. Well, maybe we'll just give it a call. Okay. So the EVP is going to be something above us. We don't know what it is. We don't actually care if it's null or whatever. We just know that somebody called us, we've got to deal with their base pointer. So we first push EVP, which we know how pushing works. So that moves the stack down, we then move the stack pointer, the base pointer, essentially getting rid of the previous stack pointer, sorry, the previous base pointer, because we've just saved it on the stack. So we know we can get it later if we need it. Then we need to subtract 18x from the stack pointer, creating space on our stack for our local variables. We then are going to move 28 onto ESP plus four. So what's 28x? 40. So what was it in the context of our program? The second argument to Kali, right, it was Kali 1040. So then we have a move A onto the stack pointer. So now the stack, even though we didn't do pushing, the stack has, so at the current stack pointer location is the leftmost argument, hex A, which is 10. Four bytes above that is the second argument of hex 28, which is 40. So then we call it, but how do we, so what do we need to do to call this function? Yeah, so we need to save the instruction pointer of the next instruction that's going to be executed, which will be, in this case, 80483BF. That's the next instruction. And what else do we simultaneously want to have happen? So we want to push that value onto the stack. But what else? Yeah, change the instruction pointer to where? The address of Kali of 8048394. So x86 has jump instructions, which I believe you got pretty familiar with on the last homework assignment. I'm seeing some dirty looks, yes.  So it's a call is similar to a jump, where all a jump does is change the instruction pointer to be whatever the target is. So in this case, the target here is 8048394, but if we just started jumping and executing from there, we have no way to get back, because the CPU doesn't magically know that it was called from somewhere. So call does two things. It essentially does push the next instruction that would be executed, 80483BF, and that in turn, obviously, because of a push, decrements the stack pointer, and then sets the instruction pointer to whatever that address is. That's all it does. It's not smart. There's no smarts going on anywhere. It's all very discrete, simple, and quotes operations. So now Kali executes, and this is the thing, like this is why we teach recursion. It's the exact same thing that happens from Kali's perspective than Main's perspective, right? When Main started executing, it had no idea how it got there. It didn't care who called it. All it knows is, I've got to save this other person's base pointer because I need my base pointer. So I'm going to push EVP onto the stack. So save Main's base pointer. I'm going to set up my base pointer by moving the stack pointer into the base pointer. And now, basically, as far as we're concerned, Main doesn't even exist. We don't care anything about Main. It only essentially exists as a function frame on our stack. So another way to think about it is the function frame basically contains all the information that is needed to kind of execute that program for that function, I should say, not program. Okay, now we're going to look at EVP plus C. So what's EVP plus C here? So EVP, so the base pointer is here. So plus C is so 4, 8, 12. This is going to be hex 28. What value is that? 40. So our function call E, our compiler, right? So we had, I believe, two arguments, A and B. A was the first one. B was the second one. How come it knows that an EVP plus C is the argument B? I mean, it knew how many parameters it had and it set it up in the stack and it controls everything. Yeah, so where's the first parameter? Yeah, plus 8. Why is it plus 8 and not plus 10 or 12 or 4? What's those 8 in between? The saved base pointer that we pushed ourselves. And above that is the saved EIP, the saved instruction pointer that the person called us put. And we know that has to be there because of the C-deco calling convention. And then the thing right above that on the stack has to be the first argument to our function. And then 4 by 2 of that is the next argument to our function and so on and so forth. Right? So this is how we can easily calculate for whatever argument in our function exactly how many bytes to look up. So just like local variables are all at EVP minus offsets that the compiler determines, in this case it's not even really the compiler gets to determine if the C-deco calling convention specifies how many bytes exactly above its EVP. So this is super important when you're looking at x86 code to remember that when you see EVP minus something, that's a local variable. When you see EVP plus something, that's an argument to a function. Cool. So we can even see that Pauli's function point, sorry, frame is essentially all the arguments and all the local variables and main also has its own function frame. So now we're going to move that x28 into DAX. We're going to move EVP plus 8 which is the first argument A onto EDX. We're going to do load effective address of essentially adding EDX to DAX and storing it into DAX. And then we're going to add one to DAX and now we're done, right? Because we know that due to the C-deco calling convention the return value of our function will be in the DAX register. But now we need to reverse everything, right? We need to get back to essentially the stack pointer needs to be an fd2b8 in order for the function to continue executing. So we pop EVP and again, we don't care who had EVP. We don't care who's EVP this is, we're just putting it back. Whatever value is in there, we put it back. And now we return, so you can think of a return, a ret as the opposite of a call instruction. Or the other way to think about it is a pop EIP. So if it was a pop EIP, what would that mean? It's all on the level of some of it. It is, but it's semantically equivalent to, so what if it was a pop EIP? What would that mean? Yeah, so take the element at the top of the stack, put it in the EIP register, and add four to the stack pointer. That's exactly what happened. So a return instruction simply does literally exactly that. Take that value, put it into the EIP, and yes, you cannot write pop EIP because that's an illegal x86 instruction, but if that helps you think about what a return does, that's exactly what it does. So now we're here. So now from a main perspective, what just happened? EAX changed. That's the only thing we care about. And maybe any global memory change that if any function we call it and they call it and they call changing global memory, those are now changed. But fundamentally in our world, only thing that we care about that change is EAX. Pretty sweet, right? This is super awesome. So now we're going to get that value out of EAX, put it into EVP minus four, which was, I think we had a local variable a, and then we do this silly, like very sillyness where we take EVP minus four and we went back into EAX. So why are we doing that? Like, what instruction does that correspond to in the program? So that, the gator does EAX, the main things. Returns EAX and no DAX to C codes. What was the C code? A, return A, exactly. Yeah, because that was the, we said A equals colleague, so that's this instruction, right? So we called it and then we have to set our local variable A, which is that EVP minus four to that value. Now that we've done that, we can be return A, which is move that value into EAX. And clearly a smart compiler could remove these, but this is just a non-optimizing compiler here. So now we're done with the semantics of the program itself. Now we have the super important prologue. So now we're going to do a leave, which is essentially set the stack, sorry, set the base pointer equal to the stack pointer. So yes, set the stack pointer, move the base pointer to the stack pointer. So move the stack pointer up and then pop EVP to, wait, it must do a pop first. Yeah, yeah, yeah, yeah, because it's returning the DAX. It doesn't matter. Okay. Sorry, why was it doing that non-optimized thing again, the EAX and the EVP minus four? The second move instruction is the return A. So to do return A, we know the return of value, you have to move that value into the EAX. So the straightforward compile of that is wherever that memory offset is, in this case EVP minus four, move that into EAX. So that's just like a straightforward translation. So you can think of it like the compiler is compiling essentially line by line and not doing a local optimization or even a local optimization to say, does this make sense? Okay, so at leave, we're going to move the base pointer into the stack pointer. So essentially changing the stack pointer now to be d zero. So fd2d0. So both the stack pointer and the base pointer are pointing the same value. What are they pointing at? The previous function's base pointer, right, the same EVP. And then we essentially do a pop EVP. So we're going to take that value and copy it into the EVP register, which essentially sets up. So what is above, so where's, what is the stack pointer to right now? So my diagram, I have it all of it at the tip of the top of fd2d4. So what is it pointing to? We already loaded that in. So the EVP is at fd2d0. So it's this fd2c0. So where is the stack before the value was pointed? I think that is technically true. Well what actually is it pointing to? What was that? The actual point. The actual what? File. It has no concepts of files. There's no, I don't even know what a file is at this level. What's the next instruction that's going to exit here? Is that returns zero? A return. What's a return going to do? A ret instruction. Is the return, let's think about this. Is this return instruction here made any different than the return instruction in call e? No. So the instruction that needs to be loaded? Exactly. It's whoever called main. There's some function that calls main that when we return from main we're going to go and start executing there. So it's actually like your exit motor, your process has to get set and an exit has to be called, all that fun stuff. So that all happens here. So yeah there's some address that you're actually going to go to after main to do the cleanup of your program. So that's what happens there and that's at that address. All right cool. So that was all background information to get to understanding stack overflows but I think we've built up enough here that you can kind of see where we're going. So the idea is a stack overflow occurs when you're copying data or a stack overflow or a buffer overrun. These are all kind of synonyms for the same thing. The idea which I know we've definitely talked about on a Wednesday long past is that in C if you want a local variable of a certain length, a buffer of a certain length, you have to specify in advance the size of that buffer. And so what this means and there's no automatic data checking on the bounds of that array. So if you're trying to copy, if you make an array of size 50 or a buffer of size 50, you can set values at 51, 52, 100 or even 1000 because nothing is doing that checking. So a stack overflow basically or data buffer overrun exists when you can trick the program to write to memory that is outside of the memory that is allocated to your program. So this is actually a good, I think more of a good general definition because you think about like heap overflow is you can overwrite a heap buffer that's then so if you have a heap array that's of size 1000 or whatever you write over that and you can cause problems. If you have a local buffer on the stack that's allocated on the stack of like 1000 bytes or something that if you overwrite those 1000 bytes and you can write past that, that has problems. So normally this will cause a segmentation fault, the second fault that we all know and love, right? We're trying to overwrite some memory that doesn't exist or is not allocated to us. But, so we talk about, okay, I'm going to ask this every time. How many people know the, the, that's probably a fable of Hansel and Gretel? Very few, yes, okay. So this is, I should have one of you guys tell it, but I guess I'll tell it. So the idea is this is a super bridge version, you can go look it up and read it. It's really groovy, especially for kids. You're going to leave out the witch? No, no, no, which is a great part of it. So, I guess we're going to tweak the wage a little bit.  So if you want to go wander around this forest, how do you know how to get home in the morning or at night when it's super dark and disorienting and you don't have a compass? So how do you get home? Hey, with breadcrumbs. So you like take a piece of bread and every so often you like leave the trail of bread and that way no matter what path you take, you can always find your way back by going from one breadcrumb to the other, right, and finding the way. So we're good. And the same instruction pointers on the stack are like the breadcrumbs of our program, right. As each function executes, it leaves a breadcrumb to say, hey, when you're done executing, come back this direction. So if we were an evil witch and we wanted to, let's say, trick these kids to come back to our like witches hut or something, one thing we could do is start maybe erasing those instruction, the breadcrumbs and leave our own breadcrumb trail right back to our witches place. I think I've butchered the fairytale, but idea remains. So we are going to overwrite the return value in such a way to trick the program to do whatever we want to perform arbitrary computations. One thing that we're going to start off doing is we can jump to user defined executable code. So if we can write to an executable segment in memory, and we can write valid x86 instructions, if we can overwrite one of those save VIPs on the stack and provide that address, we can get the program to start executing some code that we injected into the program. And as we know, the key benefits here is that this code is running with the privileges of the running program. So if it's a set UID program and you're now root and half root privileges, we can do all kinds of fun stuff. All right, I guess I'll just stop here.


The study aims to quantify and characterize the scientific literature on Rabbi's vaccine research from 1991 to 2020, identifying the top-most cited studies in this field. A total of 1,042 papers were included, with the United States being the most prolific country in terms of publications. The study highlights the need for research collaboration and cooperation among institutes and researchers in developing countries to strengthen their efforts in Rabbi's vaccine research. This article was offered by Kausif Ahmed, Arun, Mohamed Khan, and others.


Are you I'm reading that newspaper because you've been holding up for about 10 minutes well because it's very difficult to to hold up to be able to really irritate Tom. But this was the this is the complete daily news the entire edition of the daily news the day after the Dodger swept the Yankees in 63. My father saved it. Because he was such a anti Yankee fan right and so this is so what was his team before the Mets became the Mets. The Dodgers. Was it the Dodgers. OK. So he would rather root for a team that picked itself up and move 3,000 miles away than the one that played in the Bronx. That makes sense. So that's like rooting for your wife that left you makes perfect sense. It's it makes no sense. They they deserted people in Brooklyn. They deserve it. He's going to be coming out of a barrel. He's going to become a Yankee fan. No. He tried to do the team that left you. Would you ever root for your wife if she left you if she was up for it's not the same thing. Of course it's the same thing is obviously upset at Walter O'Malley. But there's still all those players as you still have a lot of the lot of the guys in 63 that were still you know on those teams that were in Brooklyn including Sandy Kofax who was the winner. You can see him celebrating there. And you know my father obviously became a Mets fan. But he was still a partial to the Dodgers. He grew up there. There's Ralph Hauke sulking after getting swept in four. I think it's the fact that he saved the entire magazine of the entire newspaper. Michael is great. You just run a story in the athletic the other day about what would have happened if the Dodgers stayed because the Dodgers actually Walter O'Malley was was a man ahead of his time. He wanted to build a new habits feel a retractable roof. This isn't you know he's pitching this in the 50s on the site where the Barclay Center stands. So Robert Moses wanted no part of it. He wanted to build the Dodgers a stadium in Queens. And Malmale said with the Brooklyn Dodgers the Queens Dodgers. If he had given him that ballpark the Dodgers would still be here. The Mets would never exist. The Giants still would have moved to the West Coast because the polo grounds was was just terrible. And they would have had to find another team. To go out to the West Coast so many things would have changed. Yeah because I guess that the story goes Michael that the the Giants probably would have moved to Minneapolis. Maybe and so so somebody else because they wouldn't have gone out. No but they wouldn't have taken just one team out to the West Coast. They had to take two. So the Dodgers had stayed. Eventually the Giants were not doing anything financially because the polo grounds was so run down and they couldn't get a new building. They would have moved to Minneapolis. And then what teams would eventually move. How long would it have been before we moved to California. But my father was not going to be how is it. How are you supposed to root for the team that beat your brains out through the entire 50s because you root for the team that stayed. That was true to the city. I don't I don't think it's it's it's so nobody did that. I mean I never I never heard any stories. Another person he's no longer with us as a pharmacist. I worked with when I worked at Lincoln pharmacy. He tried to stay a Dodger fan for a while and he was getting the newspaper delivered but he just couldn't follow it because with the time difference and you just couldn't get the information right away that when the Mets came in 62 was just an easy transition. That's why the Mets were so popular because every giant met fan. Every giant excuse me. Every giant and Dodger fan became a met fan in 60 and for those. I mean most of our viewing and listening audience would know this but the Mets cap is an amalgamation of the Dodgers and the Giants Colors the Dodger color and the color of the orange is the Giants. But I understand I understand the premise of it's like the wife leaving you but that's the team. Those are the players you rooted for. And you know it would be easier now if a team left because you could follow you to watch every game back then you couldn't. And you know and believe me I think it's over now Michael because you remember this this existed like deep into the 90s that New York was a National League town. You always heard that right. Oh it's a National League town because of the Giants and the Dodgers with just the Yankees being the American League team. I think that's gone now obviously because we're so so far away from the fact that they moved after the 57 season. But how difficult it must have been. They both leave. You can't follow them as you said because the games are on television. You can't get a newspaper from Los Angeles like three days later. Maybe you'd get the final score on the radio the next morning. And then the Mets didn't come until 62 and you weren't going to root for the Yankees. So you just didn't have a team 58 59 60 61 in four years without a team. You think you think in that situation you're allowed to just become a fan free agent. You know how do you become a fan free agent. Who do you root for. I mean again you grew up hating the Yankees so you're not going to root for them. And right. And this is and this is the late 50s. So you had no satellite watch the games or who are you going to root for. I bet we have listeners out there whose families turned into fans of completely random teams as a result of this. But I'm asking you Peter. Let's say you decided all right you know I'm going to be a Red Sox fan. I hate the Yankees all root for the Red Sox. How do you consume them.  You can't listen to their games. You can't watch their games. OK. At least at least the Red Sox score the next day. But with the Red Sox at least you can get a box score. But how do you root for a box score. You can't go to the games. It's a four or five hour drive away. And there wasn't a word there. Michael is completely different. Now you can do it back then you couldn't. You just weren't there weird and signals that you could hear from all over the place back then. Yeah. But I don't I don't think you could hear from L.A. No. No not L.A. But like Cleveland or Baltimore. Yeah. You could pick up KMOX and St. Louis. But again if you grew up a Dodger and a giant fan what love will you have for the Cardinals.