Paged pool что такое
Перейти к содержимому

Paged pool что такое

  • автор:

Невыгружаемый пул занимает память Windows 10 — решение

Невыгружаемый пул — утечка памяти в Windows 10

Одна из распространенных проблем пользователей Windows 10, особенно с сетевыми картами Killer Network (Ethernet и Wireless)— заполняющаяся оперативная память при работе в сети. Обратить на это внимание можно в диспетчере задач на вкладке «Производительность», выбрав RAM. При этом, заполняется невыгружаемый пул памяти.

Проблема в большинстве случаев вызвана неправильной работой сетевых драйверов в сочетании с драйверами монитора использования сети Windows 10 (Network Data Usage, NDU) и достаточно просто решается, о чем и пойдет речь в этой инструкции. В некоторых случаях, причиной утечек памяти могут быть и другие драйверы оборудования. Близкий по теме материал: Что такое память Кэшировано в Windows 10 и как очистить кэшированную память.

Исправление утечки памяти и заполнения невыгружаемого пула при работе в сети

Наиболее распространенной ситуацией является, когда невыгружаемый пул RAM Windows 10 заполняется при работе в Интернете. Например, легко заметить, как он растет при скачивании большого файла и после этого не очищается.

Если описанное — ваш случай, то исправить ситуацию и очистить невыгружаемый пул памяти можно следующим образом.

Исправление проблемы с невыгружаемым пулом в реестре Windows 10

  1. Зайдите в редактор реестра (нажмите клавиши Win+R на клавиатуре, введите regedit и нажмите Enter).
  2. Перейдите к разделу
  3. Дважды нажмите по параметру с именем «Start» в правой части редактора реестра и задайте значение 4 для него, для отключения монитора использования сети.
  4. Закройте редактор реестра.

По завершении, перезагрузите компьютер и проверьте, была ли исправлена проблема. Как правило, если дело действительно в драйверах сетевой карты, невыгружаемый пул больше не растет больше своих обычных значений.

Если шаги, описанные выше, не помогли, попробуйте следующее:

  • Если драйвер сетевой карты и (или) беспроводного адаптера был установлен с официального сайта производителя, попробуйте удалить его и дать Windows 10 установить стандартные драйверы.
  • Если драйвер был автоматически установлен Windows или был предустановлен производителем (и система после этого не менялась), попробуйте скачать и установить последнюю версию драйвера с официального сайта производителя ноутбука или материнской платы (если это ПК).

Заполняемый невыгружаемый пул оперативной памяти в Windows 10 не всегда бывает вызван драйверами именно сетевой карты (хотя чаще всего) и если действия с драйверами сетевых адаптеров и NDU не приносят результата, можно прибегнуть к следующим шагам:

  1. Установка всех оригинальных драйверов от производителя на ваше оборудование (особенно если на данный момент времени у вас установлены драйверы, автоматически установленные Windows 10).
  2. Использование утилиты Poolmon из состава Microsoft WDK для определения драйвера, вызывающего утечку памяти.

Как узнать, какой драйвер вызывает утечку памяти в Windows 10 с помощью Poolmon

Невыгружаемый пул в диспетчере задач Windows 10

Выяснить конкретные драйверы, приводящие к тому, что невыгружаемый пул памяти растет можно с помощью инструмента Poolmoon, входящим в состав Windows Driver Kit (WDK), скачать который можно с официального сайта Майкрософт.

  1. Загрузите WDK для вашей версии Windows 10 (не используйте шаги на предлагаемой странице, относящиеся к установке Windows SDK или Visual Studio, просто найдите пункт «Установите WDK для Windows 10» на странице и запустите установку) с сайта https://developer.microsoft.com/ru-ru/windows/hardware/windows-driver-kit.
  2. После установки, зайдите в папку с WDK и запустите утилиту Poolmon.exe (по умолчанию утилиты находятся в C:\ Program Files (x86)\Windows Kits\ 10\ Tools\ ).
  3. Нажмите латинскую клавишу P (так, чтобы второй столбец содержал только значения Nonp), затем — B (это оставит в списке только записи, использующие невыгружаемый пул и отсортирует их по количеству занимаемого пространства в памяти, т.е. по столбцу Bytes). Невыгружаемый пул в утилите Poolmon
  4. Обратите внимание на значение столбца Tag для занимающей наибольшее количество байт записи.
  5. Откройте командную строку и введите команду findstr /m /l /s значение_столбца_tag C:\Windows\System32\drivers\*.sys Поиск драйвера, вызывающего утечку памяти
  6. Вы получите список файлов драйверов, которые могут оказаться причиной проблемы.

