Правильное поведение инструкции ADD ESP 4 - PullRequest
0 голосов
/ 03 января 2019

Насколько я понял, добавление 4 (или, возможно, 8) байтов к вашему указателю стека по существу удалит предыдущее значение из стека, не помещая его в регистр, подобный pop.Но стек и указатель стека - это две разные вещи.

  • Означает ли это, что вы на самом деле не стираете значение, а просто стираете позицию указателя, чтобы он действовал так, как если бы он был пустым?
  • Означает ли это, что вы также можете SUB ESP, 4 и получать данные даже после их "стирания"?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

[...] добавление четырех [32-разрядных] (или, возможно, восьми [64-разрядных]) байтов к указателю стека по существу удалит предыдущее значение из стека, не помещая его в регистр, такой как pop.

Стек представляет собой структуру данных LIFO, поэтому последнее значение, помещенное в стек, будет удалено первым.Добавление значения 4 (8) байтов в стек просто пропускает текущее самое верхнее значение без передачи его в регистр.POP также передаст значение в регистр.

Означает ли это, что вы на самом деле не стираете значение, а просто стираете позицию указателя, чтобы он действовал так, как если бы он был пустым?

Вы просто указываете Указатель вершины стека ESP (RSP) на предыдущую запись.Текущая запись не стирается, но пропускается (больше не указывается).

Означает ли это, что вы также можете ПОДПИСАТЬ ESP 4 и получить данные даже после их «стирания»?

По сути, да.Если стек не был изменен другой процедурой, обработчиком прерываний, асинхронным вызовом или другим влиянием, которое использовало стек, вы можете извлечь предыдущее значение стека.Это особенно важно с точки зрения безопасности.Поэтому для безопасного удаления данных в стеке они должны быть перезаписаны нулями вручную.

Вдохновленный комментарием @PeterCordes Я написал простой пример в 32-разрядной сборке Linux, иллюстрирующий это:

.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 

Назовите его stack.s и соберите его с

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

Вывод будет 66, значение локальной переменной из подпрограммы.Так что утечка данных из стека возможна.Насколько это серьезно?Я не уверен.Но это возможно.

Если вы обнуляете важные данные, вы должны позаботиться о том, чтобы компилятор не оптимизировал эти инструкции.Вы можете найти лекцию продолжительностью в один час под названием "35C3 - Memsad" об этом на YouTube (это недавний доклад немецкого CCC ).

0 голосов
/ 03 января 2019

Прерывание, переключение контекста или что-то подобное может сохранить данные в стеке, перезаписывая любые данные ниже ESP, но до тех пор, пока это не произойдет, данные в стеке не будут изменены внешне для вашей программы.Если ваша программа помещает что-либо в стек или выполняет вызов, то это перезапишет данные, которые были ниже ESP перед передачей или вызовом.

...