Reputation: 57
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.
SUB ESP, 4
and retrieve the data even after "erasing" it?Upvotes: 1
Views: 1396
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
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