Дальнейший путь — выяснить по именам файлов драйверов (с помощью Google, например), к какому оборудованию они относятся и пробовать установить, удалить или откатить в зависимости от ситуации.

Почему растет невыгружаемый пул памяти в Windows?

date31.01.2022
useritpro
directoryWindows 10, Windows Server 2016, Windows Server 2019
commentsкомментариев 10

На компьютерах и серверах Windows могут возникать проблемы с исчерпанием свободной памяти, вызванной утечкой некого системного драйвера, хранящего свои данные в невыгружаемом пуле памяти системы. Невыгружаемый пул памяти (Non-paged memory) – это данные в оперативной памяти компьютера, используемые ядром и драйверами операционной системой, которая никогда не выгружается на диск (в своп/ файл подкачки), т.е. всегда находится в физической RAM памяти.

Текущий размер невыгружаемого пула памяти можно увидеть в диспетчере задач Windows на вкладке Perfomance (Производительность) в разделе Memory (Память). На скриншоте ниже видно, что практически вся память на сервере занята, и большая часть ее относится к невыгружаемому пулу 4,2 Гб (Non-paged pool / Невыгружаемый пул). В нормальном состоянии размер невыгружаемого пула редко превышает 200-400 Мб. Большой размер невыгружаемого пула часто указывает на наличии утечки памяти в каком-то системном компоненте или драйвере.

Non-paged pool забил всю память компьютера

При утечке памяти в невыгружаемом пуле на сервере, в системном журнале событий появится события:

В подавляющем большинстве случаев причиной такой утечки памяти является проблема со сторонними драйверами, установленными в Windows. Как правило, это сетевые драйвера. Обратите внимание, как ведет себя пул при скачивании больших файлов (скорее всего он при этом быстро растет).

Максимальный размер невыгружаемого пула в Windows:

  • Windows x64 до 128 Гб и не более 75% физической памяти
  • Windows x86 до 2 Гб и не более 75% RAM

Для очистки пула помогает только перезагрузка, и, если для домашнего компьютера это еще может быть приемлемо, то на круглосуточно работающем сервере желательно найти нормальное решение.

Установка последних версий драйверов сетевых адаптеров

Попробуйте скачать и установить последние версии драйверов ваших сетевых адаптеров с сайта производителя.

Если у вас в Windows включено автоматическое обновление драйверов, убедитесь не начались ли проблемы после установки новых драйверов. Попробуйте откатить версию драйвера на более старую и проверить, воспроизводится ли проблема. Если проблема решилась, отключите авто обновление драйверов.

Отключение драйвера мониторинга сетевой активности Windows

Достаточно часто причиной утечки памяти в невыгружаемый пул является несовместимость драйвера мониторинга сетевой активности (Network Data Usage — NDU, %WinDir%\system32\drivers\Ndu.sys) с драйверами сетевого адаптера компьютера (чаще всего конфликтуют драйвера для сетевых карт Killer Network и MSI). Данный сервис можно отключить без особых потерь функционала Windows.

Службу можно остановить командной:

sc config NDU start= disabled

sc config NDU start= disabled

Либо через реестр:

  1. Откройте редактор реестра regedit.exe
  2. Перейдите в ветку HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Ndu\
  3. Измените значения параметра Start на 4.

отключение NDU - HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Ndu\

После внесения изменений нужно перезагрузить компьютер

Отключение роли Hyper-V

В некоторых случаях утечку памяти в невыгружаемый пул вызывает установленная роль Hyper-V. Если эта роль не нужна, рекомендуем отключить ее.

