I'm practicing backdooring PE binary compiled with ASLR in a WOW64 environment. The approach is pretty straightforward and basically is something like this:

  • Find code cave and a hijacking point. In this case, I choose not to patch the entry point but the shellcode will be trigged on user interaction.
  • After the hijacking point is reached, I found a useful way to jump to my code cave.
  • Once I'm inside my code cave, like standard approaches, I save my flags and registers with PUSHAD and PUSHFD instructions.
  • Execute successfully the shellcode: my reverse shell is connected and working flawlessy.
  • After that, I need to come back to the original flow, reconstructing the flags, registers and patched instructions.

In a no-ASLR environment, I can hardcode the original address back inside the ESP and executing standard POPFD, POPAD instructions. But now, how can I come back to the original ESP value? Also, I noticed that somehow the ESP address changes also in the offset and not only in the base address. Maybe it depends on some user interactions...

1 Answer 1


If I understand your question, you’re missing something very fundamental about how functions must behave.

Push operations don’t “save” values per se, they store values to the stack and then decrement the stack pointer. This means that the stack pointer must be at the same value (excluding the size of the data that was pushed) in order to restore” values by popping them. Everything is in band and depends on the integrity of the stack pointer.

When your function returns to the caller, the ESP/RSP value MUST be the same as when it was called when your payload finishes. This is how a “normal” compiled function works and it is required behavior for a program to work correctly. Otherwise ret instructions would be meaningless since they depend on the stack pointer being set to to the same place that the call instruction pushed the return address

If you allocate 64 bytes of stack space in your function, for example, you should increment the stack pointer back up 64 bytes when your function is complete. Don’t forget that both ret and call will modify the stack pointer slightly as well.

To troubleshoot your code, breakpoint at the beginning and end of your payload and verify you have properly restored the stack to its original value at the end, usually via a sub instruction or by using an immediate value with the ret instruction. In my opinion using sub is clearer.

tl;dr; When writing assembly code, think of the stack as the heap and be conscious of “freeing” any allocated stack space when you are done with it or at the end of the function. Keep the stack pointer in sync like properly compiled code would.

  • Thanks for your help but it is not my case. I mean, I'm using a metasploit reverse shell as shellcode so I do not mess with the stack. What is so strange is that the ESP value at hijacking point changes every run so it's impossible to decrement it after shellcode run and so restoring the normal program flow. I'm afraid I need to change the hijacking point.
    – Kartone
    Commented Jul 28, 2019 at 16:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .