Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2020-1206 — Технический анализ уязвимости CVE-2020-1206 (SMBleed) — раскрытия информации в ядре Windows SMBv3, включая неаутентифицированный оракул утечки памяти и техники эксплуатации в сочетании с SMBGhost для удалённого выполнения кода (RCE). | Kitploit
Инструменты/GitHubGitHub/datntsec/cve-2020-1206
Криминалистика памятиАнализ уязвимостейЭксплуатацияСбор информацииТестирование на ПроникновениеЭксплуатация Бинарных Файлов
GitHubdatntsec/cve-2020-1206

CVE-2020-1206

Технический анализ уязвимости CVE-2020-1206 (SMBleed) — раскрытия информации в ядре Windows SMBv3, включая неаутентифицированный оракул утечки памяти и техники эксплуатации в сочетании с SMBGhost для удалённого выполнения кода (RCE).

Репозиторий
565 лет назадЕщё не проверено

Популярное

Смотреть все →

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

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

В уязвимости SMBGhost (CVE-2020-0796) я рассказывал о технике write-what-where primitive через использование целочисленного переполнения (integer overflow) для изменения указателя Alloc.Userbuffer таким образом, чтобы он указывал на нужный нам адрес, и записи туда произвольных данных. Подобно SMBGhost, эта уязвимость также присутствует в функции Srv2DecompressData в srv2.sys. Давайте ещё раз посмотрим на функцию Srv2DecompressData, связанную с уязвимостью SMBGhost (CVE-2020-0796), упрощённую Zecops.``` c typedef struct _COMPRESSION_TRANSFORM_HEADER { ULONG ProtocolId; ULONG OriginalCompressedSegmentSize; USHORT CompressionAlgorithm; USHORT Flags; ULONG Offset; } COMPRESSION_TRANSFORM_HEADER, *PCOMPRESSION_TRANSFORM_HEADER;

typedef struct _ALLOCATION_HEADER { // ... PVOID UserBuffer; // ... } ALLOCATION_HEADER, *PALLOCATION_HEADER;

NTSTATUS Srv2DecompressData(PCOMPRESSION_TRANSFORM_HEADER Header, SIZE_T TotalSize) { PALLOCATION_HEADER Alloc = SrvNetAllocateBuffer( (ULONG)(Header->OriginalCompressedSegmentSize + Header->Offset), NULL); If (!Alloc) { return STATUS_INSUFFICIENT_RESOURCES; }

ULONG FinalCompressedSize = 0;


NTSTATUS Status = SmbCompressionDecompress(
    Header->CompressionAlgorithm,
    (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER) + Header->Offset,
    (ULONG)(TotalSize - sizeof(COMPRESSION_TRANSFORM_HEADER) - Header->Offset),
    (PUCHAR)Alloc->UserBuffer + Header->Offset,
    Header->OriginalCompressedSegmentSize,
    &FinalCompressedSize);
if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) {
    SrvNetFreeBuffer(Alloc);
    return STATUS_BAD_DATA;
}


if (Header->Offset > 0) {
    memcpy(
        Alloc->UserBuffer,
        (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER),
        Header->Offset);
}


Srv2ReplaceReceiveBuffer(some_session_handle, Alloc);
return STATUS_SUCCESS;

}

Функция Srv2DecompressData принимает сжатое сообщение, отправленное клиентом, и выделяет необходимую область памяти, распаковывая в неё сообщение. Затем, если поле Offset не равно нулю, она копирует данные (RawData), расположенные перед сжатыми данными, в начало выделенной области памяти.

![](https://assets.kitploit.com/production/public/readmes/24502/a5bf8b5059336fb3677162343bace0d0b45085f2eb89e42d85f81e032fe233dc.png)

Ошибка SMBGhost заключается в том, что функция не проверяет целочисленное переполнение, что приводит к выделению неправильного размера и вызывает переполнение буфера. Через 3 месяца после того, как Microsoft исправила SMBGhost, была найдена уязвимость CVE-2020-1206 (SMBleed, как её называет [Zecops Blog](https://blog.zecops.com/)). Эта уязвимость позволяет нам утечь адрес другой машины, а в сочетании с SMBGhost даёт возможность получить RCE. Чтобы получить более простое представление о функции Srv2DecompressData, мы будем использовать эту функцию в том виде, в котором она была до исправления SMBGhost, и предположим, что она уже исправлена.

# Подделка OriginalCompressedSegmentSize
Как и в случае с SMBGhost, в этот раз мы также подделаем OriginalCompressedSegmentSize, задав значение немного большее, чем распакованные данные, которые мы отправляем. Например, мы сжимаем данные размером x байт; вместо того чтобы указывать в поле OriginalCompressedSegmentSize значение x, мы укажем x + 0x1000 — см. рисунок ниже:

![](https://assets.kitploit.com/production/public/readmes/24502/687d3bdc67e4b2f5bb3cecbe41ea52be98a5c904a8688b325a69acb0a854ca75.png)

Неинициализированные данные ядра будут считаться частью сообщения.

Как я говорил в анализе [CVE-2020-0796](https://github.com/datntsec/CVE-2020-0796), Srv2DecompressData всё равно пропустит этап проверки после функции SmbCompressionDecompress, если распаковка прошла успешно:``` c
if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) {
    SrvNetFreeBuffer(Alloc);
    return STATUS_BAD_DATA;
}

