Создание или уничтожение SEH-кадра
Первые инструкции после установки кадра стека часто похожи на следующий фрагмент, который является стандартным кодом, начинающим _try-блок. Первый узел в цепочке SEH-обработчиков расположен в TIB со смещением 0. В показанном ниже фрагменте кода дизассемблера компилятор помещает в стек значение данных и указатель на функцию _except_ handlers. Первая инструкция MOV обращается к TIB. Смещение 0 указывает, что узел добавляется к вершине цепочки исключений. Две последних инструкции показывают, каким образом код перемещает фактический узел в цепочку
PUSH 004060d0
PUSH 004014a0
MOV EAX , FS:[00000000]
PUSH EAX
MOV DWORD PTR FS:[0] , ESP
Хотя этот пример довольно прост и понятен, компилятор не всегда производит такой аккуратный код. Иногда он расширяет область создания SEH-кадра. В зависимости от флажков генерации кода и оптимизации, компилятор перемещает окружающие инструкции так, чтобы усилить преимущества конвейерной обработки CPU. Следующий пример дизассемблерного кода, в котором загружены символы библиотеки KERNEL32.DLL, демонстрирует запуск функции IsBadReadPtr из Microsoft Windows NT 4.
MOV EAX , FS:[00000000h]
PUSH EBP
MOV EBP , ESP
PUSH 0FFh
PUSH 77F3DlE8h
PUSH _except_handler3
PUSH EAX
MOV EAX , [BaseStaticServerData];
MOV DWORD PTR FS:[0000000h] , ESP
Как показывает следующий фрагмент кода, уничтожение SEH-кадра намного проще, чем его создание. Основной момент, который нужно запомнить, это то, что запись FS: [0] означает доступ к SEH.
MOV ЕСХ , DWORD PTR [EBP-lOh] .
MOV DWORD PTR FS:[0] , ECX
Организация доступа к TIB
Значение в FS:[18] является линейным адресом структуры TIB. В следующем фрагменте кода реализация GetCurrentThreadid (из Windows 2000) получает сначала линейный адрес TIB-блока и затем, в позиции со смещением 0x24 (в Т1В-блоке) — фактический идентификатор (ID) потока.
GetCurrentThreadid:
MOV EAX , FS:[00000018h]
MOV EAX , DWORD PTR [EAX+024h]
RET
Доступ к локальному хранилищу потока
Локальное хранилище потока (Thread Local Storage — TLS) — это механизм Win32, который позволяет каждому потоку (в многопоточной ситуации) иметь свой собственный экземпляр глобальных переменных. Указатель на массив локального хранилища потока размещается в структуре TIB со смещением 0х2С. Следующий фрагмент кода дизассемблера показывает, как получить доступ к указателю локального хранилища потока.
MOV ЕСХ , DWORD PTR FS:[2Ch]
MOV EDX , DWORD PTR [ECX+EAX*4]