Not a kernel guy

… in the Windows kernel team

Tuesday, April 1, 2008

Отгадка.

В комментариях к загадке ответ был дан почти сразу. Действительно, обработчик отложенной загрузки DLL попытается загрузить «version.dll» по имени, а не по полному пути. В результате загрузчик будет искать библиотеку, пользуясь правилами по умолчанию. Номер два в этом списке поиск DLL в system32, что при отключенном перенаправлении файловой системы, равноценно попытке загрузить 64-х битную DLL в 32-х битный процесс. Бум.

Но проблема на самом деле не так уж и проста, как может показаться с самого начала. Первая сложность здесь в том, что загрузка DLL происходит неявно для программиста. Из кода никак не понять, что библиотека выбрана для отложенной загрузки. В достаточном большом проекте это означает, что «любой залетный программист» из соседней группы может запретить перенаправление, исправляя какой-то свой баг. Причем какое-то время всё может работать, так как нужная библиотека могла загрузиться ранее. А потом, по закону подлости, это вылезет во время презентации продукта заказчику.

Причем это не единственный способ скрытой загрузки DLL. Таких способов масса: создание COM объекта, вызов CreateProcess или ShellExecute, установка хука на оконные сообщения и т.д. и т.п.

Вторая проблема заключается в том, что реализовать работающее/альтернативное решение либо сложно, либо неочевидно. Показательно, что из двух предложенных решений проблемы из предыдущего топика только одно решало проблему полностью, а второе – только маскировало проблему. С другой стороны, даже правильное решение не работает однообразно для 32-х разрядного и 64-х разрядного кода. 32-х битное приложение должно использовать «sysnative» для доступа к настоящему каталогу «system32». 64-х разрядные приложения ничего не знают о «sysnative» и подобное перенаправление для них не работает. Да, я знаю, что Microsoft – зло. В данном конкретном случае я полностью согласен. :-)

Ещё один пример, на форуме разработчиков Far Manager обсуждался плагин, который должен был запрещать перенаправление файловой системы раз и навсегда при старте приложения. Именно с целью попасть в настоящий «system32». Не знаю, чем это закончилась, но помню аргументацию в стиле «попробовал - работает». Действительно работает, пока не сломается.

Третья сложность заключается в неочевидных взаимоотношениях LoadLibrary и перенаправления файловой системы. Если запустить 32-х разрядную версию fileverison.exe, чтобы получить версию ядра (файл «%windir%\system32\ntoskrnl.exe»), то случится странное. Не смотря на перенаправление файловой системы, 32-х разрядный процесс успешно загрузит ресурсы из 64-х битного «ntoskrnl.exe». Хотя никакого «ntoskrnl.exe» в «%windir%\syswow64», куда перенаправляется процесс, нет.

Как так получается? Очень просто. GetFileVersionInfo вызывает LoadLibraryEx с флагом LOAD_LIBRARY_AS_IMAGE_RESOURCE. Этот флаг указывает, что файл загружается только для извлечения ресурсов. Если указан этот флаг и первая попытка найти файл с заданным именем окончилась неудачей, LoadLibraryEx попробует отключить перенаправление файловой системы и повторит попытку. В приеме выше, 64-х битный «ntoskrnl.exe» будет загружен во время второй попытки. Добавлю, что этот механизм работает только для модулей «system32» и своему появлению он обязан проблемам с совместимостью к каким-то из приложений.

Вот такие вот ужасы.

Posted at 9:28 pm •

RSS feed | Trackback URI

4 Comments »

Comment by balmaster — April 2, 2008 @ 2:35 pm

Нда, жестокая весчь. Совмещать 64 битную операционку с 32 битным унаследованым кодом.
Интересно а ктонить считал что больше + или - бизнес поимел от такой политики?

Comment by Not a kernel guy — April 3, 2008 @ 7:23 am

Интересно а ктонить считал что больше + или - бизнес поимел от такой политики?

Это только с точки зрения “правильности” дизайна выглядит ужастно. А с практической точки зрения это очень даже неплохое решение. Портирование приложений (и самой OS) на 64 бита значительно упростилось из-за таких вот вывертов. C’est la vie.

 
 
Comment by Cartman — April 4, 2008 @ 9:35 am

> Не знаю, чем это закончилась, но помню аргументацию в стиле «попробовал - работает».

Закончилось это встраиванием в 32-битную версию far хука, включающего перенаправление только на время запуска процессов и загрузки dll.

Comment by Not a kernel guy — April 4, 2008 @ 5:34 pm

Ну работать это будет до первого дятла, т.е. до первой внедренной DLL, которая захочет чего-то найти в system32.

 
 

Your Comment (smaller | larger)

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Powered by WordPress