Метафизика wmf файлов

       

шаблоны, используемые Ильфаком для распознавания пролога Escape


В нормальных условиях этого более, чем достаточно, но задумаемся, что произойдет, если отладчик типа soft-ice

установит программную точку останова на Escape. При этом в первый байт функции будет записан код CCh и hotfix уже не сможет распознать пролог, а, значит, thunk

окажется не установлен и система останется уязвимой! Конечно, цивильные люди отладчиками не пользуются, но у них могут быть установлены (возможно, неявно) некоторые API-шпионы, троянские программы, защитные механизмы и т. д….

Некоторые антивирусные программы и защитные системы (такие, например, как Lavasoft's Ad-Watch) не позволяют приложениям модифицировать ветку AppInit_DLLs, автоматически восстанавливая ее содержимое. В этом случае, hotfix не сработает, пока разбушевавшегося "сторожа" не утихомирить вручную. Проблема в том, что пользователь может и не знать, что hitfix не функционален… А ведь черви не дремлют!

К тому же, заплатка загружает библиотеку GDI32.DLL

всем приложениям даже тем, которым она совершенно не нужна, заставляя ее понапрасну болтаться в памяти, а точнее в адресном пространстве, благо оно общее и перерасхода памяти не возникает. Ну… практически не возникает. При модификации функции Escape каждый процесс получает копию отпаченной страницы, то есть мы теряем по одной странице физической памяти на процесс, чем можно пренебречь.

(Кстати говоря, Чтобы временно отключить hotfix достаточно просто переименовать wmfhotfix.dll) во что-нибудь другое. Это проще (и быстрее), чем удалять его деинсталлятором..

Хакеры, постоянные держащие загруженный soft-ice могут (теоретически) установить условную точку останова на GDI32!Escape с аргументом 09h:, однако, практически лично у меня она не срабатывает.: "bpx Escape if esp->
8==09", тогда никакие заплатки устанавливать вообще не понадобиться
. При выполнении wmf-эксплоита soft-ice тут же всплывет и нам будет достаточно сказать "(esp+8) 0", а затем выйти из отладка по <Ctrl-D>
или "
x".
При
совместном использовании soft-ice с hotfix' ом лучше устанавливать не программную, а аппаратную точку останова: "bpm Escape X", иначе возникнет уже упомянутый конфликт. Но это еще что! При установке программной точки останова существует ничтожна малая вероятность, что она будет установлена в тот злополучный момент когда hotfix уже опознает hotlink, но еще не успеет внедрить jump в начало Escape. Результатом будет крах системы.

Примерный сценарий развития событий выглядит так:

 

q       отладчик запоминает оригинальное содержимое



первого байта
Escape;

q       в первый байт Escape отладчик ставит байт CCh

q       Ильфак затирает этот CCh, внедряя сюда jump;

q       в какой-то момент точка останова срабатывает, передавая управления отладчику;

q       отладчик восстанавливает байт Escape

(пролог)
, за который идет покоцанный jump;

q       эта последовательность не имеет никакого смысла и выбрасывает исключение;

q       результат: крах.

 

Еще одно мелкое замечание, даже скорее придирка. Ходят слухи, что в последующих версиях Windows, Microsoft запретить прикладным приложениям приставить все три атрибута доступа PAGE_EXECUTE_READWRITE и это сможет сделать только система или администратор. Поэтому, сначала надо делать PAGE__READWRITE, а потом PAGE_EXECUTE, но это, как говориться, уже задел на будущее, причем весьма далекое и туманное.

Мыщъх так же написал свой собственный fix, работающий по тому же самому принципу, что и заплатка от Ильфака, но укладывающийся всего в десяток строк, "движок" которого прилагается к статье (см. файл kpnc-hack.c). Он перехватывает MessageBoxA и пишет в заголовке "hacked". Во избежание недоразумений перехват осуществляется в переделах адресного пространства моего процесса, то есть локально, но при желании его можно глобализовать, поместив в dll, подключаемую через AppInit_DLLs.



Вот как он работает:

 

q       сохраняем некоторое кол-во байт от начала API-функции (>
=  sizeof(jump)
);


q       ставим в начало функции jump на наш thunk;

q       в thunk'е: анализируем аргументы функции и делаем все, что хотим;

q       в thunk'е: восстанавливаем оригинальное содержимое функции;

q       в thunk'е: вызываем восстановленную функцию call'ом;

q       в thunk'е: вновь устанавливая jump на thunk и выходим;

 

Чтобы постоянно не устанавливать атрибуты PAGE_READWRITE перед каждым копированием, их достаточно установить всего один раз. Это чуть-чуть уменьшит накладные расходы, однако, даже при перехвате интенсивно используемых API-функций (к числу которых Escape со всей очевидностью не принадлежит), издержки получаются исчезающее малы, поэтому ими можно полностью пренебречь.

Проблема в другом. Существует вполне осязаемая вероятность, что в момент восстановления оригинального содержимого функции кто-то вызовет ее в обход thunk'а! А если такой вызов произойдет в процессе копирования кода, мы поимеем непредсказуемое поведение. Но это в теории. На практике, Windows поддерживает механизм Copy-on-Write, автоматически "расщепляя" модифицируемые страницы, а это значит, что вызвать грабли может только один из потоков текущего процесса. Применительно к Escape – ни Internet Explorer, ни Irfan Viewer просто не в состоянии одновременно вызывать Escape из двух различных потоков, поэтому такой трюк вполне законен. Он упрощает программирование и снимает проблему с CCh, а так же обладает другими преимуществами, о которых нет никакого смысла распространяться, поскольку, кто не успел — тот опоздал. В смысле мыщъх опоздал со своим fix'ом или все-таки не опознал? Ведь его fix работает и пот 9x, для которой до сих пор никакого лекарства нет…


Содержание раздела