Remove-WindowsFeature -Name Hyper-V

Команда для Windows 10:

Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All

Поиск драйвера, вызвавшего утечку памяти с помощью Poolmon

Если описанные выше способы не помогли, можно попробовать определить драйвер, который вызвал утечку памяти в невыгружаемый пул.

Для этого нам понадобится консольная утилита Poolmoon.exe, входящая в комплект разработки Windows Driver Kit (WDK). Скачайте с сайта Microsoft и установите WDK для вашей версии Windows и запустите утилиту Poolmon.exe (в WDK для Windows 10 утилита находится в каталоге C:\Program Files (x86)\Windows Kits\10\Tools\ ).

После запуска утилиты Poolman.exe нажмите клавиши P. Во втором столбце останутся теги процессов, которые используют невыгружаемую память (атрибут Nonp) Затем нажмите клавишу B, чтобы выполнить сортировку по столбцу Bytes.

Poolmoon - спсико тегов в невыгружаемом пуле памяти

В левом столбце указаны теги драйверов. Ваша задача определить файл драйвера, использующего этот тег. В нашем примере видно, что больше всего RAM в невыгружаемом пуле используют драйвера с тегами Nr22, ConT и smNp.

Вы должны проверить драйвера на наличие найденных тегов с помощью утилиты strings.exe (от Sysinternals), с помощью встроенной команды findstr или с помощью PowerShell.

Следующие команды должны найти файлы драйверов, связанные с найденными вами тегами. данными процессами можно командами:

findstr /m /l /s Nr22 %Systemroot%\System32\drivers\*.sys
findstr /m /l /s ConT %Systemroot%\System32\drivers\*.sys
findstr /m /l /s smNp %Systemroot%\System32\drivers\*.sys

Также можно воспользоваться PowerShell:

Set-Location «C:\Windows\System32\drivers»
Select-String -Path *.sys -Pattern «Nr22» -CaseSensitive | Select-Object FileName -Unique
Select-String -Path *.sys -Pattern «Py28» -CaseSensitive | Select-Object FileName -Unique
Select-String -Path *.sys -Pattern «Ne40» -CaseSensitive | Select-Object FileName –Unique

poolmon показать имя драйвера использующего невыгружаемый пул

Обратите внимание, что имя драйвера теперь отображается в столбце Mapped_driver.

Если поиск не дал результатов, проверьте возможно утечка памяти вызвана не системным процессом. Запустите Task Manager, перейдите на вкладку Details, добавьте колонку NP Pool и найдите процессы с большим размером памяти в невыгружаемом пуле.

показывать размер невыгружаемого пула процессов в taskmanager Windows 10

Таким образом, мы получили список файлов драйверов, которые могут оказаться причиной проблемы. Теперь по именам файлов нужно определить, к каким драйверам и системным компонентам они относятся. Для этого можно воспользоваться утилитой sigcheck от Sysinternals.

sigcheck

Утилита возвращает имя драйвера, его свойства и информацию о версии.

Теперь можно попытаться удалить/обновить/переустановить проблемный драйвер или службу.

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

  1. Загрузите дамп памяти в отладчик Windbg;
  2. Выполните команду: !vm
  3. Если значение NonPagedPool Usage больше чем Max, это говорит о том, что невыгружаемый пул исчерпан;
  4. Проверьте содержимое пула командой (результаты будут отсортированы по использованию невыгружаемого пула): !poolused 2
  5. После получение тега драйвера найдите файл с помощью findstr или strings как описано выше.

Данная инструкция применима как для Windows Server 2019/2016/2012R2, так и для клиентских Windows 10, 8.1.

Предыдущая статьяПредыдущая статья Следующая статья Следующая статья

Paged pool что такое

Review these articles:

Santhosh Sivarajan | MCTS, MCSE (W2K3/W2K/NT4), MCSA (W2K3/W2K/MSG), CCNA, Network+| Houston, TX
Blogs — http://blogs.sivarajan.com/

FaceBook Twitter LinkedIn SS Tech Forum

