Аудит и дизассемблирование exploit'ов

         

структура SEH-фреймов


Первое двойное слово указывает на предыдущий SEH-фрейм в цепочке (если текущий обработчик не знает, что делать с исключением, он отдает его предыдущему обработчику; если ни один из обработчиков не может обработать исключение, операционная система выбрасывает знаменитое сообщение о критической ошибке и завершает работу приложения в аварийном режиме).

Следующее двойное слово — содержит адрес процедуры обработчика исключений (не путать с функцией-фильтром исключений, которая обслуживаться не операционной системой, а компилятором!). Очень заманчиво записать сюда указатель на shell-код, но вся проблема в том, что этого указателя мы не знаем и в общем случае не можем узнать! На самом деле, ситуация не так уж плачевна.

Рассмотрим процесс обработки исключений повнимательнее. В тот момент, когда прикладной код пытается сделать что-то недопустимое, процессор генерирует прерывание. Операционная система перехватывает его и передает внутренней функции KiUserExceptionDispatcher, содержащейся внутри NTDLL.DLL. Та в свою очередь вызывает промежуточную функцию RtlUnwind

(все из той же NTDLL.DLL), передающую управление фильтру исключений, установленным компилятором (в случае Microsoft Visual C++ эта функция называется __except_handler3), которая и вызывает прикладной обработчик, зарегистрированный программистом уязвимого приложения.

Короче, получается следующая цепочка вызовов:

NTDLL.DLL!KiUserExceptionDispatcher ->
NTDLL.DLL!RtlUnwind —>
__except_handler3



Содержание раздела