Привет. В статье "SEH изнутри" http://www.wasm.ru/article.php?article=Win32SEHPietrek1 на рис.3 приведен следующий листинг: Код (Text): DWORD handler = (DWORD)_except_handler; __asm{ // Создаем структуру EXCEPTION_REGISTRATION: push handler // Адрес функции обработчика исключений. push FS:[0] // Адрес предыдущего EXECEPTION_REGISTRATION. mov FS:[0], ESP // Добавляем в связанный список EXECEPTION_REGISTRATION. } __asm{ mov eax, 0 // Обнуляем значение регистра EAX. mov [eax], 1 // Чтобы преднамеренно вызвать исключение, делаем запись по нулевому адресу. } printf("After writing!\n"); __asm{ // Удаляем из связанного списка EXECEPTION_REGISTRATION. mov eax, [ESP] // Получаем указатель на предыдущий EXECEPTION_REGISTRATION. mov FS:[0], EAX // Устанавливаем в начале списка предыдущий EXECEPTION_REGISTRATION. add esp, 8 // Удаляем из стека структуру EXECEPTION_REGISTRATION. } Я не могу понять следующее - где-то читал, что по адресу fs:[0] живет TIB, но в комментах сказано, что на этот адрес пишем адрес предыдущего EXECEPTION_REGISTRATION. И что значит "Добавляем в связанный список EXECEPTION_REGISTRATION" в следующем комменте, что такое вообще связный список? Тут скорее всего все просто, но я понятия не имею где искать ответ, поэтому решил спросить на форуме.
В начале NT_TIB адрес EXCEPTION_REGISTRATION. Смотрим структуру NT_TIB http://www.nirsoft.net/kernel_struct/vista/NT_TIB.html
т.е. по адресу fs:[0] сидит структура _NT_TIB, и мы в стек пихаем адрес PEXCEPTION_REGISTRATION_RECORD? А что делает mov FS:[0], ESP - что сейчас находится в ESP?
Nicholas_F, не совсем понятно: что именно вам не понятно? Действительно, по адресу FS:[0] находится TIB. TIB является структурой, и выглядит (если память не изменяет) следующим образом: Код (Text): typedef struct _NT_TIB { struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; PVOID StackBase; //база стека PVOID StackLimit; //лимит стека PVOID SubSystemTib; union { PVOID FiberData; DWORD Version; }; PVOID ArbitraryUserPointer; struct _NT_TIB *Self; } NT_TIB; typedef NT_TIB *PNT_TIB; Как видите, первым элементом этой структуры является указатель на вершину связного списка ExceptionList. Каждый элемент этого списка содержит адрес обработчика исключений и адрес предыдущего элемента связанного списка ExceptionList. Таким образом на текущий обработчик исключений SEH указывает тот элемент списка ExceptionList, который находится на вершине связанного списка, адрес которого находится по адресу FS:[0]. Что касается связных списков, то они бывают нескольких видов, и в данном случае используется однонаправленный связный список. IMHO, проще всего представить себе этот список как массив, элементы которого хранятся в памяти не последовательно, а в разных местах. каждый элемент этого списка представляет собой структуру, в которой помимо прочего хранится адрес предыдущего элемента этого списка.
В ESP находится адрес нового элемента (являющегося структурой EXCEPTION_REGISTRATION_RECORD) добавляемого в связный список.
Ага... понятно, но вот это не совсем ясно: ESP - по идее указывает на вершину стека... откуда там может быть адрес нового элемента являющегося структурой EXCEPTION_REGISTRATION_RECORD?
Потаму что эта структура сформирована в стеке, и находится на его вершине (на которую указывает регистр ESP).
Вот инструкции, которые формируют эту структуру в стеке: Код (Text): push handler // Адрес функции обработчика исключений. push FS:[0] // Адрес предыдущего EXECEPTION_REGISTRATION.
Нет, fs:[0] это не NT_TIB. Селектор fs указывает на сегмент, содержащий в себе Thread Environment Block, начинающийся с NT_TIB (Thread Information Block). fs:[0] - это уже поле в NT_TIB со смещением 0, то есть ExceptionList Называть fs:[0] адресом TIB некорректно.
Вот такая непонятка еще, про одну из SEH структур: Iczelion в своих туториалах по PE формату использует следующую структуру для обработки исключения: Код (Text): SEH struct PrevLink dd ? CurrentHandler dd ? SafeOffset dd ? PrevEsp dd ? PrevEbp dd ? SEH ends Как я понимаю, первые два поля - это структура EXEPTION_REGISTATION, а к чему относятся посление 3 поля? Эта структура фиксированной длины, значит она имеет свое описание? Как я понял, после возврата callback функции ExeptionContinueExecution выполнение кода продолжится со смещения SafeOffset и оно сохраняется в структуре CONTEXT. Но в этой же структуре сохраняются и значения регистров на момент исключения откуда они и могут быть восстановлены - зачем их сохранять еще и в нашей SEH struct?
Это понял. А про SEH struct? Как понимать эту структуру, включающую в себя EXEPTION_REGISTRATION и еще что-то...?