This posting is provided AS IS with no warranties,and confers no rights.

Thanks for reply.

But the thing is this, I have arleady reviewed above mentioned link, Even then i am unable to understand the things.

Please let me know what exactly happened at the time of process execution.

Just to be Simple, The memory manager Component of Windows creates the following memory pools that the system uses to allocate memory: nonpaged pool and paged pool. Both memory pools are located in the region of the address space that is reserved for the system and mapped into the virtual address space of each process.

The nonpaged pool consists of virtual memory addresses that are guaranteed to reside in physical memory as long as the corresponding kernel objects are allocated.

The paged pool consists of virtual memory that can be paged in and out of the system. To improve performance, systems with a single processor have three paged pools, and multiprocessor systems have five paged pools.

The handles for kernel objects are stored in the paged pool, so the number of handles you can create is based on available memory.

Kernel Pool Overflow: от теории к практике

Ядро Windows всегда было лакомым кусочком для хакера, особенно при наличии законченных методик его эксплуатирования, приводящих к повышению прав. Учитывая тот факт, что за последние несколько лет количество уязвимостей, связанных с переполнением динамической памяти ядра, резко возросло, я активно заинтересовался данным направлением и, к собственному удивлению, в конечном итоге накопал столько материала, что его хватит не на один 0day-баг.

Наглядный ядерный шеллкод :)

Актуальность проблемы

Технология Memory Management является одной из самых важных в работе ядра. Уязвимости этого механизма, пожалуй, также самые страшные и, в то же время, актуальные. Они и являются основным стимулом для создания всяких разных видов защиты, таких как safe unlinking. В данной статье будут детально рассмотрены некоторые аспекты, как теоретические, так и практические, по эксплуатации динамического переполнения памяти ядра.

  • ms08-001 — IGMPv3 Kernel Pool Overflow – удаленное переполнение в tcpip.sys;
  • ms09-006 – уязвимость в обработке определенных записей wmf/emf, связанная с брешью в win32k.sys;
  • ms10-058 – integer overflow уязвимость, ведущая к переполнению пула в tcpip.sys.

Обзор распределения памяти ядром

Как в любой уважающей себя операционной системе, Windows (а точнее говоря, ее ядро) предоставляет некоторые функции для выделения/освобождения памяти. Виртуальная память состоит из блоков, называемых страницами. В архитектуре Intel x86 размер страницы составляет 4096 байт. Однако большинство запросов на выделение памяти меньше объема страницы. Поэтому функции ядра, такие как ExAllocatePoolWithTag и ExFreePoolWithTag, резервируют неиспользуемую память для последующего ее выделения. Внутренние функции напрямую взаимодействуют с железом каждый раз, когда страница задействована. Все эти процедуры достаточно сложны и деликатны, вот почему они реализованы именно в ядре.

Различия между Paged и NonPaged pool

Память ядра системы делится на два различных пула. Этот финт был придуман для выделения наиболее часто используемых блоков памяти. Система должна знать, какие страницы наиболее востребованы, а от каких можно временно отказаться (логично, правда?). Paged pool может быть сохранен в оперативной памяти или вытеснен в файловую систему (swap). NonPaged pool используется для важных задач, существует только в оперативной памяти и для каждого уровня IRQL.

Файл pagefile.sys содержит paged-память. В недалеком прошлом он уже становился жертвой атаки, в ходе которой неподписанный код внедрялся в ядро Vista. Среди обсуждаемых решений было предложено отключить paged-память. Джоанна Рутковска рекламировала такое решение как более безопасное по сравнению с другими, хотя следствием этого стала небольшая потеря физической памяти. Microsoft отказывается от прямого доступа к диску, что подтверждает важность таких возможностей ядра Windows, как Paged- и NonPaged-пулы. Эта статья написана с упором на NonPaged pool, так как обработка Paged-Pool происходит совершенно иначе. NonPaged pool можно рассматривать как более ли менее типичную реализацию heap. Подробная информация о системных пулах доступна в Microsoft Windows Internals.

Таблица NonPaged pool

