 So, good afternoon everyone this in this demo I will show you the buffer overflow demo will look at the concept of buffer overflow attack which is a software vulnerability and also some of the defenses which can be used to overcome this attack. So, consider the following program on the left you see the main function on the right is a subroutine called the sub function. Now, in the main function on line 3 you initialize a character array called buffer 1 which is initialized to the value hello world. This string is of size 12 including the terminating character at the end. On the next line you see a printf statement which indicates that we are inside the main function. After that is a printf function which displays the value of buffer 1 which in this case would be hello world. Next we call the sub function passing buffer 1 as an argument to this function. So, moving on to the sub function this function takes as a parameter a string. The first line in the sub function is the printf statement which indicates that we are inside the sub function. Next we initialize a character array called buffer 2 of size 12 which is initialized with all a's followed by a terminating character. Next is the printf statement which will display the value of buffer 2 which in this case would be all a's. Next is the string copy function which will copy the contents in buffer 1 which was passed as an argument to this function and it will be copied into buffer 2. And then we will print the contents of this copied content in buffer 2. This will then return back to the main function where after the sub function returns is the printf statement which will indicate that we have returned to the main function and then the program terminates. So, this is our first program. The second program is almost similar to the first program with the only difference that will initialize buffer 1 with this long hex code which you can see at the bottom. I will explain what it means in some time. For now just consider this long hex code as being initialized to buffer 1. So, to summarize what this program does is that it will pass a buffer to a sub routine the contents of that buffer will be copied into another buffer and the program terminates. So, this is the stack representation of our first program. This in the stack representation the stack grows from bottom to top whereas, memory increases from top to bottom. So, look at the left stack at the bottom is the local variable buffer 1 which was initialized with the hello world string in the main function. After that as you can see a call to the sub function was invoked. So, in the stack as we had seen yesterday first the arguments for the sub function which is buffer 1 in this case is pushed on to the stack. Next we insert the return address to which the program should return after executing the sub function that will be pushed on next. Next we save the frame pointer of the calling function on the stack because the frame when the execution moves on to the sub function the register containing the frame pointer will be overwritten. So, when we move back to the main function we need the frame pointer of the main function and hence we push it on to the stack. Next a canary value which is a random value will be pushed on to the stack. After that as you can see in the sub function we initialized buffer 2 with the value of all a's followed by the terminating character. So, next the stack will contain the local variable of the sub function which is all a's in this case. In the stack the portion of the stack which is marked in gray is the stack frame for the sub function. Now in the program next we will copy the contents of buffer 1 which was passed as an argument to the sub function into buffer 2. After this operation is performed as you can see on the right side of the in the stack shown on the right side the buffer 2 now contains the string hello world which was copied and it overwrote the initial string which contained all a's. In this program the buffer 1 and buffer 2 both were of the same size and hence buffer overflow did not occur and the program terminated successfully without compromising on any of the other fields on the stack. Now we will consider the second program in which we will initialize buffer 1 with this long hex string shown at the bottom. So, this is the stack representation when we execute the program. On the left first we initialize buffer 1 with the long hex string in the main function this you can see at the bottom. Next a call to the sub function is made. So, as you had seen earlier first the arguments for the sub function will be pushed on to the stack which is buffer 1 in this case. Next the return address will be pushed and then the frame pointer of the calling function will be pushed and just before the sub function starts executing a canary value which is a random value will be pushed on to the stack. Again in the second program the buffer 2 is initialized to all a's which is of size 12. So, this buffer 2 will be now pushed on to the stack. Now the string copy function in the sub function will be the string copy function will be executed will be which will copy the contents in buffer 1 into buffer 2. Now in this case since buffer 1 the size of buffer 1 was greater than size of buffer 2 buffer overflow will occur. So, as you can see on the stack which is shown on the right hand side the contents of buffer 1 are copied into buffer 2, but since the size of buffer 1 was greater than buffer 2 the contents override the adjacent memory and the values are corrupted. I mean the initial canary value frame pointer value return address have been overwritten with this new data. So, here we can see the overwritten return address. Now I will explain what the contents of buffer 1 in program 2 were. Initially we had a bunch of hex code which corresponded to the NOOP function the NOOP assembly instruction. This is the hex code 90. This was followed with a set of assembly instructions which you can see in the table the last four instructions correspond to a system exit call. So, for the purpose of this demonstration we used the system exit call to indicate that an attack this is analogous to an attacker who might insert his own malicious shell code. However for this for the purpose of this demonstration we inserted the system exit call hex code. And finally, towards the end of the string the hex code which is shown in red corresponds to the address of buffer 2. As you can see in this stack the overwritten return address points to the beginning of buffer 2. So, this is what buffer 1 was initialized to. One important thing to note here that then we had a bunch of NOOP instructions at the beginning of the buffer 1 string. This was because an attacker may not precisely know the exact target location where he should insert his malicious code. That is why he inserts a bunch of NOOP operations. So, that the target area for the attacker increases and even if he misses by 1 or 2 memory locations either above or below he can the program his malicious code can still execute. So, some of the defenses that we looked at yesterday were the following. Stack protection using canary values. In this we insert a value at the entry to a function and then check whether it is modified while exiting the function. Another defense is to make the stack non executable. The first two defenses are at the compiler level. Whereas the third defense which is to randomize the memory layout is at the operating system level. In this defense this defense is used. So, that it is very difficult to jump to the desired location on the stack. Finally, a programmer level defense is to use the STRN CPY function instead of the STR CPY function. The STRN CPY function does array bound checking which the STR CPY function does not. So, now we will move on to the demo of the buffer overflow attack. So, for the purpose of this demonstration we will first disable the defenses. The first three defenses which we looked at which are by default enabled in an Ubuntu system. First we will disable the memory layout randomization defense. So, for that type the following command on the terminal sudo sysctl space minus w space kernel dot randomize underscore va which stands for virtual address underscore space equal to 0 equal to 0 will disable memory layout randomization. Whereas by default it is equal to 1 which enables randomization. We will compile our program 1 with the following command gcc space minus o space program 1 space look at this option minus f no hyphen stack hyphen protector. This option when you compile a program with this option the stack protection will be disabled stack protection using the canary value matching technique will be disabled. This is followed by the minus z execute stack option. When you compile a program with this option it will make the stack executable. Now we will run our program. So, as you can see in the output first we are inside the main function we print the value of buffer 1 which is hello world. Next a call to the sub function is made passing hello world as an argument we first initialize buffer 2 with a string of all a's. We then executed the string copy function which copied the contents of buffer 1 into buffer 2 and then we print the value of buffer 2 which is hello world. In this case since buffer 1 and buffer 2 were of the same size buffer overflow did not occur and control return to the main function and we can see the statement return to main. Next we will execute the program 2 in which we had initialized buffer 1 with the large hex code. So, we will follow a similar pattern to compile program 2 in which we will disable the stack protection and make the stack executable. We will now run the program. Now as you can see in the output we first we are first inside the main function we print the value of buffer 1. The value shown here is just some ASCII representation of the hex code. Next a call to the sub function is made passing buffer 1 as an argument we first initialize buffer 2 with the string of all a's of size 12. Then we copy the contents of buffer 1 into buffer 2 using the strcpy function which does not check array bounds and so the contents of buffer 1 were copied into buffer 2 and since the size of buffer 1 was greater than buffer 2 it overwrote the adjacent memory location. And then we print the value of buffer 2 which matches with that of buffer 1, but however since the return address was overwritten and was made to point to buffer 2 which contained the malicious code. In this case the system exit call the system exit call was executed and then we never returned back to the main function which is why you do not see the return to main statement here. So, we now run the program I mean the previously what you saw we run the program by disabling all the defenses. We disabled the address layout randomization, we disabled stack protection, we made the stack executable and then we run the program. Now let us look at what happens if we enable one of these defenses. So, now what we will do is we will make this we will enable the stack protection which is why we have removed the f no stack protector option. We will compile it and then run the program. So, as you can see the program was aborted and you see a stack smashing detected display when you run the program. This is because we can we had enabled stack protection which then checked for the canary value which was initialized at the beginning with some random value and then it matched the value at the end before exiting, but since we had overwritten that value the match did not occur and then and hence it detected that the data has been corrupted and so the program terminated abruptly. Now let us see what happens if we just make the stack non executable. So, we will remove that option while compiling and then run the program. So, here you will see at the bottom that we receive a message called segmentation fault. This is because since we had made the stack non executable the overwritten return address contained hex code executable code which could not be executed since we had made the stack non executable and hence since we are not allowed to we were not allowed to execute that code it showed the segmentation fault message. So, we looked at three cases one in which we disabled all the defense in the next case we had enabled stack protection only and in the third case we had made the stack non executable. There are various other options that you can try out since we use three defenses you will have a total of eight combinations to try out we showed three and we leave the rest five options as an exercise for you. So, with that I like to conclude my demo. Thank you.