Хотя поле OriginalCompressedSegmentSize установлено в x + 0x1000 вместо x, после успешной распаковки переменная FinalCompressedSize содержит не значение x, а значение x + 0x1000:```c NTSTATUS SmbCompressionDecompress( USHORT CompressionAlgorithm, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, PULONG FinalCompressedSize) { // ...

NTSTATUS Status = RtlDecompressBufferEx2(
    ...,
    FinalUncompressedSize,
    ...);
if (status >= 0) {
    *FinalCompressedSize = CompressedBufferSize;
}

// ...

return Status;

}

Поскольку после успешной распаковки FinalCompressedSize обновляется, чтобы содержать значение CompressedBufferSize (соответствующее OriginalCompressedSegmentSize, переданному в функцию SmbCompressionDecompress). Последующее обновление и проверка практически не нужны и могут привести к некоторым непредвиденным ошибкам.


# Базовая эксплуатация
Структура сообщения, которую Zecops использует для демонстрации уязвимости, — это [сообщение SMB2 WRITE](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e7046961-3318-4350-be2a-a8d69bb59ce8). Эта структура содержит такие поля, как количество записываемых байтов, флаги и т. д., за которыми следует буфер произвольной длины. Это довольно удобно для эксплуатации, поскольку можно создать сообщение и указать заголовок с буфером, содержащим неинициализированные данные.

Основываясь на POC от [Zecops](https://blog.zecops.com/) в репозитории Microsoft WindowsProtocolTestSuites, чтобы лучше понять это, мы добавим небольшое дополнение к функции сжатия:``` c
// HACK: fake size
if (((Smb2SinglePacket)packet).Header.Command == Smb2Command.WRITE)
{
    ((Smb2WriteRequestPacket)packet).PayLoad.Length += 0x1000;
    compressedPacket.Header.OriginalCompressedSegmentSize += 0x1000;
}

Обратите внимание, что этот POC требует учетных данных и разрешения на запись, которые часто доступны во многих случаях. Однако возвращаемая ошибка будет одинаковой для любого сообщения (включая сообщения как с учетными данными, так и без них), поэтому, возможно, нам удастся провести эксплуатацию без аутентификации. Ещё одно замечание: память, которую мы будем утекать, происходит из предыдущих выделений в NonPagedPoolNx, и поскольку мы можем контролировать размер выделения, мы будем в некоторой степени контролировать данные, которые утечём.

Исходный код POC SMBleed

Итак, можно ли без учетных данных утечь адрес ядра? Чтобы ответить на этот вопрос, давайте проанализируем SMB глубже.

Углубляемся в SMB

При аутентификации клиент отправляет следующие сообщения:

SMB2 NEGOTIATE → SMB2 SESSION_SETUP → SMB2 SESSION_SETUP

Если учетные данные неверны, сессия разрывается после второго пакета SMB2 SESSION_SETUP:

Предположим, что у нас нет учетных данных; проверим, есть ли команда, которую можно отправить без аутентификации. В ходе поиска мы замечаем:

  • Первой командой, которую необходимо отправить, является SMB2 NEGOTIATE, и это также единственная команда SMB2 NEGOTIATE за всю сессию.
  • Последующие команды, до успешной аутентификации, должны быть SMB2 SESSION_SETUP.

При этом сообщение SMB2 NEGOTIATE не сжимается. Ошибка находится в функции декомпрессии, поэтому мы не будем его рассматривать, а изучим только сообщения SMB2 SESSION_SETUP.

Скачать инструмент