One of the most common vulnerability that could be found in the wild is the buffer overflow. Either found as a stack overflow or heap overflow, it could allow not only reading but overwriting memory addresses which shouldn't be accessible from the standard program execution flow. By doing a code revision, or maybe some reversing over a binary or executable, it is possible to find this kind of vulnerabilities which impact the integrity, confidentiality and availability of the information when exploited by an attacker.
for (i = 0; i < 128; i++) is executed 128 times.
In this case, after the for loop is ended and all the bytes from the argument are copied to the buffer, the stack frame of the vulnerable function stays as intented. The program can continue using the saved EBP that was pushed when the vulnerable function was called.
But if the argv[1] are 128 A's and the null byte character at the end, the total size of the string to be copied will be 129 bytes. Accordingly to the vulnerable for definition, the loop execution will run 129 times, then the for loop will try to copy 129 bytes to the reserved 128 bytes buf memory. If working with little-endian format, we will overwrite the least significant byte of the saved EBP· with a null byte by entering as payload 128 A's. This will cause that the saved EBP address will change from 0xbffff542 to 0xbffff500.
Disassembly of main function
Disassembly of vulnerable function
The EBP popped after the leave instruction of the vulnerable function was not overwritten. By examining the memory at address 0xbffff543, it's possible to notice that everything is going as the developer of this software planned.
However, things are going to change when running the program with a 128 A's string as an argument. Let's see what happens:
At first glance, we can notice the overwriting of the EBP address with the null byte in its least significant byte. But when examining that address, we find that this memory address is part of the buffer we copied.
Because the EBP register before exitting main has the 0xbffff500 value, after the leave and ret instructions of main's epilogue, the ESP register will be moved to point to the corrupted EBP, and then, the value where ESP is pointing will be popped to EBP (0x41414141) . Afterwards, ESP will be pointing to the address 0xbffff4fc, and after ret instruction is executed, it will set the EIP register with the value of the memory address where ESP is pointing to (0xbffff4fc = 0x41414141 -> EIP).
Thus, to exploit this vulnerability by loading a shellcode to the buffer, we should set the address of the shellcode once, at least, and it must be in the corrupted EBP - 4 address.
We are going to use a simple shellcode to load as a payload. It will print on screen CSLHack! when successfully executed.
The program execution in GDB will be different when deployed in bash, including the reserved memory addresses. So we need to make a payload which should be reliable from the address that could be obtained when debugging the software on GDB. We will use this structure to build our payload.
By using the NOP's instructions, the exploit becomes more reliable, and filling the space left with repetitions of some address pointing to the NOP's segment (&shellcode) will work when running the program in bash and loading the payload to it.