Перехват исключений (SEH)
Создание библиотек dll
Перехват сообщений Windows
Перехват API
Примеры
Способы обработки отладочных событий
1. Читать и писать в память отлаживаемого процесса
ReadProcessMemory, WriteProcessMemory
5 параметров:
a. Дескриптор процесса
b. Адрес в памяти процесса, куда читать
c. Адрес строки в отладчике куда читать
d. Количество байтов
e. Реально прочитанное количество байт
2. Работа с контекстом (работа с регистрами отлаживаемого процесса)
GetThreadContext – получить контекст
SetThreadContext – сохранить контекст
2 параметра:
a. Дескриптор потока
b. Адрес структуры CONTEXT (хранятся значения регистров)
CONTEXT STRUCT
ContextFlags dd ?
CONTEXT_SEGMENTS
regGS dd ?
reg FS dd ?
reg ES dd ?
reg DS dd ?
CONTEXT_INTEGER
regEdi dd ?
reg Esi dd ?
reg Ebx dd ?
reg Ecx dd ?
reg Eax dd ?
CONTEXT_CONTROL // управления
regEbp dd ?
regEip dd ?
regCs dd ?
regFlag dd ?
regEsp dd ?
regSS dd ?
3. Точки остановки BREAKPOINTS
int 3 ; 3 – номер прерывания
точка остановки
int – interrupt (0CCh)
0CCh поставим во время работы отлаживаемого процесса в нужное нам место памяти.
Когда программа дойдет до этого места, она остановится, мы сможем обрабатывать отладочное событие EXCEPTION_BREAKPOINT. Предварительно нужно байт, вместо которого будет ставиться int 3 сохранить в отладчике а потом восстановить, а потом ещё вернуться на байт назад для работы программы.
Отладка wink.exe
Запуск wink.exe
При нажатии на кнопку расчет получится число 6.
6 = 3 + 2 + 1.
Нужно написать отладчик, чтобы wink.exe под отладчиком работала иначе. Она выводит ImageBase (при CREATE_PROCESS_DEBUG_EVENT), потом значение регистра EIP (EXCEPTION_BREAKPOINT, 1 раз), Key (пароль, выводится при EXCEPTION_BREAKPOINT, 2 раз) и только после этого появится тот диалог.
И на экран выводится не 6, а 3ка (также при CREATE_PROCESS_DEBUG_EVENT: 03h заменить на 02h). При закрытии должно появиться окошко, где будет написано DEBUG_EXIT.
Int 3 – ставится тоже при CREATE_PROCESS_DEBUG_EVENT (также предварительно записывается байт)
При ECXEPTION_BREAKPOINT – наращиваем счётчик брэйкпоинта
При втором брэйке, вывести ключ, восстановить программу
Когда конец работы – выводим MessageBox._
Джерри Рихтер - создание эффективных Win32 приложений
Structure Exception Handler
В языках высокого уровня это на уровне try/catch, но программа громадно раздувается. Мы рассмотрим обработку исключений на уровне Win32 (на низком уровне)
Есть область TIB (системная область), на нее указывает регистр FS, в начале области находится адрес структуры SEH, а одно из полей структуры указывает на обработчик исключений. (Косвенная адресация на обработчик исключений)
Структура SHE содержит 5 полей, но мы рассмотрим 2 из них:
1. prevLink – указывает на следующий SEH (структуру SEH)
2. currentHandler() – напрямую указывает на обработчик исключений
3. …
Структура должна находится в системном стеке, у каждой структуры свой обработчик
Обработчики работают на уровне ядра.
Наша задача – написать обработчик, который при доступе к нижнему предохранительному блоку, выдаётся сообщение
Пример:
При обращении к адресу 0, выводим MessageBox.
Нам нужно сделать новый SEH, указать на него и prevLink’ом указать на следующую структуру и создать свой обработчик
.data
str1 db 'Exception, access to address 0'
.code
start:
push offset SehHandler
push FS: [0] ; prevLink
mov FS:[0], ESP ;сформировали 2 действие (указатель на наш SEH)
mov eax, 0
mov [eax], eax
SehHandler PROC
invoke MessageBox, 0, addr str1, NULL, MB_ICONERROR
pop FS:[0]
add ESP, 8
mov eax, 1 ;передано управление следующему обработчику
ret
endp
Если мы хотим, чтобы серого окошка не было, мы можем добавить поля в SEH. В структуре SEH могут существовать 3 поля, которые позволяют после исключения не выходить из программы, а переходить на безопасное место в программе (исправление исключений)