h7x4
h7x4

Reputation: 57

True behaviour of the instruction ADD ESP 4

As far as I've understood, adding 4 (or potentially 8) bytes to your stack pointer will essentially erase the previous value from the stack without putting it into a register like pop. But the stack and the stack pointer are two different things.

Upvotes: 1

Views: 1396

Answers (2)

zx485
zx485

Reputation: 29042

[...] adding four[32-bit] (or potentially eight[64-bit]) bytes to your stack pointer will essentially erase the previous value from the stack without putting it into a register like pop.

The stack is a LIFO data-structure, so the last value put on the stack would be removed first. Adding a value of 4(8) bytes to the stack just skips the current top-most value without transferring it to a register. POP would transfer the value to register, too.

Does this mean that you actually do not erase the value, but just erase the pointer position so that it's going to act as if it's empty?

You let just point the Top-Of-The-Stack-Pointer ESP(RSP) to the previous entry. The current entry is not erased, but skipped (not pointed to anymore).

Does this mean you also could SUB ESP 4 and retrieve the data even after "erasing" it?

Essentially, yes. Unless the stack has been modified by another procedure, an interrupt handler, an asynchronous call or another influence that did make use of the stack, you can retrieve the previous value of the stack. This is especially important for security aspects. So to securely erase data on the stack, it has to be overwritten by zeros manually.

Inspired by a comment from @PeterCordes I wrote a simple example in Linux 32-bit assembly illustrating this:

.intel_syntax noprefix
.global _start
.text

_start:
    call subroutine
    mov  ebx, [esp-12]  /* Get data from subroutine */
    mov  eax, 1 
    int  0x80
    /* echo $? outputs '66' */

subroutine:
    push ebp
    mov ebp, esp
    push 66  /* local variable to be leaked */
    mov esp, ebp    
    pop ebp
    ret 

Name it stack.s and assemble it with

as -32 stack.s
ld -m elf_i386 -elf -o a a.out
./a
echo $?

The output will be 66, the value of the local variable from the subroutine. So data leakage from the stack is possible. How serious this is? I'm not sure. But it's possible.

If you zero-out critical data, you have to take care that the compiler doesn't optimize away these instructions. You can find an one hour long lecture called "35C3 - Memsad" about this on YouTube (It's a recent talk from the german CCC).

Upvotes: 3

rcgldr
rcgldr

Reputation: 28921

An interrupt, context switch, or something similar may save data on the stack, overwriting any data below ESP, but until this happens, the data on the stack is not changed externally to your program. If your program pushes something onto the stack, or makes a call, then that will overwrite the data that was below ESP before the push or call.

Upvotes: 5

Related Questions