среда, 7 сентября 2011 г.

Как злоупотребляли оконными ловушками в Win16

Это перевод One way people abused hooks in 16-bit Windows. Автор: Реймонд Чен.

В прошлый раз мы увидели, как в 16-битных Windows реализуются оконные ловушки. Даже хотя значения HHOOK являются не прозрачными типами данных ("чёрным ящиком"), с которыми нужно работать как с описателями, многие программы "знали слишком много, чтобы стать опасными" - и воспользовались тем фактом, что значения HHOOK были просто указателями на предыдущую процедуру ловушки.

Самый частый способ использования этой информации во зло заключается в снятии ловушки неверным способом. Вместо вызова функции UnhookWindowsHook снова вызывалась SetWindowsHook! Более конкретно: текущая ловушка удалялась установкой на вершину цепочки предыдущей ловушки:
var
  g_hhkPrev: HHOOK;

// Установка ловушки
g_hhkPrev := SetWindowsHook(WH_KEYBOARD, MyHookProc);
...

// Безумие! Удаление ловушки установкой предыдущей ловушки "обратно"
SetWindowsHook(WH_KEYBOARD, g_hhkPrev);
Несмотря на это вопиюще неверное поведение, код работал; это вроде как две неверные вещи при сложении дали почти правильное. Если никто не трогал цепочку ловушек между установкой и таким "снятием" ловушки, то переустановка старой ловушки в вершину списка восстанавливала список ловушек в то же состояние, в которое он приходит при правильном удалении ловушки.

Но если между этими двумя вызовами кто-то другой установит их собственную ловушку, то установка старой ловушки заново приведёт к "удалению" не только MyHookProc, но и всех ловушек, которые были установлены после неё (это в точности та же проблема, которая получается, если вы неосторожно удаляете саб-классированные оконные процедуры).

Я до сих пор понятия не имею, почему кому-то взбрело в голову удалять ловушку именно таким способом вместо правильного - они ничего не сэкономили, а просто заменили одну строчку на другую:
UnhookWindowsHook(WH_KEYBOARD, MyHookProc);
Windows 3.1 ввела модель с SetWindowsHookEx/CallNextHookEx, которая не использовала технику внешнего связанного списка, а хранила список сама, внутренне. Это защитило цепочку ловушек от программ, которые портили её неверным управлением списком, но это также означало, что теперь все эти сумасшедшие программы, которые пытались удалить ловушку повторной установкой старой ловушки, теперь будут просто портить внутренний список ловушек. Нам пришлось написать специальный код, который определял такие случаи и заменял их на корректные вызовы.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.