Техника защиты компакт-дисков от копирования



              

Передача управления на функцию обработки сообщений


Двум предыдущим способам "реанимации" приложений присущи серьезные ограничения и недостатки. При тяжелых разрушениях стека, вызванных атаками типа buffer overfull или же просто алгоритмическими ошибками, содержимое важнейших регистров процессора окажется искажено, и мы уже не сможем ни совершить откат (стек утерян), ни выйти из текущей функции (EIP "смотрит" в "космос"). В консольных приложениях в такой ситуации действительно очень мало, что можно сделать… Вот GUI –— другое дело! Концепция событийно ориентированной архитектуры наделяет всякое оконное приложение определенными серверными функциями. Даже если текущий контекст выполнения необратимо утерян, мы можем передать управление на цикл извлечения и диспетчеризации сообщений, заставляя программу продолжить обработку действий пользователя.

Классический цикл обработки сообщений выглядит так как это показано в листинге 3.14.:

Листинг 3.14. Классический цикл обработки сообщений

while (GetMessage(&msg, NULL, 0, 0))

{

             TranslateMessage(&msg);

             DispatchMessage(&msg);

}

Листинг 14 классический цикл обработки сообщений

Все, что нам нужно –— это передать управление на цикл while, даже не заботясь о настойке кадра стека, поскольку оптимизированные программы (а таковых большинство) адресуют свои локальные переменные не через EBP, а непосредственно через сам ESP. Конечно, при обращении к переменной msg, функция "угробит" содержимое стека, лежащее ниже его вершины, но это уже не важно.

Правда, при выходе из приложения оно "упадет" окончательно (ведь вместо адреса возврата из функции обработки сообщений, машинная команда RET обнаружит на вершине стека неизвестно что), но это произойдет после сохранения всех данных и потому никакой угрозы не несет. Исключение составляют приложения, "забывающие" закрыть все открытые файлы и перекладывающие эту работу на плечи функции ExitProcess.


Содержание  Назад  Вперед