Алгоритм выделения должен быстро распределять наиболее часто используемые объемы. Поэтому существуют три разные таблицы, каждая из которых выделяет память определенного диапазона. Такую структуру я обнаружил в большинстве алгоритмов управления памятью. Считывание блоков памяти с устройств занимает некоторое время, поэтому в алгоритмах Windows происходит балансировка между скоростью ответа и оптимальным выделением памяти. Время ответа сокращается, если блоки памяти сохраняются для последующего выделения. С другой стороны, избыточное резервирование памяти может сказаться на производительности.
Таблица представляет собой отдельный способ хранения блоков памяти. Мы рассмотрим каждую таблицу и ее местоположение.

NonPaged lookaside – таблица, назначаемая каждому процессору и работающая с объемами памяти, менее или равными 256 байт. У каждого процессора есть контрольный реестр (PCR), хранящий служебные данные процессора – уровень IRQL, GDT, IDT. Расширение реестра называется контрольным регионом (PCRB) и содержит lookaside-таблицы. Следующий дамп windbg представляет структуру такой таблицы:

Дампы структур в windbg

Дампы структур в windbg

Lookaside-таблицы предоставляют наиболее быстрое считывание блоков памяти по сравнению с другими типами. Для такой оптимизации очень важно время задержки, а односвязный список (который реализован в Lookaside) тут намного эффективнее, чем двухсвязный. Функция ExInterlockedPopEntrySList используется для выбора записи из списка с использованием аппаратной инструкции «lock». PPNPagedLookasideList и есть вышеупомянутая Lookaside-таблица. Она содержит два Lookaside-списка: P и L. Поле «depth» структуры GENERAL_LOOKASIDE определяет, как много записей может находиться в списке ListHead. Система регулярно обновляет этот параметр, используя различные счетчики. Алгоритм обновления основан на номере процессора и не одинаков для P и L. В списке P поле «depth» обновляется чаще, чем в списке L, потому что P оптимизирован под очень маленькие блоки.

Вторая таблица зависит от числа процессоров и того, как ими управляет система. Данный способ выделения памяти будет использоваться, если объем менее или равен 4080 байт, или если lookaside-поиск не дал результатов. Даже если целевая таблица меняется, у нее будет та же структура POOL_DESCRIPTOR. В случае единственного процессора используется переменная PoolVector для считывания указателя NonPagedPoolDescriptor. В случае многих процессоров, таблица ExpNonPagedPoolDescriptor содержит 16 слотов с описаниями пулов. PCRB каждого процессора указывает на структуру KNODE. Узел может быть связан с более чем одним процессором и содержит поле «color», используемое как список для ExpNonPagedPoolDescriptor. Следующие схемы иллюстрируют этот алгоритм:

Описание пула при одном процессоре

Описание пула при одном процессоре

Описание пула при нескольких процессора

Описание пула при нескольких процессорах

Ядро определяет глобальную переменную ExpNumberOfNonPagedPools, если данная таблица используется несколькими процессорами. Она должна содержать количество процессоров.

Следующий дамп windbg отображает структуру POOL_DESCRIPTOR:

Структура POOL_DESCRIPTOR

Структура POOL_DESCRIPTOR

В очереди spinlock’ов реализована синхронизация; часть библиотеки HAL используется для предотвращения конфликтов в дескрипторе пула (pool descriptor). Эта процедура позволяет только одному процессору и одной нити получать одновременный доступ к записи из дескриптора пула. Библиотека HAL различается на разных архитектурах. Для дескриптора пула по умолчанию главный NonPaged spinlock заблокирован (LockQueueNonPagedPoolLock). А если он не заблокирован, то для него создается отдельная очередь spinlock.

Третья, и последняя таблица используется процессорами для обработки памяти объемов свыше 4080 байт. MmNonPagedPoolFreeListHead также используется, если закончилась память в остальных таблицах. Доступ к этой таблице происходит при обращении к главной очереди NonPaged spinlock’ом, также называемой LockQueueNonPagedPoolLock.

