I am trying to get deeper into buffer overflow and lower-level stuff in general and am confused regarding one particular topic. I have seen examples of buffer overflows in which the shellcode is supplied by the attacker in two types. The first is one where the shellcode takes place before the return address and the second is where it takes after. The visual demonstrations below should help:
lower address, higher up the stack[buffer][savedebp][return][var3][var2][var1]
higher address, lower down the stack
If this is our stack, then
a) shellcode before the return address:
[x90x90...shellcode][(shellcode continued)][return to top of stack][var3][var2][var1]
The idea is it will return to the top of the stack, go down the noop sled and eventually execute the shellcode
b) shellcode after return address:
[xrandomxrandom][xrandom][return to a little higher address][x90x90][shelcode][(shellcode continued)]
Here it is supposed to read that it should continue executing a little bit higher than the address that the stored EIP
is stored on the stack. Thus go down to the noop sled and execute the shell from there.
What I don't understand is how the a) should work. Since assembly restores the older eip during the epilogue by popping the stored older eip from the stack, it goes without saying that the stack must be cleaned before it can pop it due to the first in last out nature of stacks. If this is the case, then the shellcode that was supplied by the attacker should not be on the stack anymore by the time the machine reads the supplied return address from the overwritten eip. It must be popped for the stored eip to be reached in the first place.
Could anyone explain how this would work for me?