1

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?

1 Answer 1

0

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

I think this is your confusion, because that's not remotely true. The stack in memory is an abstract data structure, not a physical pile of objects that physically interfere with accessing lower ones. Sure, popping a value off the stack can only be done at the top (lowest address, in most systems), but the actual operation of e.g. pop ecx is "load the four bytes at esp into ecx, then increase esp by four". Notably, the "popped" value is still exactly where it was in memory, and will stay there until overwritten by another value or until the entire memory page is deallocated. Similarly, it's entirely possible (and constantly done) to read and even write values that are on the stack but not at the top of it; so long as their length doesn't change (for variable-length stuff you usually use the heap), they can be at any depth in the stack and there's no need to clear everything on top of them to get there. The current top of the stack is simply defined by the value of esp (or other similar register on other architectures) and has nothing to do with what addresses contain "usable" data.

2
  • thanks a lot for the answer. I figured they weren't being cleaned after they were popped as I figured there was no way else to explain how this exploit would work, that just cleared it up for me. You're awesome!
    – poyraz04
    Oct 22, 2021 at 22:24
  • Glad to help, and welcome to Security.SE! That was a well-written question, and clearing up that kind of confusion is one of the things this site is best at. If you found the answer helpful you can upvote it (little arrow to its upper left), and if it resolved your question you can mark it as the accepted answer (checkmark below the arrows).
    – CBHacking
    Oct 23, 2021 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.