В ходе освобождения меньшего по объему блока памяти ExFreePoolWithTag объединяет его с предыдущим и следующим свободными блоками. Так может быть создан блок размером в страницу и более. В этом случае блок добавляется в таблицу MmNonPagedPoolFreeListHead.

Алгоритмы выделения и освобождения памяти

Распределение памяти ядром в разных версиях ОС почти не меняется, но этот алгоритм не менее сложен, чем heap пользовательских процессов. В этой части статьи я хочу проиллюстрировать основы поведения таблиц в ходе процедур выделения и освобождения памяти. Многие детали, такие как механизмы синхронизации, будут намеренно опущены. Эти алгоритмы помогут в объяснении метода и понимании основ распределения памяти в ядре.

Алгоритм распределения в NonPaged pool (ExAllocatePoolWithTag):

Наглядный алгоритм выделения памяти

Наглядный алгоритм выделения памяти

Алгоритм высвобождения NonPaged pool (ExFreePoolWithTag):
Соответственно, алгоритм выделения памяти

Соответственно, алгоритм выделения памяти

От синего экрана смерти до исполнения желаний

При переполнении динамической памяти обычно затираются метаданные других выделенных блоков, что в основном ведет к нескольким BugCheck’ам (или попросту BSOD’ам):

BAD_POOL_HEADER: Вызывается в коде ExFreePoolWithTag, если PreviousSize следующего чанка не равен BlockSize текущего чанка.

BAD_POOL_HEADER (19)
The pool is already corrupt at the time of the current request. This may or may not be due to the caller. The internal pool links must be walked to figure out a possible cause of the problem, and then special pool applied to the suspect tags or the driver verifier to a suspect driver.
Arguments:
Arg1: 00000020, a pool block header size is corrupt.
Arg2: 812c1000, The pool entry we were looking for within the page. <—- освобождаемый чанк
Arg3: 812c1fc8, The next pool entry. <—- следующий чанк, заголовок которого мы затерли
Arg4: 0bf90000, (reserved)

DRIVER_CORRUPTED_EXPOOL: Вызывается в коде ExFreePoolWithTag, если при unlink’e произошло исключение Page Fault.

DRIVER_CORRUPTED_EXPOOL (c5)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is caused by drivers that have corrupted the system pool. Run the driver verifier against any new (or suspect) drivers, and if that doesn’t turn up the culprit, then use gflags to enable special pool.
Arguments:
Arg1: 43434343, memory referenced <—— наше фейковое значение Blink’a
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: 80544d06, address which referenced memory

BAD_POOL_CALLER: Вызывается в коде ExFreePoolWithTag, если чанк, который пытаются освободить, уже является освобожденным.

Рассмотрим подробнее заголовок (метаданные) чанка:

Значения PreviousSize, BlockSize вычисляются следующим образом:

Если значение PoolType равно нулю, то такой чанк является освобожденным, и после заголовка идет структура nt!_LIST_ENTRY.

kd> dt nt!_LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY

Эксплуатация

Алгоритм освобождения чанка работает таким образом, что если после освобождаемого чанка есть свободный, то происходит слияние, то есть из двух свободных чанков склеивается один. Это происходит путем нехитрой операции unlink’a.

Удаляем запись entry из двусвязного списка

PLIST_ENTRY b,f;
f=entry->Flink;
b=entry->Blink;
b->Flink=f;
f->Blink=b;

Это ведет к перезаписи 4 байт по контролируемому адресу:

Незатейливая схема алгоритма, который мы осуществили

Незатейливая схема алгоритма, который мы осуществили

Практикуемся!

Обладая достаточными знаниями, рассмотрим уязвимость в драйвере одного антивирусного продукта.

