Даже и не думайте пользоваться функцией Wow64DisableWow64FsRedirection!
Apr 3, 2009 · CommentsПрограммированиеWow64
Просто удивительно, насколько опасной может быть функция Wow64DisableWow64FsRedirection. Эта функция позволяет временно отключить перенаправление файловой системы в Wow64. Еще более удивительно, что лишь малая доля разработчиков соглашается менять свой код, даже после подробного объяснения, в чем, собственно, проблема.
В чем состоит опасность? Во-первых, при отключенном перенаправлении файловой системы не работает загрузка 32-х битных системных библиотек. Они, как правило, загружаются из system32 и только перенаправление ввода/вывода спасает ситуацию. Во-вторых, и это самое главное, разработчик очень редко полностью контролирует весь ввод-вывод на участке между Wow64DisableWow64FsRedirection и Wow64RevertWow64FsRedirection.
«Как это возможно?» - спросите вы, «ведь все три строчки кода – вот они, как на ладони». Очень просто. Вот неполный список случаев, когда может происходить неявная загрузка кода:
-
Неявный вызов LoadLibrary. Многие функции Win32 вызывают LoadLibrary. Один из примеров – Multimedia API. То же самое делают и другие библиотеки, особенно те, что поддерживают плагины.
-
Отложенная загрузка библиотек (Delayed Loading) – это хороший способ ускорить загрузку приложения. Проблема только в том, что загрузка может случиться в любой, в том числе самый неподходящий момент. Все приложения, так или иначе, используют отложенную загрузку, так как ею пользуются ключевые системные библиотеки.
-
Так называемые «DLL import forwarders» позволяют сказать загрузчику, что функция «Foo», экспортируемая из «Foo.dll», на самом деле реализована в «Bar.dll». В результате при попытке получить адрес функции «Foo», загрузчик попытается загрузить «Bar.dll». Например:
link /dump /exports c:\Windows\System32\kernel32.dll | findstr forwarded
1 0 AcquireSRWLockExclusive (forwarded to NTDLL.RtlAcquireSRWLockExclusive)
2 1 AcquireSRWLockShared (forwarded to NTDLL.RtlAcquireSRWLockShared)
14 D AddVectoredContinueHandler (forwarded to NTDLL.RtlAddVectoredContinueHandler)
15 E AddVectoredExceptionHandler (forwarded to NTDLL.RtlAddVectoredExceptionHandler)
70 45 CancelThreadpoolIo (forwarded to NTDLL.TpCancelAsyncIoOperation)
86 55 CloseThreadpool (forwarded to NTDLL.TpReleasePool)
87 56 CloseThreadpoolCleanupGroup (forwarded to NTDLL.TpReleaseCleanupGroup)
88 57 CloseThreadpoolCleanupGroupMembers (forwarded to NTDLL.TpReleaseCleanupGroupMembers)
89 58 CloseThreadpoolIo (forwarded to NTDLL.TpReleaseIoCompletion)
90 59 CloseThreadpoolTimer (forwarded to NTDLL.TpReleaseTimer)
91 5A CloseThreadpoolWait (forwarded to NTDLL.TpReleaseWait)
92 5B CloseThreadpoolWork (forwarded to NTDLL.TpReleaseWork)
-
Взаимодействие с COM объектами очень часто приводит к загрузке дополнительных библиотек. К примеру, это быть вызов QueryInterface или любой другой вызов возвращающий указатель на COM интерфейс.
-
Внедрение кода в другой процесс – обычное дело в Windows. Внедренный код может вызвать LoadLibrary в самый неподходящий момент. В этом случае виноват не ваш код, но с точки зрения пользователя упадет именно ваше приложение.
-
и т.д. и т.п.
Проблема еще и в том, что код, использующий Wow64DisableWow64FsRedirection, в общем-то, работает в большинстве случаев. Так что разработчик не видит проблемы до тех пор, пока код не будет запущен в незнакомом окружении на машине заказчика. Или пока не выйдет новая версия ОС, используемой библиотеки или клавиатурного шпиона, которая вдруг начала загружать код в том месте, где раньше ничего такого не происходило.
PS. А когда можно использовать Wow64DisableWow64FsRedirection? Единственный поддерживаемый сценарий – вызов CreateFile, обернутый в Wow64DisableWow64FsRedirection и Wow64RevertWow64FsRedirection.