- Ntvdm 64 bit windows
- Скачать ntvdm64.dll для Windows
- Ошибки ntvdm64.dll
- NTVDM and 16-bit app support
- Current status of NTVDM
- Security and Limitations
- What if I still need to run 16-bit apps on 32bit Windows 10?
- Steps to enable/disable 16-bit application support/NTVDM in Windows 10
- Получаем системные привилегии с помощью ошибок в NTVDM
- NTVDM
- Режим реального времени
- Режим Virtual 8086
- CVE-2013-3196 (write-what-where в nt!PushInt)
- General Protection Fault
- Где собака зарыта
- CVE-2013-3197 (write-what-where в nt!PushException)
- Причина головной боли
- CVE-2013-3198 (write-what-where в nt!VdmCallStringIoHandlerPushException)
- Мысли вслух
- Резюмируя
Ntvdm 64 bit windows
NTVDMx64 makes it possible to run old DOS applications under 64-bit Windows 7 and Windows 10. (It is reported to work correctly with Windows Server 2008 R2, and perhaps also with more recent Windows Server versions.)
Recent versions of NTVDMx64 make it possible to run 16-bit Windows applications under 64-bit Windows, but you may prefer to use the much less obtrusive otvdm/winevdm for this purpose.
Unlike emulator applications such as vDos and DOSBox, NTVDMx64 is fully integrated with Windows, with the same access to the Windows file system and ports that NTVDM has under 32-bit Windows. NTVDMx64 does not perform as quickly as DOSBox or vDos, but its integration is a unique and important advantage. For example, a DOS application running under NTVDMx64 can print directly to LPT1 if the computer has a parallel port; this is impossible under DOSBox (although possible with vDos through a configuration option).
NTVDMx64 is not my work! It is a patched version of Microsoft’s original NTVDM, based on the leaked source code of Windows NT, and patched by a programmer who calls himself «Leecher1337.» The leaked source code may not be distributed legally, so, in order to avoid legal problems, Leecher1337 publishes only patch files that contain modifications to the original code. These patch files may be downloaded from his GitHub page. With the proper development environment, the patched Windows NT code can be compiled to build a 64-bit version of NTVDM, which Leecher1337 has named NTVDMx64. Do not waste your valuable time sending me questions about NTVDMx64! I don’t know the answer! Post your questions on Leecher1337’s GitHub page! I really mean this!
Leecher1337 does not distribute a compiled version of his patched version, but I have obtained a copy, together with an installer, which may be downloaded here (in versions for sixteen languages). I did not build this copy; I obtained it from another source. To install NTVDMx64, run INSTALL.BAT, and restart your system when prompted. If you want, you may uninstall it from the Control Panel or PC Settings. This installer is frequently updated to match the latest version of Leecher1337’s code. (Updated March 2021.)
Warning: If Microsoft asks me to take down this page for any reason at all, the page and all files linked from it will be deleted immediately. Microsoft has not made any such request during the years that this page has been posted.
All comments and questions about NTVDMx64 should be posted on Leecher1337’s Github page. Do not waste your valuable time sending me e-mails asking for help installing and running NTVDMx64, because I will not know the answers. Open an issue at the GitHub page for this project.
NTVDMx64 cannot run if the «secure boot» feature is enabled on your computer. If secure boot is enabled, the installer will warn you and refuse to run. You must disable secure boot in the BIOS settings of your machine; it is not a Windows setting. If you don’t know how to accomplish this, search the web or consult the manual for your system board.
Windows Smart Screen may refuse to let the installer run; choose Run Anyway from the buttons that appear when you click on More Info (or some similar setting). Windows Defender may block a DLL in the program; find it in the Quarantine settings, click on its name, and choose Restore. Other anti-virus programs may similarly block the installation. Don’t complain to me or to Leecher1337; complain to your anti-virus vendor. And don’t waste your extremely valuable time asking me or Leecher1337 whether this software is unsafe. If you don’t want to override these security features, don’t use this software.
Cautions and warnings: NTVDMx64 uses non-standard methods of process propagation to inject loader code into 32-bit and 64-bit applications. I don’t know exactly what this means, but I am reliably told that this may cause problems not yet recognized. You may want to experiment with a VMware or other virtual machine before running it on production systems. Also, it has been tested only under 64-bit Windows 7 and 64-bit Windows 10. Do not attempt to run it under any earlier version!
You may launch DOS applications from the Windows command prompt (CMD) or by double-clicking them in Windows Explorer. The first time you try to run any DOS program, you may see an error message; try again immediately afterwards, and the program should run.
Some programs will require command-line switches to run. For example, WordPerfect for DOS 6.x should be started with the /NE command-line switch. Some programs will not run at all; there is probably nothing that can be done about those programs, but you should feel free to file a very detailed «issue» at the GitHub page linked above.
Microsoft’s NTVDM uses a licensed version of the SoftPC emulation software by Insignia. The original NTVDM, written for Windows NT, operated differently when run on Intel’s x86 hardware and on alternate hardware, including VAX VMS, DEC Alpha, and Mips. SoftPC included a software-based CPU (CCPU) that could emulate an Intel 80386 processor. For performance reasons, when running under an Intel processor, the emulated CPU was not used; instead, the V86 mode of the hardware CPU was used, via a kernel interfaceВ which Microsoft called «Monitor». So the CCPU was used only on non-x86 architectures, and the Monitor interface was used on x86. Leecher1337’s NTVDMx64 modifies the original code so that the CCPU is used when running under 64-bit Windows, because Intel processors have no V86 support in the «long mode» used by 64-bit Windows.
This copy of NTVDMx64 makes one change in the CONFIG.NT file from the original NTVDM: it increases the FILES = line from 20 to 100, which should be sufficient for most applications). If you want to change that number, or make any other changes in CONFIG.NT, do the following: run CMD.EXE as an administrator; navigate if necessary to \WINDOWS\SYSTEM32 and run the command «start notepad config.nt», and edit the file.
For a full description, see Leecher1337’s Github page, which also notes some problems with DPMI programs and DOS extenders.
Like NTVDM, NTVDMx64 can be customized from the system menu of an NTVDMx64 window to change window size, display font, etc. Unlike NTVDM, it switches smoothly between text and graphic modes.
Скачать ntvdm64.dll для Windows
Платформа | Файл | Продукт | Язык | Описание | |
---|---|---|---|---|---|
ntvdm64.dll v. 6.1.7601.24540 | Microsoft Windows Operating System v. 6.1.7601.24540 | English (U.S.) | 16-bit Emulation on NT64 | ||
ntvdm64.dll v. 6.1.7601.24540 | Microsoft Windows Operating System v. 6.1.7601.24540 | English (U.S.) | 16-bit Emulation on NT64 |
Ошибки ntvdm64.dll
Ошибки ntvdm64.dll возникают по нескольким причинам, например, файл может быть поврежден, удален или не найден на компьютере. Распространенные ошибки библиотек:
- Ошибка при запуске ntvdm64.dll: не найден указанный модуль.
- Файл не предназначен или несовместим с версией Windows.
- Отсутствует ntvdm64.dll, попробуйте переустановить программу.
- Модуль или библиотека не обнаружены на компьютере.
- ntvdm64.dll вернул код ошибки.
Чтобы исправить ошибки ntvdm64.dll, скачайте файл и переустановите его в системной папке Windows. В некоторых случаях файл должен находиться в папке с игрой или программой. Подробная инструкция по установке ntvdm64.dll и других библиотек находится в разделе «Помощь».
NTVDM and 16-bit app support
NTVDM, or the NT Virtual DOS Machine, is a system component introduced in 1993 for all IA-32 editions of the Windows NT family (not included with 64-bit versions of the OS). This component allows the execution of 16-bit Windows applications on 32-bit Windows operating systems, as well as the execution of both 16-bit and 32-bit DOS applications. The Windows NT 32-bit user-mode executable that is the basis for a single DOS (or Windows 3.x) environment is called ntvdm.exe.
Current status of NTVDM
Given that it’s older technology introduced more than 20 years ago, the Microsoft Windows team can provide only limited support for NTVDM. Many enterprise customers are still running 16-bit Windows applications and depending on this feature. However, in modern operating systems, it’s in maintenance mode and is no longer being developed. Therefore, our recommendation is that customers do not use NTVDM. We encourage our customers to build new apps that don’t rely on this component.
NTVDM is a Feature on Demand and only supported on the x86 version of Windows. It is not supported on x64 and ARM versions of Windows, which do not support 16-bit x86 code of any kind, including DOS programs.
Security and Limitations
The technology underlying NTVDM is no longer actively under development and use of this technology may pose security risks. Microsoft does have Device Guard and other Windows features that can mitigate the security risks. We recommend that NTVDM is turned off in all enterprise environments.
What if I still need to run 16-bit apps on 32bit Windows 10?
We strongly recommend that you update your apps, so they are no longer dependent on NTVDM.
If you need assistance updating older apps, so that you are no longer dependent on this technology, enterprise customers can receive support. App Assure is a free program available to assist with app compatibility and OS upgrade issues. To get started, you can submit a request or email the team directly for support.
Steps to enable/disable 16-bit application support/NTVDM in Windows 10
If you are unable to update your apps and need to use NTVDM on Windows 10, he’s how to do so.
To ensable this feature, you must be running Windows 10 32-bit and must have local administrator privileges. We do not recommend enabling end-users to have local administrator privileges.
NTVDM is provided as a Feature on Demand, which first must be installed using a DISM command. Run Windows PowerShell ISE as an administrator and use the following command:
- To enable NTVDM: DISM /online /enable-feature /all /featurename:NTVDM
- To disable NTVDM: DISM /online /disable-feature /featurename:NTVDM
—>
Получаем системные привилегии с помощью ошибок в NTVDM
Обратная совместимость — вещь хорошая, но использовать ее надо в разумных пределах. Ведь до сих пор в ядре Windows можно найти код, разработанный еще в прошлом веке. Говорить о его высокой безопасности было бы глупо. И мы докажем это на примере трех privilage escalation уязвимостей, прижившихся в подсистеме виртуальной машины DOS
В 1978 году компания Intel выпустила первый процессор семейства х86, модели 8086, который предоставлял довольно ограниченную среду для исполнения 16-битного кода, известную под названием «режим реального времени» (Real mode). Вскоре после этого началась активная разработка программных решений для новой аппаратной платформы, причем как операционных систем, так и работающих в них обычных программ. Система Disk Operating System (DOS) от Microsoft быстро утвердилась в качестве ведущей рабочей среды для десктопных ПК, а приложения под эту ОС создавались и выходили на рынок в течение более десяти лет. В качестве самых известных примеров можно привести Norton Commander, ChiWriter или Quattro Pro. При разработке в 1992 году архитектуры NT для операционной системы Windows, которая использовала преимущества уже более мощного и безопасного защищенного режима (Protected Mode), одним из ключевых решений стало сохранение обратной совместимости с DOS, то есть обеспечение возможности безопасного запуска старых программ в новом графическом окружении.
WARNING
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
NTVDM
Созданный в Windows специальный режим совместимости получился очень функциональным. Из-за того, что он был довольно сложным компонентом как с технической стороны, так и со стороны логики работы, его появление открыло локальным пользователям много новых возможностей проведения атак, направленных на повышение своих прав в операционной системе. В NTVDM уже не раз находили и исправляли проблемы безопасности, но до сих пор в ядре остается много интересных и неисследованных возможностей. В следующем разделе мы детально рассмотрим одну из них — специфичную обработку исключений, возникающих в хост-процессе NTVDM.EXE. Тут, правда, стоит отметить, что любой потенциальный баг, который может обнаружиться в подсистеме совместимости DOS, затронет только 32-битные платформы Windows, так как 64-битные версии системы не поддерживают VDM из-за особенностей реализации режима Long Mode, в котором исполняется 64-битный код на процессорах Intel. В новых операционных системах Windows 8 и 8.1 воздействие потенциальных уязвимостей ядра нивелируется за счет того, что там эта подсистема отключена по умолчанию, а для ее запуска необходимы административные права. Тем не менее эти уязвимости можно успешно задействовать без участия пользователя на системах от Windows XP до Windows 7 32-бит (а на данный момент такие системы предположительно составляют около 50% парка всех десктопных ОС).
Режим реального времени
Поддерживать обратную совместимость с 16-битными приложениями для современного 32-битного окружения очень сложно с технической точки зрения из-за фундаментальных различий в функционировании между реальным и защищенным режимом. Сюда входят и режимы работы процессора, и ширина слов и адресов, и кодирование инструкций, и много других моментов. Иначе говоря, стандартными средствами современных операционных систем запустить устаревшие программы из 80-х не получится. С другой стороны, переключение процессора в реальный режим каждый раз при запуске 16-битной программы тоже не выход, поскольку это лишает смысла базовые установки защищенного режима, такие как разделение прав. Передача управления потенциально недоверенному коду, который работает в практически неограниченной среде исполнения и имеет прямой доступ ко всей периферии компьютера, не только создает потенциальную угрозу безопасности системы, но и лишает операционную систему контроля над компьютером, так как решение о возврате в предыдущий рабочий контекст будет приниматься именно этим старым приложением.
Режим Virtual 8086
Инженеры Intel, которые прекрасно понимали эти и многие другие связанные с обратной совместимостью проблемы, разработали еще один совершенно новый режим исполнения, назвав его Virtual 8086 (V8086), который стал важной составляющей защищенного режима. Основная особенность режима V8086 состоит в том, что для работающего в нем кода он совершенно неотличим от реального режима, но при этом полностью управляется основной операционной системой. Это позволяет запускать старые приложения в 32-битном окружении с сохранением безопасности и без негативных побочных эффектов. Эту технологию можно рассматривать в качестве механизма виртуализации для ПО DOS, в котором операционная система выполняет роль монитора виртуальной машины (Virtual Machine Monitor — VMM). VMM отвечает за создание рабочей среды и обработку критичных и привилегированных инструкций, которые использует гостевое приложение, при этом 16-битный код выполняется в специальном режиме и с нативной скоростью. Типичный, разработанный Intel порядок исполнения для операционной системы, использующей V8086, показан на рис. 1.
Рис. 1. Передача управления операционной системой при выполнении устаревших 16-битных приложений
В случае Microsoft Windows сущность «операционная система» далее распадается на два компонента: ядро и процесс NTVDM.EXE, работающий на уровне пользователя. Поддержка описанной подсистемы имеется на обоих уровнях — некоторые события, происходящие внутри устаревшего ПО, обрабатываются напрямую ядром, в то время как другим требуется некоторая помощь на уровне ring 3 (см. рис. 2). Благодаря тому что исполнение кода старого ПО изолировано в специальный процесс, ядро может легко определить, нуждается ли конкретное событие процессора в отдельной обработке, в зависимости от того, исходит оно от VDM-хоста или нет. В результате большинство процедур уровня ring 0 предоставляют дополнительные функциональные возможности при вызове их из особых процессов; в качестве одного из ярких примеров можно отметить обработчики системных прерываний (trap handlers) для x86 (такие как nt!KiTrap0c, nt!KiTrap0d, nt!KiTrap0e), системные вызовы NT (например, nt!NtVdmControl) и системные вызовы win32k.sys (например,nt!NtUserInitTask). Важно отметить, что, хотя процесс NTVDM.EXE и обрабатывается системой особым образом, он все равно наследует токен безопасности локального пользователя; это, в свою очередь, позволяет атакующему исполнять произвольный код в рамках процесса, используя всего лишь две документированные функции API — OpenProcess и CreateRemoteThread — для того, чтобы воспользоваться гипотетической уязвимостью в тех частях ядра, которые отвечают за поддержку VDM.
Рис. 2. Пример управления выполнением время исполнения устаревших 16-битных приложений в Microsoft Windows
Наконец, нельзя забывать, что NTVDM поддерживает основную часть спецификаций интерфейса защищенного режима DOS (DOS Protected Mode Interface — DPMI), то есть в дополнение к реализации режима Virtual 8086, он также может предоставлять среду исполнения (например, создавать сегменты памяти) и выполнять код защищенного режима. Следовательно, вполне может появиться код с поддержкой обработки 32-битных инструкций в ядре в дополнение к простой 16-битной эмуляции.
CVE-2013-3196 (write-what-where в nt!PushInt)
General Protection Fault
Одной из самых важных особенностей режима Virtual 8086, а также рабочей среды, созданной NTVDM.EXE для исполнения устаревшего 32-битного кода с поддержкой DPMI, состоит в том, что любая попытка выполнить критичную или требующую повышенных прав инструкцию (такую как INT, OUT или STI) сразу же приведет к исключению General Protection Fault в ядре. Как уже отмечалось выше, после этого операционная система должна безопасно эмулировать работу инструкции и вернуться к исполнению прерванного гостевого кода, обеспечивая продолжение исполнения. Как выяснилось, код эмулирования инструкций для 16- и 32-битных режимов эмуляции находится полностью в пространстве ядра, что открывает перед нами интересные возможности для атаки: программным путем воспроизвести поведение особых инструкций х86. Для того чтобы попасть в эмулятор, нужно выполнение следующих условий:
- Исключение #GP происходит внутри режима Virtual 8086 (флаг EFlags.VM установлен) ИЛИ Исключение #GP происходит в режиме пользователя (ring 3) и
- Селектор cs: segment не равен KGDT_R3_CODE (0x1b) в момент исключения и
- Исключение #GP происходит в хост-процессе VDM.
Рис. 3. Таблица диспетчеризации инструкций режима Virtual 8086, используемая обработчиком #GP
Если любой из вариантов полностью выполнен, то обработчик #GP передает управление внутренней процедуре nt!VdmDispatchOpcode_try , которая производит базовое декодирование вызвавшей сбой инструкции и вызывает одну или несколько функций-обработчиков, применимых к этой инструкции. Списки обработчиков для режимов эмуляции 16 и 32 бит показаны на рис. 3 и 4; как можно увидеть, ядро выдает очень длинный список инструкций и их префиксов. По нашему мнению, до этого года эта часть кода, скорее всего, никогда ранее не подвергалась проверке на наличие уязвимостей, что делало ее серьезной мишенью для исследования. После этого «открытия» мы решили провести реверс-инжиниринг всех обработчиков в поисках потенциальных недоработок и получили первые результаты уже в течение следующих нескольких часов. Первая уязвимость находилась в слое эмуляции инструкции INT для защищенного режима.
Рис. 4. Таблица диспетчеризации инструкций защищенного режима, используемая обработчиком #GP
Где собака зарыта
Базовая роль функции обработчика nt!OpcodeINTnn состоит в том, что она извлекает операнд imm8 инструкции, вызвавшей сбой, а дальше вызывает другую внутреннюю процедуру nt!PushInt. Ее основная задача заключается в том, чтобы получить базовый адрес пользовательского ss: сегмента и положить адрес обработчика системных прерываний в стек (в адресном пространстве пользователя), используя полный адрес указателя стека ss:esp. Полученный путем обратного инжиниринга С-код, ответственный за помещение в стек трех 16- или 32-битных слов (в зависимости от гостевого режима исполнения), приведен ниже.
Проблема в реализации состояла в том, что указатель на стек пользовательского пространства (ring 3) никак не проверяется на корректность, вероятно из-за предположения, что он всегда будет указывать на адресное пространство процесса NTVDM.EXE. А это, разумеется, не всегда так, поскольку эксплойт может устанавливать регистр esp на любой произвольный указатель, например на адрес, относящийся к ядру. Таким образом, для задействования уязвимости было достаточно выполнить всего лишь две простые инструкции в контексте виртуальной машины DOS: mov esp, 0xdeadbeef и затем int 0 . Единственные ограничения состояли в том, что и cs: , и ss: должны выбирать сегменты кода и данных в рамках локальной таблицы дескрипторов (LDT — Local Descriptor Table), а аргумент инструкции int должен быть прерыванием уровня ядра (любое значение в диапазоне между 0–255, за исключением последовательности 0x2a–0x2e). Результат запуска двух описанных инструкций на непропатченной Windows 7 SP1 приведен ниже:
Благодаря тому факту, что одна из 32-битных переменных хранится ядром в произвольно выбранном исключении eip, ситуация превращается в простое write-what-where условие с незначительными ограничениями, которыми можно пренебречь (например, что непосредственное значение не может иметь установленным старший бит). Имея в своем распоряжении такую удобную базовую возможность, становится возможным «угнать» управление выполнением (control flow) ядра, переписав один из указателей функций, например широко известный указатель nt!HalDispatchTable+4, вызываемый из пространства пользователя через системный вызов nt!NtQueryIntervalProfile.
Рис. 5. Успешная реализация write-what-where в nt!PushInt
Устранение данной уязвимости реализовано довольно просто и состоит из трех дополнительных инструкций, добавленных в nt!PushInt. Они проверяют, чтобы адрес ss:esp , который должен быть из пространства пользователя, действительно указывал на нижние части адресного пространства (см. рис. 6).
Рис 6. Бинарные различия между первоначальной реализацией nt!PushInt и после патча
CVE-2013-3197 (write-what-where в nt!PushException)
Если внимательно посмотреть на обработчики системных прерываний Windows (помимо nt!KiTrap0d ), то становится очевидным, что специфическую функциональность для VDM обеспечивает не только обработчик #GP, а большинство из них. В этом плане особенность General Protection Fault состоит в том, что она имеет выделенные подпрограммы для обработки конкретных типов исключений (таких как критичные или привилегированные инструкции); другие обработчики не используют такую сложную функциональность, а вместо этого просто вызывают функцию nt!Ki386VdmReflectException в случае, если встречаются с исключением VDM. Этим они пытаются эмулировать событие в виртуальной среде, примерно по той же схеме, что и эмуляция инструкций в nt!VdmDispatchOpcode_try . Граф передачи управления иллюстрирует, что большинство обработчиков зависят от этой функции (cм. рис. 7).
Рис. 7. Граф функции nt!Ki386VdmReflectException
Причина головной боли
При типичных обстоятельствах (то есть для любого обычного процесса) исполнение, как правило, завершается в одном из вариантов nt!CommonDispatchException, который отправляет событие к обработчику исключений пространства пользователя. В случае VDM ядро сначала пытается с помощью nt!PushException создать фрейм-ловушку в стеке пространства пользователя и перенаправить управление по адресу cs:eip, который берется из полей VfCsSelector и VfEip структуры NtCurrentTeb()->Vdm->VdmIntDescriptor[trap_no] (см. рис. 8); и только если эта процедура не срабатывает, исключение обрабатывается обычным способом. И, подобно предыдущему случаю, при создании эмулированного фрейма-ловушки ядро не проверяет, что указатель стека находится действительно в рамках адресного пространства пользователя. Это опять приводит к возможности использовать write-what-where условие, только размером 16 или 32 байта вместо 6 или 12. Задействовать уязвимость так же просто, для этого достаточно установить esp на произвольный адрес в пространстве ядра и вызвать исключение (например, #DE через инструкцию div edx) с нормальными реквизитами полностью инициализированной среды VDM и пользовательскими сегментами cs: и ss: в момент возникновения ошибки.
Рис. 8. Внутренние структуры пространства пользователя, которые задействуются для возобновления исполнения NTVDM, прерванного исключением
И в этот раз благодаря тому, что одно из записанных в контролируемый адрес значений — это eip ошибки, та же методика использования указателя функции (function pointer exploitation technique) может использоваться для получения полного контроля над компьютером. Правда, из-за ограничений на значение LDT воспользоваться этой уязвимостью можно только на системах начиная с Windows Vista. В обновлении безопасности Microsoft просто вставили два простых блока, которые отвечают за проверку указателя в стеке пространства пользователя для ветвей создания фрейма ловушки и для 16, и для 32 бит.
CVE-2013-3198 (write-what-where в nt!VdmCallStringIoHandlerPushException)
В дополнение к обработке привилегированных инструкций VDM ядро также эмулирует выполнение критичных инструкций, то есть таких инструкций, которые могут выполняться, только если CPL cs: и es: (причем базовый адрес последнего сегмента указывает на память ядра для перезаписи), инициализировать регистр di значением 0x0 и dx значением 0x3b0, а потом вызвать инструкцию insb; разумеется, все операции необходимо проводить внутри процесса NTVDM.EXE. Если мы установим базу сегмента es: в 0xaaaaaaaa и запустим эксплойт на непропатченной системе, то должно произойти следующее:
По умолчанию порт 0x3b0 записывает в память единственный байт — 0x00 , так что данная уязвимость может быть использована для обнуления любого указателя на функцию пространства ядра; сделав это, мы можем перенаправить выполнение кода ring 0 на страницу NULL, которая уже расположена в адресном пространстве NTVDM. Таким образом, мы и в этом случае можем повысить токен безопасности локального процесса или скомпрометировать безопасность системы любым другим удобным нам путем.
Для устранения этой проблемы Microsoft ввела inline-вызов ProbeForRead перед считыванием данных из пространства пользователя по адресу ds:si, а также общий вызов ProbeForWrite перед записью данных обратно по адресу es:di.
Мысли вслух
Все три уязвимости для повышения привилегий, о которых шла речь в этой статье, были возможны благодаря условию write-what-where, которое возникает в силу того, что предоставляемые пользователем данные не проходят никакой валидации. В других ситуациях уязвимости этого типа для базового образа ядра NT (ntoskrnl.exe) встречаются крайне редко. И хотя Microsoft за последние годы смогла внутренними силами отследить и устранить большинство таких проблем, они каким-то образом упустили код эмуляции ввода/вывода, исключений и инструкций в VDM; скорее всего, из-за того, что инструменты статического анализа, очень эффективные для высокоуровневого кода С и С++, в настоящее время не поддерживают ассемблер или плохо взаимодействуют с ним. Стоит отметить, что возможность использовать эти уязвимости появилась только после небольшого несвязанного изменения в коде входного контроля LDT, которое впервые появилось в Windows Vista. Из-за этого изменения внутренняя функция nt!PspIsDescriptorValid оказалась лишена проверок, связанных с базой и ограничениями ввода. Впрочем, это не более чем удачное совпадение. Реальной причиной, которая лежит в основе этой уязвимости, стали не различия в контроле сегментов, а тот факт, что код эмуляции использовал полные адреса ss:esp, ds:si и es:di в операциях памяти, хотя и одна из ключевых особенностей безопасности для ядра Windows гласит: привилегированный код никогда не должен доверять любым сегментам памяти со стороны пользователя.
Резюмируя
На примере этих трех открытий мы еще раз ясно видим, что многие уязвимости ядра обусловлены существованием кода, написанного чуть ли не в начале 90-х годов. Тогда безопасность не рассматривалась в качестве важного приоритета (в отличие от нашего времени), что приводило к созданию плохого кода, и никто его не пересматривал с точки зрения обеспечения безопасности с тех пор, как он был написан двадцать лет назад. При этом большие участки кода используются и в самых последних версиях Windows, включая новейшие Windows 8.1 и Server 2012. Современный исходный код ядра, который пишется в 2013 году, должен соответствовать руководствам по безопасной разработке и тщательно тестироваться перед выпуском. Поэтому мы считаем, что вместо того, чтобы копаться в новых функциональных элементах, которые были внедрены в последних версиях системы, гораздо эффективнее искать ошибки в тех ключевых компонентах, которые были созданы давным-давно.
Ну и последнее, что стоит отметить, — отключение по умолчанию обратной совместимости с приложениями DOS в Windows 8 было отличным решением Microsoft. Благодаря ему большинство еще не обнаруженных ошибок либо невозможно использовать, либо нет смысла искать, потому что атакующий не получит от их использования достаточных дивидендов. К тому же это решение позволило полностью отключить любые страницы NULL (раньше их наличия требовал хост-процесс VDM), а благодаря этому полностью исчезают либо значительно сокращаются ошибки типа NULL pointer dereference, которые часто встречаются и в ядре, и в драйверах устройств. По общему влиянию на будущие защитные свойства это одно из самых серьезных улучшений со стороны Microsoft за все время. Ну а сейчас вперед — найди свой собственный баг в ядре!
Автор: Mateusz «j00ru» Jurczyk.
Впервые опубликовано в журнале «Хакер» от 01/2014.