.text:00016330 mov cx, [eax]; eax указывает на данные под нашим контролем
.text:00016333 inc eax
.text:00016334 inc eax
.text:00016335 test cx, cx
.text:00016338 jnz short loc_16330
.text:0001633A sub eax, edx
.text:0001633C sar eax, 1
.text:0001633E lea eax, [eax+eax+50h] ; размер UNICODE строки + 0x50 байт
.text:00016342 movzx edi, ax ; Неправильное привидение типа, округление до WORD
.text:00016345
.text:00016345 loc_16345:;
.text:00016345 movzx eax, di
.text:00016348 push ebx
.text:00016349 xor ebx, ebx
.text:0001634B cmp eax, ebx
.text:0001634D jz short loc_16359
.text:0001634F push eax; Кол-во байт
.text:00016350 push ebx; Тип пула(NonPaged)
.text:00016351 call ds:ExAllocatePool ; В итоге мы контролируем размер выделяемого chunk’a
.text:00016357 mov ebx, eax
[..]
.text:000163A6 movzx esi, word ptr [edx]
.text:000163A9 mov [eax+edx], si ; Тут происходит запись за границы
.text:000163AD inc edx
.text:000163AE inc edx
.text:000163AF test si, si
[..]
.text:000163F5 push ebx; P
.text:000163F6 call sub_12A43
.text:00012A43 sub_12A43 proc near; CODE XREF: sub_12C9A+5Cp
.text:00012A43; sub_12C9A+79p .
.text:00012A43
.text:00012A43 P = dword ptr 4
.text:00012A43
.text:00012A43 cmp esp+P], 0
.text:00012A48 jz short locret_12A56
.text:00012A4A push 0; Tag
.text:00012A4C push [esp+4+P]; P
.text:00012A50 call ds:ExFreePoolWithTag ; Освобождение, write4 сценарий

C-подобный псевдокод

Как видно из кода, уязвимость связана с приведением целочисленных типов, которая ведет к тому, что размер для юникод-строки будет рассчитан неправильно. Все это приведет к переполнению, если передать драйверу буфер с юникод-строкой больше 0xffff байт.

Нехитрый код для воспроизведения BSoD

Эксплуатация данной уязвимости не так проста, как может показаться на первый взгляд. Здесь имеют место некоторые ограничения, а именно – переполнение (запись за границы чанка) огромное (больше 0xffff), что потенциально ведет к синему экрану еще до исполнения ExFreePoolWithTag (и, следовательно, к замене указателей при слиянии):

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except,
it must be protected by a Probe. Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: fe8aa000, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: f0def3a9, If non-zero, the instruction address which referenced the bad memory address.
Arg4: 00000000, (reserved)
eax=00029fa8 ebx=fe8a7008 ecx=00000008 edx=fe880058 esi=00004141 edi=fe87d094
eip=f0def3a9 esp=f0011b78 ebp=f0011bac iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010206
KmxSbx+0x63a9:
f0def3a9 66893410 mov word ptr [eax+edx],si ds:0023:fe8aa000=. <—- запись за границу, улетели в неспроецированную память

При перезаписи памяти мы можем переписать данные, которые являются указателями каких-либо ядерных структур, что может привести к самым неожиданным последствиям (очередному BSoD).

Для улучшения эффективности эксплуатации данной уязвимости воспользуемся следующим трюком: создадим N потоков, которые вызывают DeviceIoControl, с такими параметрами, чтобы с какой-то вероятностью N количество блоков определенной длины (0xff0 в данном примере) были выделены, затем освобождены – это дает нам шанс, что при переполнении мы не получим синий экран типа Page Fault (PAGE_FAULT_IN_NONPAGED_AREA). Предложенный пример кода с подробными комментариями ищи на нашем DVD.

Наглядный ядерный шеллкод :)

Наглядный ядерный шеллкод 🙂

Выводы

На прощание могу лишь сказать, что в интернете очень мало информации об эксплуатации Kernel Pool Overflow. Также огорчает, что в паблике нет рабочих эксплойтов, что создает некое заблуждение, что переполнение памяти в ядре очень сложно эксплуатировать, а если и возможно, то максимальный исход злодеяний – обычный BSoD.

В этой статье авторы попытались показать на реальном примере, что, подключив смекалку, можно улучшить стабильность методов эксплуатации подобных уязвимостей.
В дальнейших статьях мы поговорим о более сложных аспектах эксплуатации Kernel Pool Overflow, которые, конечно, существуют и ждут своего часа :). Stay tuned!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *