Можно ли напрямую идентифицировать неисправный код, который перезаписал весь стек?

Проще говоря, если программа на C++ выполняет следующую функцию (скажем, в Windows 7, скомпилированная с любой версией VS), затем происходит сбой, и вы подключаете отладчик с помощью WER, или WER создает аварийный дамп, а затем анализирует этот аварийный дамп. .

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

Или все следы выполнения исчезают, когда я испорчу весь стек?

void bye_bye_stack() {
  int local = 42;
  int* stackaddr = &local;
  while(time(NULL) != NULL) { // prevent optimizations via call to time()
    ++stackaddr; // stack grows towards smaller addresses, so increasing the pointer will point to info we already put on the stack
    *stackaddr = local; // destroy stack content
    // program will (likely) crash here once we reach a read-only page
  }
}

person Martin Ba    schedule 18.01.2013    source источник
comment
Нет, это крайнее горе. EIP и EBP являются ненужными, ESP указывает на уничтоженные кадры стека, многие из них могли быть потеряны. Все, что вы можете сделать, это вернуться и попытаться найти обратный адрес, который не был растоптан. Что по-прежнему дает вам только часть стека вызовов. Затем вы обдумываете использование безопасных функций CRT.   -  person Hans Passant    schedule 18.01.2013


Ответы (3)


В общем, уничтожив стек так, как вы это делаете, вы уничтожите «стек вызовов», а это означает, что информация о ранее вызванных подпрограммах будет потеряна. Однако, если вы инициируете нарушение прав доступа/ошибку сегментации из этой подпрограммы, указатель инструкции, где это произошло, будет сохранен, указывая на эту подпрограмму.

Однако, если стек поврежден и вы вернетесь из этой процедуры, будет очень сложно, если вообще возможно, выяснить, что произошло.

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

person rmhartog    schedule 18.01.2013
comment
Проблема в том, что нарушение прав доступа возникает внутри этой функции. Однако код Windows x86 начнет пытаться найти обработчик исключений Win32 SEH, и это скроет исходную ошибку. С подключенным отладчиком и прерыванием при первом исключении можно найти функцию. Однако, как только срабатывает механизм обработки исключений SEH (то есть, когда не прерываются исключения первого шанса), кажется, что все следы исчезли. - person Martin Ba; 18.01.2013

Это не прямой ответ на ваш вопрос.

Однако, когда я сталкивался с перезаписью стека, я запускал утилиту gflags, которая немедленно подтверждала бы запуск перезаписи стека.

Gflags предоставляется Microsoft.

person Stephane Rolland    schedule 18.01.2013

Это действительно зависит. Backraces, представленные в аварийном дампе, напрямую зависят от информации, хранящейся в стеке. Обычно это означает, что вы НЕ МОЖЕТЕ доверять обратной трассировке, если подозреваете повреждение стека.

Предоставленная вами функция, скорее всего, повредит ВЕСЬ стек, а затем вызовет исключение, когда вы превысите ограничения сегмента или достигнете памяти, которая недоступна для процесса. В это время в стеке не будет ничего, что указывало бы на подозреваемого.

person Tomek    schedule 18.01.2013