Переполнение буфера в Microsoft Internet Explorer


Оглавление (нажмите, чтобы открыть):

Новые критические уязвимости в MS Office и Internet Explorer

Несмотря на все усилия Microsoft по повышению безопасности программного обеспечения, в ее продуктах продолжают обнаруживаться серьезные уязвимости. Не успела Microsoft среагировать на обнаружение дыры в ActiveX-модуле File Transfer Manager, как вынуждена была снова латать слабые места в системе безопасности своих продуктов.

На этот раз дыры обнаружились не в редком программном компоненте, вроде уже упомянутого File Transfer Manager, а в самых популярных продуктах компании: MS Office и Internet Explorer. Опасность новых уязвимых мест специалисты Microsoft оценивают как критическую.

В MS Office были обнаружены сразу три уязвимости, все из которых находятся в модуле Office Web Components (OWC), ответственном за интеграцию офисных программ Microsoft с интернетом. Наиболее серьезная уязвимость связана с имеющейся в OWC функцией Host. Прислав пользователю особым образом скомпонованное письмо в формате HTML или заманив его на специальную веб-страницу, хакер может использовать эту функцию для захвата полного контроля над компьютером.

Две другие уязвимости связаны с методами загрузки текста и работы с буфером обмена, реализованными в Office Web Components. Используя некоторые их особенности, злоумышленник может просматривать содержимое файлов и буфера обмена на компьютере жертвы.

По данным Microsoft, эти дыры имеются в следующих программных продуктах компании: MS Office 2000 и Office XP, а также в BackOffice Server 2000, BizTalk Server 2000 и 2002, Commerce Server 2000 и Commerce Server 2002, Internet Security and Acceleration Server 2000, Money 2002 и 2003, Project 2002, Project Server 2002 и Small Business Server 2000. Компания уже выпустила соответствующую заплатку. Она подходит для всех вышеуказанных продуктов, кроме Project и Project Server. Пользователям Office XP рекомендуется вместо универсального патча установить недавно выпущенный Service Pack 2. Более подробную информацию о дырах можно найти в соответствующем бюллетене Microsoft.

Кроме этого, 22 августа Microsoft выпустила кумулятивный патч для браузера Internet Explorer версий 5, 5.5 и 6. Он исправляет сразу шесть уязвимостей, включая дыру в реализации протокола gopher, ошибку переполнения буфера в модуле ActiveX, ответственном за форматирование текста, возможность чтения XML-файлов через функцию перенаправления (redirect) и другие.НТВ

Уязвимости Internet Explorer

Несмотря на наличие на рынке альтернативных решений (например, Opera и FireFox), одним из основных браузеров до сих пор остается Internet Explorer. Как следствие, его уязвимости представляют угрозу для очень большого числа пользователей, а потому весьма активно эксплуатируются разработчиками вредоносных программ.

Статистика

мире существует ряд компаний, которые занимаются регистрацией фактов обнаружения уязвимостей в различных продуктах с последующей статистической обработкой и публикацией результатов. Для определенности будем опираться на данные, опубликованные на сайте Secunia (http://secunia.com) на основании анализа уязвимостей Internet Explorer за период 2003-2005 годов (рис. 1-3). Как видно из диаграммы (см. рис. 1), почти ежемесячно в Internet Explorer находят новую уязвимость, причем в среднем в месяц обнаруживается около двух новых уязвимостей.

Рис. 1. Количество обнаруженных уязвимостей в IE версий 6.x и 5.x

Если же посмотреть на статистику степени опасности обнаруженных уязвимостей, то за указанный период получается картина, представленная на рис. 2. Следует отметить, что 29% не представляющих опасность уязвимостей относится к таким, практическая ценность которых, с точки зрения злоумышленника, близка к нулю.

Рис. 2. Статистика уязвимостей IE версии 6.x
по степени опасности

Еще более интересная для пользователя статистика — по устранению обнаруженных уязвимостей (см. рис. 3). На данный момент не устранено 28% известных уязвимостей, причем для ряда этих уязвимостей существуют эксплоиты. Кроме того, важным показателем является время между обнаружением уязвимости, появлением реализующего уязвимость эксплоита, созданием эксплуатирующих уязвимость вредоносных программ и выходом обновления, устраняющего уязвимость.

Рис. 3. Статистика устранения уязвимостей
IE версии 6.x

Основные виды уязвимостей

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

Уязвимости, позволяющие злоумышленнику получить доступ к системе

Чаще всего данная уязвимость сводится к выполнению машинного кода, созданного злоумышленником. Наиболее распространенной разновидностью из данной категории является переполнение буфера, которое приводит к срыву стека и к выполнению программного кода, сформированного атакующим. Кроме того, по статистике автора, нередки уязвимости, основанные на некорректной обработке CHM-файлов через протоколы ms-its (ms-itss, its, mk:@MSITStore) — данная методика часто применяется для внедрения на компьютер пользователей троянских программ и SpyWare-компонентов.

Уязвимости, приводящие к созданию DoS

Под DoS в данном случае подразумевается любой сбой в работе Internet Explorer, начиная от его аварийного завершения и зависания и заканчивая значительными расходами ресурсов и снижением производительности системы в целом. Самая типичная реализация — переполнение буфера (только в случае DoS достаточно простого срыва стека), вредоносные скрипты. Простейшей демонстрацией DoS может служить HTML-файл вида:

Переполнение буфера в Microsoft Internet Explorer

Ребят. ну не могу я выложить работающий эксплоит публично. Это не дырка в BMP’шке.. с такимже успехом туда можно потом будет что угодно вставить. вирус например. Данный эксплоит ловит пока только DrWeb да и то частный случай. Надеюсь меня понять можно. скриншот покажу.
http://ix0des.nm.ru/demo1.jpg

2 mg@ ну не нравится тебе формулировка ‘удаленный’ читай как локальный или вообще просто пользователь.

2 mg@, уважаемый. почему вы такой упрямый ?
Вы английский плохо знаете ?

Microsoft Word/Outlook Object Tag Security Setting Compromise Vulnerability
Microsoft Outlook when configured to employ Microsoft Word as an email editor, is reported prone to a security setting compromise vulnerability. It is reported that under certain circumstances, when an HTML email is received and said email message contains an OBJECT tag that is not closed, the URI that the OBJECT tag points to will be rendered in the Microsoft Outlook window when the email message is forwarded

Microsoft Internet Explorer Shell: IFrame Cross-Zone Scripting Vulnerability
It has been alleged that Microsoft Internet Explorer is prone to a weakness that may potentially allow for the execution of hostile script code in the context of the My Computer Zone. This issue is related to how shell: URIs are handled by the browser. It should also be noted that shell: URIs may be used to reference local content in the same manner as file:// URIs.

Update: Although unconfirmed, further reports indicate that MSN messenger version 6.2.0137, Microsoft Word, Outlook 2003, and Outlook Express may also potentially provide exploitation vectors for this vulnerability.

Тема: Internet Explorer — интернет браузер

Опции темы
Отображение
  • Линейный вид
  • Комбинированный вид
  • Древовидный вид

Internet Explorer — интернет браузер

Повреждение памяти в реализации установления COM объектов в Microsoft Internet Explorer

Программа:
Internet Explorer 5.01 Service Pack 4
Internet Explorer 5.5 Service Pack 2
Internet Explorer 6

Наличие эксплоита: Нет

Описание:
Уязвимость позволяет удаленному пользователю выполнить произвольный код на целевой системе.

Уязвимость обнаружена в библиотеке MDT2DD.DLL при инициализации COM объектов, которые не предполагались быть инициализированными в Internet Explorer. Удаленный пользователь может с помощью специально сформированной Web страницы повредить память и выполнить произвольный код на целевой системе с привилегиями текущего пользователя.

Решение: Установите исправление с сайта производителя.

Internet Explorer 5.01 Service Pack 4 on Microsoft Windows 2000 Service Pack 4:
http://www.microsoft.com/downloads/details.aspx. 3C7B06C3A30A

Internet Explorer 6 Service Pack 1 on Microsoft Windows 2000 Service Pack 4 or on Microsoft Windows XP Service Pack 1:
http://www.microsoft.com/downloads/details.aspx. 1D1E3DC9732F

Internet Explorer 6 for Microsoft Windows Server 2003 and Microsoft Windows Server 2003 Service Pack 1:
http://www.microsoft.com/downloads/details.aspx. 60E01F3B3A59

Internet Explorer 6 for Microsoft Windows Server 2003 for Itanium-based Systems and Microsoft Windows Server 2003 with SP1 for Itanium-based Systems:
http://www.microsoft.com/downloads/details.aspx. 73A4D48E001A

Internet Explorer 6 for Microsoft Windows Server 2003 x64 Edition:
http://www.microsoft.com/downloads/details.aspx. 216C0260ACA3

Критические дыры в Windows Media Player и Internet Explorer

Компания eEye Digital Security, специализирующаяся на вопросах сетевой безопасности, сообщает об обнаружении новых уязвимостей в программном обеспечении Microsoft. На этот раз дыры найдены в медиаплеере Windows Media Player и браузере Internet Explorer.

По информации eEye, проблема проявляется на операционных системах Windows XP (в том числе со вторым сервис-паком), Windows NT, Windows 2003 (в том числе с первым сервис-паком) и всех версиях Windows 2000 при использовании медиаплеера и IE с настройками по умолчанию. Злоумышленник теоретически может получить полный доступ к удаленному компьютеру и выполнить на нем произвольный программный код с привилегиями текущего пользователя. Для реализации атаки нужно вынудить жертву открыть сформированный специальным образом файл или посетить вредоносную веб-страницу в интернете. Более подробная информация об уязвимостях, получивших рейтинг критических, из соображений безопасности не разглашается.

Корпорация Microsoft уже поставлена в известность о проблеме и занимается ее изучением, отмечает CNET News. При этом представители Microsoft подчеркивают, что случаев практического использования дыр на сегодняшний день зафиксировано не было. Кстати, в браузере Internet Explorer, по данным датской компании Secunia, остаются открытыми, по крайней мере, еще двадцать уязвимостей, многие из которых позволяют выполнять вредоносный код на ПК вез ведома его владельца.

Отказ в обслуживании в Microsoft Internet Explorer c установленным J2SE

Программа: Microsoft Internet Explorer 6.0

Наличие эксплоита: Да

Описание: Уязвимость позволяет удаленному пользователю вызвать отказ в обслуживании браузера.

Уязвимость обнаружена в библиотеке mshtmled.dll в Microsoft Internet Explorer с установленным J2SE Runtime Environment. Удаленны пользователь может с помощью специально сформированной web страницы вызвать отказ в обслуживании браузера.

Решение: Способов устранения уязвимости не существует в настоящее время.

Подмена строки состояния в Microsoft Internet Explorer

Программа: Microsoft Internet Explorer 6.0

Наличие эксплоита: Да

Описание: Уязвимость позволяет удаленному пользователю подменить строку состояния браузера.

Уязвимость существует при отображении URL в строке состояния браузера. Удаленный пользователь может изменить строке состояния и заставить пользователя обманом посетить злонамеренный сайта. Пример:

Возникает ошибка(переполнение буфера команд компьютера-клиента)

Сведения о вопросе

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

Это помогло устранить вашу проблему?

К сожалению, это не помогло.

Великолепно! Спасибо, что пометили это как ответ.

Насколько Вы удовлетворены этим ответом?

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

Копирование и вставка проблемы при использовании Yammer в Internet Explorer

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

Если при попытке вставить из буфера обмена в Yammer, при использовании Yammer в Internet Explorer, а не вставить содержимое, необходимо настроить в Internet Explorer. Последние обновления для изменения позволяет гибче отправка содержимого требуется доступ к буферу обмена программный Чтобы вставить содержимое в Yammer. Если доступ к буферу обмена программный отключено, копирования и вставки не работает.

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

Если у вас как конечным пользователем access параметры безопасности Internet Explorer, можно изменить настройки зоны участвует в Yammer.

Если ваш ИТ-отдел создал групповой политики, запрещает пользователям доступ к собственные параметры безопасности Internet Explorer, необходимо задавать ваш ИТ-отдел за помощью. Типичная решение — для ИТ-администраторов изменение групповой политики для перемещения yammer.com в список надежных сайтов и убедитесь, что доступ к буферу обмена программный включена в этой зоны.

Если у вас есть доступ в настройках системы безопасности Internet Explorer, вот как можно изменить параметры, чтобы вставить в Yammer works.

В Internet Explorer, перейдите на страницу Параметры > Свойства обозревателя, а затем откройте вкладку Безопасность.

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

Прокрутите вниз до раздела сценарии, в нижней части списка.

В разделе Разрешить программный доступ к буферу обмена установите флажок Включить.

Эксплуатация уязвимостей исполняемых файлов для новичков: переполнение буфера стека

В этой статье будет рассмотрена атака переполнения буфера стека, с подробным описанием того, что это такое, как это работает и какие технологии используются для её реализации. Статья написана так, чтобы тему смог понять мог даже неподготовленный читатель.

Теория: память приложений

При выполнении приложения загружаются в память. Но как мы все знаем, компьютеры имеют ограниченное количество памяти, и приложению нужно быть очень осторожным, чтобы не перезаписать область в памяти, принадлежащую другому приложению. Для того, чтобы избежать такой ситуации, используется так называемая виртуальная память, которую можно прекрасно описать с помощью сцены из сериала, выпущенного в начале 2000-х — Дрейк и Джош, в котором главные герои раскладывают суши по контейнерам:

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

Прим. перев. Посмотреть серию можно здесь, сцена с суши на 18 минуте.

Давайте перейдём от аналогии к концепции виртуальной памяти.

Конвейер с суши: как уже говорилось ранее, компьютеры имеют ограниченную память и должны быть очень осторожны и точны при записи данных, чтобы не перезаписать память других приложений. Хоть компьютер и может просто записать приложение в физическую память, в конечном итоге это приведёт к проблемам, так как фрагменты приложений быстро заполнят всю свободную память. В примере выше индивидуальные сушинки можно рассматривать как фрагменты приложения или часть памяти, занятой определённым приложением, а набор суши из шести штук — само приложение.

Дрейк и Джош: чтобы обойти проблему с заполнением конвейера одиночными сушинками, главные герои разбирают их по разным контейнерам, которые потом отправляют дальше по конвейеру. Ваш компьютер, как Дрейк и Джош, распределяет приложения по контейнерам, называемым виртуальным адресным пространством. Такие виртуальные адресные пространства позволяют приложению считать, что оно имеет полный контроль над всей памятью устройства. Однако когда приложение пытается получить доступ к памяти вне своего виртуального адресного пространства, маленькая, но чрезвычайно важная часть вашего ЦПУ — блок управления памятью — перенаправляет обращение к физической памяти в соответствии с выделенной областью для этого приложения, облегчая таким образом любую работу с памятью. Такое распределение позволяет компьютеру организовать работу сразу нескольких приложений через справочную таблицу с требованиями в виде динамической памяти.

ASCII-диаграмма работы виртуальной памяти

Также важно знать, что код всех приложений содержится внутри их виртуального адресного пространства. Приложения часто используют динамически подключаемые библиотеки (DLL), такие как libc или kernel32. DLL — внешние (т. е. не хранятся в исполняемом файле запускаемого приложения) системные или специально написанные библиотеки, которыми пользуется приложение. Пример представлен ниже.

Как вы видите, нигде в этой шестистрочной программе не объявляется printf() . Однако эта программа всё равно запустится без ошибок и выведет «Hello World». Это потому, что функция printf() — системная функция, определённая в libc, стандартной библиотеке C. Во время компиляции libc внешне подключается к исполняемому файлу. В системах Linux можно посмотреть используемые программой библиотеки с помощью команды ldd.

Отображение используемых программой библиотек с помощью ldd

Если вы смотрите на скриншот выше и думаете, что такое 0xb7e99000, то это адрес библиотеки libc в памяти. Адреса в памяти представлены в шестнадцатеричном формате. Более подробно о шестнадцатеричном формате вы можете узнать здесь.

Теория: стек

Стек — это просто большая структура данных, которая используется для хранения приложением информации или данных во время её работы. Работу стека можно описать следующей аналогией:

Боб — мойщик посуды в модном ресторане. Каждый вечер у Боба есть стопка тарелок, которые нужно вымыть. Более того, в течение ночи на верх стопки могут добавляться ещё тарелки, по мере уборки столов. Если Боб возьмёт тарелку откуда-то ещё кроме как сверху стопки, то вся стопка развалится и тарелки разобьются.


А теперь вместо Боба и стопки тарелок представьте компьютер и стопку объектов с данными. Когда что-то добавляется (push) в стек, оно кладётся наверх стопки. Когда извлекается (pull), то берётся сверху стопки. Так работает механизм LIFO (Last In First Out, последним пришёл — первым вышел).

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

Теория: вызов функций и возвраты

Посмотрите на код, представленный ниже:

В этом фрагменте кода мы видим что функция add() принимает два аргумента целочисленного типа, имена которых А и В . В функции main() мы вызываем функцию add() с 1 в качестве аргумента А и 2 — В . Если перевести это в машинный код:

Как вы видите, при вызове функции с параметрами программа сначала добавляет оба параметра в стек, а затем выполняет команду call . Команда call перенаправляет указатель инструкции программы по адресу вызываемой функции. Указатель программы подобен маленькому карандашу, который вы используете для отслеживания слов при чтении. Указатель инструкции всегда указывает на ту инструкцию, которая должна быть выполнена (слово, которое будет прочитано). Однако, перед тем, как перейти к вызываемой функции, команда call помещает адрес следующей за ним инструкции в стек, чтобы, когда произойдёт возврат из функции add() , было известно, с чего продолжать выполнение программы. Адрес места, в которое функция должна вернуться, называется указателем возврата функции.

Атака: переполнение буфера стека

Прежде чем углубляться в технические подробности о том, что такое переполнение стекового буфера и как оно работает, давайте рассмотрим простую для понимания аналогию:

Алиса и Боб раньше встречались, но в итоге Алиса рассталась с Бобом. Время шло, Алиса оставила прошлое позади, но Бобу так и не удалось справиться с горем. Теперь Алиса выходит замуж за Роберта Хакермана, заклятого врага Боба. Боб, будучи жутким чудаком, следил за всеми свадебными планами Алисы благодаря своему секретному доступу к электронной почте Алисы. Боб увидел, что Алиса наняла известного дизайнера свадебных тортов, который хотел, чтобы Алиса отредактировала части своего рецепта под свои вкусовые предпочтения. Дизайнер дал Алисе рекомендованный список ингредиентов, которые можно добавить, но сказал, что сделает всё в точности, как она захочет. Боб открыл документ, прикреплённый к электронному письму дизайнера, и увидел, что меняемые строки рецепта выглядят так:

… Затем мы наделим глазурь вкусом, добавив _____. После этого мы добавим немного шоколада …

Боб заметил, что если ввести «банан» в строку, текст будет выглядеть так:

Мастер Йода рекомендует:  Хитрости с битовыми операциями

… Затем мы наделим глазурь вкусом, добавив банан. После этого мы добавим немного шоколада …

Но если Боб введёт «клубника» в строку, текст будет выглядеть так:

… Затем мы наделим глазурь вкусом, добавив клубникуосле этого мы добавим немного шоколада …

Боб понял, что это будет идеальный способ испортить свадьбу Алисы, и всё, что ему нужно было сделать, это переписать остальную часть рецепта своей собственной отвратительной версией! В день свадьбы Алисы дизайнер наконец-то показал торт, который он сделал — он был покрыт жуками и сделан из замороженного майонеза!

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

12–13 ноября в 10:00, Санкт-Петербург, 3490–15 900 ₽

Переполнение буфера

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

Впервые данная уязвимость была использована в 1988 году – на ней основывались атаки червем Морриса. С тех пор количество подобных атак увеличивается с каждым годом. В настоящее время можно утверждать, что уязвимости, связанные с переполнением буфера, являются доминирующими при удаленных атаках, где обычный пользователь Сети получает частичный или полный контроль над атакуемым. Приблизительно половина вредоносных программ использует этот тип уязвимости.

В материале «Википедии» (http://ru.wikipedia.org) дано следующее определение данной уязвимости: «Переполнение буфера – это явление, возникающее, когда компьютерная программа записывает данные за пределами выделенного в памяти буфера».

В «Новом словаре хакера» Эрика С. Рэймонда сказано, что «переполнение буфера – это то, что с неизбежностью происходит при попытке засунуть в буфер больше, чем тот может переварить».

Представьте следующую ситуацию. Функция изменения пароля может воспринять пароль длиной не более 256 символов. Чаще всего никто не пользуется паролями длиннее 8–10 символов, поэтому разработчики не предусмотрели проверку строки ввода данных. При попытке ввести более 256 символов, если за данными находился адрес возврата функции, он будет перезаписан и в лучшем случае выполнение программы завершится с ошибкой. Хакеру, обнаружившему такой уязвимый участок, остается подставить в качестве адреса возврата правильный адрес, что переведет управление в любую точку программы на его выбор. В результате может быть выполнен любой произвольный код, который хакер поместил в указанную область памяти, с привилегиями, с которыми выполняется текущая программа.

Подобные ошибки в программном обеспечении находят чуть ли не ежедневно, но не всегда и не сразу устраняют. Для примера можно просмотреть статистику на специализированных сайтах. Согласно данным Secunia (http://secunia.com) в Microsoft Windows XP Professional не устранено 30 из 201 уязвимостей, обнаруженных с 2003 по начало 2008 года, хотя имеющих статус highly critical (предельно опасный), которые позволяют удаленно выполнить код (то есть фактически получить доступ к системе), в этом списке уже нет. В среднем обнаруживается три-четыре уязвимости в месяц.

В Internet Explorer 7 не устранено 7 из 21 найденной уязвимости, и некоторые из них имеют статус highly critical. В среднем в месяц обнаруживается одна-две уязвимости. Если учесть все уязвимости, при которых можно удаленно выполнить код в системе, можно сделать вывод, что с этим браузером вообще опасно выходить в Интернет. Internet Explorer позволяет выполнение кода при обработке HTML Help ActiveX, файлов HTA, SWF, ZIP, BMP и JPEG, архивов FTP, Cookies, тега IFRAME и всплывающих окон, то есть для проникновения в систему троянца достаточно зайти на сайт и просмотреть/сохранить рисунки или архив ZIP.

Внимание!

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

В операционной системе Windows код Internet Explorer используют и многие другие приложения (почтовый клиент Outlook Express, Проигрыватель Windows Media и др.), отчего увеличивается вероятность поражения. Например, существует JPEG-эксплоит, который использует ошибку в системной библиотеке, возникающую при обработке графических JPEG-файлов. Эта ошибка позволяет заразить компьютер через любую программу – Outlook Еxpress или любой другой почтовый клиент, показывающий JPEG-картинки.

Следует также обратить внимание на возможность вывода в адресной строке Internet Explorer адреса, не соответствующего адресу загруженного сайта (такой вид атаки называется URL-спуфинг), и отображение всплывающих окон, которые, как думает пользователь, принадлежат просматриваемой в браузере странице, а также модификация заголовка окна или информации в строке состояния.

По данным различных источников, именно Internet Explorer сегодня является самым популярным веб-браузером, так как он интегрирован в Windows. Поэтому данная программа будет привлекать внимание злоумышленников, желающих реализовать свои замыслы, ведь вероятность того, что пользователь придет на специально созданный ресурс именно с Internet Explorer, остается самой высокой.

Давайте посмотрим, что на сегодня можно сказать о самом известном из бесплатных браузеров – Mozilla Firefox 2. В нем обнаружено 19 уязвимостей, из которых не устранено четыре. Самая опасная из них имеет статус less critical (ниже критического). Использовав эти уязвимости, получить полное управление компьютером невозможно, злоумышленник может лишь раскрыть некоторую системную информацию, поэтому следует признать, что положение этого браузера лучше, чем Internet Explorer.

Таким образом, оптимальным решением будет использование альтернативных приложений. Вместо Internet Explorer для серфинга можно применять, например, Mozilla Firefox, вместо Outlook Еxpress – The Bat! и т. д. У этих программ ситуация с безопасностью лучше.

Следует также периодически устанавливать обновления и использовать новые версии программ, в которых устранены старые ошибки (возможные новые ошибки – это уже другой вопрос). Правда, размер обновлений подчас до стигает нескольких десятков мегабайт и кроме Internet Explorer и Windows необходимо обновлять другие продукты, следовательно, трафик может быть накладным для бюджета. В таком случае следует ограничиться хотя бы обновлениями, устраняющими критические ошибки.

Наверняка вы задаетесь вопросом: неужели за столько лет никто не пытался бороться с переполнением буфера? Конечно же, пытались. Ведь разработка атакующих программ за несколько десятилетий переросла чистый энтузиазм и приняла коммерческую основу, что говорит о нарастающей опасности.

На борьбу с данной уязвимостью направлены такие утилиты, как, например, Stack-Guard. Первоначально она была разработана для Unix-систем, но в настоящее время ее аналог используется в Microsoft Visual Studio.NET и ProPolice компании IBM. В продуктах компании Microsoft, Windows XP SP2 и Server 2003 SP1 используется технология DEP (Data Execution Protection – защита от выполнения данных), которая делает секцию данных и стек неисполняемыми, что должно предотвращать подобный тип атак.

В некоторых процессорах Intel и AMD имеется специальный бит: в Intel – XD (eXecute Disable – запрет выполнения), в AMD – NX (No eXecute – нет выполнения), позволяющий аппаратно реализовать поддержку DEP.

При отсутствии поддержки на компьютере неисполняемых страниц на аппаратном уровне используется Software-enforced DEP (принудительный программный DEP). Программная защита DEP встраивается во время компиляции и поэтому работает только для пересобранных с поддержкой DEP системных библиотек и приложений.

В этих средствах можно обнаружить и недостатки. При использовании технологии DEP встал вопрос совместимости. Некоторым приложениям требуется исполняемый стек (а таких много: эмуляторы, компиляторы, защитные механизмы и пр.), поэтому по умолчанию защита включена только для системных процессов. Появление новой технологии подстегнуло хакеров, и практически одновременно были представлены методы, позволяющие обойти защиту. Атаковать стало сложнее, но все равно возможно.

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

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

Как устроены дыры в безопасности: переполнение буфера

Прим. переводчика: Это перевод статьи Питера Брайта (Peter Bright) «How security flaws work: The buffer overflow» о том, как работает переполнение буфера и как развивались уязвимости и методы защиты.

Беря своё начало с Червя Морриса (Morris Worm) 1988 года, эта проблема поразила всех, и Linux, и Windows.

Переполнение буфера (buffer overflow) давно известно в области компьютерной безопасности. Даже первый само-распространяющийся Интернет-червь — Червь Морриса 1988 года — использовал переполнение буфера в Unix-демоне finger для распространения между машинами. Двадцать семь лет спустя, переполнение буфера остаётся источником проблем. Разработчики Windows изменили свой подход к безопасности после двух основанных на переполнении буфера эксплойтов в начале двухтысячных. А обнаруженное в мае сего года переполнение буфера в Linux драйвере (потенциально) подставляет под удар миллионы домашних и SMB маршрутизаторов.

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

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

Чтобы понять, почему происходит переполнение буфера — и почему результаты столь плачевны — нам нужно рассмотреть то, как программы используют память, и как программисты пишут код.

(Примечание автора: мы рассмотрим, в первую очередь, переполнение стекового буфера (stack buffer overflow). Это не единственный вид переполнения, но оно является классическим и наиболее изученным видом)

Стекируем

Переполнение буфера создаёт проблемы только в нативном коде — т.е. в таких программах, которые используют набор инструкций процессора напрямую, без посредников вроде Java или Python. Переполнения связаны с тем как процессор и программы в нативном коде управляют памятью. Различные операционные системы имеют свои особенности, но все современные распространённые платформы следуют общим правилам. Чтобы понять, как работают атаки, и какие бывают способы противодействия, сначала немного рассмотрим использование памяти.

Важнейшей концепцией является адрес в памяти. Каждый отдельный байт памяти имеет соответствующий числовой адрес. Когда процессор читает или записывает данные в основную память (ОЗУ, RAM), он использует адрес памяти того места, откуда происходит считывание или куда производится запись. Системная память используется не только для данных; она также используется для размещения исполняемого кода, из которого состоит программа. Это означает, что каждая из функций запущенной программы также имеет адрес.

Изначально, процессоры и операционные системы использовали адреса физической памяти: каждый адрес памяти напрямую соотносился с адресом конкретного куска RAM. Хотя, некоторые части современных операционных систем всё ещё используют физические адреса, все современные операционные системы используют схему, именуемую виртуальной памятью.

При использовании виртуальной памяти, прямое соответствие между адресом памяти и физическим участком RAM отсутствует. Вместо этого, программы и процессор оперируют в виртуальном пространстве адресов. Операционная система и процессор совместно поддерживают соответствие (mapping) между адресами виртуальной и физической памяти.

Такая виртуализация позволяет использовать несколько важных функций. Первая и важнейшая — это защищённая память. Каждый отдельный процесс получает свой собственный набор адресов. Для 32-битного процесса, адреса начинаются с нуля (первый байт) и идут до 4,294,967,295 (в шестнадцатеричном виде, 0xffff’ffff; 2^32 — 1). Для 64-битного процесса, адреса продолжаются до 18,446,744,073,709,551,615 (0xffff’ffff’ffff’ffff, 2^64 — 1). Таким образом, у каждого процесса есть свой собственный адрес 0, за ним свой адрес 1, свой адрес 2 и так далее.

(Примечание автора: Далее в статье я буду говорить о 32-битный системах, если не указано иное. В данном аспекте разница между 32-битными и 64-битными несущественна; для ясности я буду придерживаться единой битности)

Поскольку каждый процесс получает свой собственный набор адресов, эта схема является простым способом предотвратить повреждение памяти одного процесса другим: все адреса к которым процесс может обращаться принадлежат только ему. Это гораздо проще и для самого процесса; адреса физической памяти, хотя они в широком смысле работают также (это просто номера, начинающиеся с нуля), имеют особенности, которые делают их несколько неудобными в использовании. Например, они обычно не-непрерывные; например, адрес 0x1ff8’0000 используется для памяти режима системного управления процессора — небольшой кусок памяти, недоступный обычным программам. Память PCIe-карт также находится в этом пространстве. С адресами виртуальной памяти таких неудобств нет.

Что же находится в адресном пространстве процесса? Говоря в общем, существуют четыре распространённых объекта, три из которых представляют для нас интерес. Неинтересный для нас блок, в большинстве операционных систем, — «ядро операционной системы». В интересах производительности, адресное пространство обычно разделяют на две половины, нижняя из которых используется программой, а верхняя занимается адресным пространством ядра. Половина, отданная ядру, недоступна из половины занятой программой, однако само ядро может читать память программы. Это является одним из способов передачи данных в функции ядра.

В первую очередь разберёмся с исполняемой частью и библиотеками, составляющими программу. Главный исполняемый файл (main executable) и все его библиотеки загружаются в адресное пространство процесса, и все составляющие их функции, таким образом, имеют адрес в памяти.

Вторая часть используемой программой памяти используется для хранения обрабатываемых данных и обычно называется кучей (heap). Эта область, например, используется для хранения редактируемого документа, или просматриваемой веб-страницы (со всеми её объектами JavaScrit, CSS и т.п.), или карты игры, в которую играют.

Третья и важнейшая часть — стек вызовов, обычно называемый просто стеком. Это самый сложный аспект. Каждый поток в процессе имеет свой стек. Это область памяти, используемая для одновременного отслеживания как текущей функции исполняемой в потоке, так и всех предшествующих функций — тех, что были вызваны, чтобы попасть в текущую функцию. Например, если функция a вызывает функцию b, а функция b вызывает функцию c, то стек будет содержать информацию об a, b и c, в таком порядке.

Стек вызовов является специализированной версией структуры данных, называемой «стеком». Стеки являются структурами переменной длины, предназначенными для хранения объектов. Новые объекты могут быть добавлены (pushed) в конец стека (обычно называемого «вершиной» стека) и объекты могут быть сняты (popped) со стека. Только вершина стека подлежит изменению с использованием push и pop, таким образом, стек устанавливает строгий порядок сортировки: объект, который последним положили в стек, будет тем, который будет снят с него следующим.

Важнейшим объектом, хранимым в стеке вызовов, является адрес возврата (return address). В большинстве случаев, когда программа вызывает функцию, эта функция выполняет то, что должна (включая вызов других функций), а затем возвращает управление в функцию, которая её вызвала. Для возврата к вызывающей функции необходимо сохранить запись о ней: исполнение должно продолжиться с инструкции следующей после инструкции вызова. Адрес этой инструкции называется адресом возврата. Стек используется для хранения этих адресов возврата: при каждом вызове функции, в стек помещается адрес возврата. При каждом возврате, адрес снимается со стека и процессор начинает выполнять инструкцию по этому адресу.

Стековая функциональность является настолько базовой и необходимой, что большинство, если не все процессоры имеют встроенную поддержку этих концепций. Возьмём за пример процессоры x86. Среди регистров (небольших участков памяти в процессоре, доступных инструкциям), определённых в спецификации x86, два наиболее важных — eip (указатель инструкции — instruction pointer), и esp (указатель стека — stack pointer).

ESP всегда содержит адрес вершины стека. Каждый раз когда что-то добавляется в стек, значение esp уменьшается. Каждый раз, когда что-то снимается со стека, значение esp увеличивается. Это означает, что стек растёт «вниз»; по мере добавления объектов в стек, адрес хранимый в esp становится всё меньше и меньше. Несмотря на это, область памяти, на которую указывает esp, называется «вершиной стека.

Здесь мы видим простую развёртку стека с 64-символьным буфером с именем name, за ним указатель вложенного кадра (frame pointer), потом адрес возврата. В регистре esp содержится адрес вершины, в ebp — адрес указателя кадра.

EIP содержит адрес текущей инструкции. Процессор поддерживает значение eip самостоятельно. Он читает поток инструкций из памяти и изменяет значение eip соответственно, так что он всегда содержит адрес инструкции. В рамках x86 существует инструкция для вызова функций, call, а также инструкция для возврата — ret.

CALL принимает один операнд, адрес вызываемой функции (хотя есть несколько способов передать его). Когда выполняется call, указатель стека esp уменьшается на 4 байта (32 бита), и адрес инструкции следующей за call — адрес возврата — помещается в область памяти, на которую теперь указывает esp. Другими словами, адрес возврата помещается в стек. Затем, значением eip устанавливается равным адресу, переданному в качестве операнда call, и выполнение продолжается с этой точки.

RET производит обратную операцию. Простой ret не принимает операндов. Процессор сначала считывает значение по адресу памяти, хранимому в esp, потом увеличивает esp на 4 байт — снимает адрес возврата со стека. Значение помещается в eip, и выполнение продолжается с этого адреса.

(Примечание переводчика: в этом месте в авторском тексте приводится видео с демонстрацией call и ret.)

Если бы стек вызовов хранил только набор адресов возврата, проблемы бы не было. Реальная проблема приходит со всем остальным, что кладут в стек. Так выходит, что стек — это быстрое и эффективное место хранения данных. Хранение данных в куче относительно сложно: программа должна отслеживать доступное в куче место, сколько занимает каждый из объектов и прочее. При этом работа со стеком проста: чтобы разместить немного данных, достаточно просто уменьшить значение указателя. А чтобы почистить за собой, достаточно увеличить значение указателя.

Это удобство делает стек логичным местом для размещения переменных, используемых функцией. Функции нужно 256 байт буфера, чтобы принять ввод пользователя? Легко, просто отнимите 256 от указателя стека — и буфер готов. В конце функции, просто прибавьте 256 к указателю, и буфер отброшен.

Однако, у такого подхода существуют ограничения. Стек не подходит для хранения очень больших объектов: общий объём доступной памяти обычно фиксирован при создании потока и, часто, составляет примерно 1МБ в объёме. Поэтому большие объекты должны быть помещены в кучу. Стек также не применим для объектов, которые должны существовать дольше, чем выполняется одна вызванная функция. Поскольку все размещения в стеке удаляются при выходе из функции, время жизни любого из объектов в стеке не превышает времени выполнения соответствующей функции. На объекты в куче это ограничение не распространяется, они могут существовать „вечно“.

Когда мы используем программу корректно, ввод с клавиатуры сохраняется в буфере name, закрываемым нулевым (null, zero) байтом. Указатель кадра и адрес возврата не изменяются.

Стековое хранилище используется не только для явно определяемых программистом переменных; стек также используется для хранения любых значений, нужных программе. Особенно остро это проявляется в x86. Процессоры на базе x86 не отличаются большим числом регистров (всего существует 8 целочисленных регистров, и некоторые из них, как уже упомянутые eip и esp, уже заняты), поэтому функции редко имеют возможность хранить все необходимые им значения в регистрах. Чтобы освободить место в регистрах, и при этом сохранить значение для последующего использования, компилятор поместит значение регистра в стек. Значение позднее может быть снято с регистра и помещено обратно в регистр. В жаргоне компиляторов, процесс сохранения регистров с возможностью последующего использования называется spilling.

Мастер Йода рекомендует:  Создание красивого контент-слайдера Javascript

Наконец, стек часто используют для передачи аргументов функциям. Вызывающая функция помещает каждый из аргументов по очереди в стек; вызываемая функция может снять их из стека. Это не единственный способ передачи аргументов — можно использовать и регистры, например, — но это один из наиболее гибких.

Набор объектов хранимых функцией в стеке — её собственные переменные, сохранённые регистры, любые аргументы, подготавливаемые для передачи в другие функции — называются „вложенным кадром“. Поскольку данные во вложенном кадре активно используются, полезно иметь способ простой адресации к нему.

Это возможно реализовать, используя указатель стека, но это несколько неудобно: указатель стека всегда указывает на вершину, и его значение меняется по мере помещения и снятия объектов. Например, переменная может сначала быть расположена на позиции esp+4. После того, как ещё два значения положили в стек, и переменная стала располагаться по адресу esp+12. Если снять со стека одно из значений, переменная окажется на esp+8.

Описанное не является неподъёмной задачей, и компиляторы способны с ней справиться. Однако это делает использование указателя стека для доступа к чему-либо кроме вершины „стрёмным“, особенно при написании на ассемблере вручную.

Для упрощения задачи, обычным делом является ведение второго указателя, который хранит адрес „дна“ (т.е. начала) каждого кадра — значение, известное как указатель вложенного кадра (frame pointer). И на x86 даже есть регистр, который для этого обычно используют, ebp. Поскольку его значение неизменно в пределах функции, появляется способ однозначно адресовать переменные функции: значение, лежащее по адресу ebp-4, будет оставаться доступно по ebp-4 всё время жизни функции. И это полезно не только для людей — дебаггерам проще разобраться, что происходит.

Скриншот из Visual Studio демонстрирует всё это в действии на примере простой программы для x86. На процессорах x86, регистр esp содержит адрес вершины стека, в данном случае 0x0019fee0 (выделено синим). (Примечание автора: на платформе x86, стек растёт вниз, в направлении адреса памяти 0, однако эта точка всё равно сохраняет название „вершина стека“). Показанная функция хранит в стеке только переменную name, выделенную розовым цветом. Это фиксированный буфер длиной 64 байта. Поскольку это единственная переменная, её адрес тоже 0x0019fee0, такой же, как у вершины стека.

В x86 также есть регистр ebp, выделенный красным, который (обычно) выделен для хранения указателя кадра. Указатель кадра размещается сразу за переменными стека. Сразу за указателем кадра лежит адрес возврата, выделенный зелёным. Адрес возврата ссылается на фрагмент кода по адресу 0x00401048. Эта инструкция следует сразу за вызовом (call), демонстрируя то, как адрес возврата используется для продолжения исполнения там, где программа покинула вызывающую функцию.

NAME в приведённой иллюстрации относится как раз к тому роду буферов, которые регулярно переполняются. Его размер зафиксирован и составляет 64 байта. В данном случае, он заполнен набором чисел и завершается нулём. Из иллюстрации видно, что если в буфер name будет записано более 64 байт, то другие значения в стеке будут повреждены. Если записать на четыре байта больше, указатель кадра будет уничтожен. Если записать на восемь байт больше, то и указатель кадра, и адрес возврата будут перезаписаны.

Очевидно, что это ведёт к повреждению данных программы, но проблема с переполнением буфера куда серьёзнее: они ведут к выполнению [произвольного] кода. Это происходит потому, что переполненный буфер не просто перезапишет данные. Также могут оказаться перезаписаны более важные вещи, хранимые в стеке — адреса возврата. Адрес возврата контролирует то, какие инструкции процессор будет выполнять, когда закончит с текущей функцией; предполагается, что это будет какой-то адрес внутри вызывающей функции, но если это значение будет переписано переполнением буфера, оно может указывать куда угодно. Если атакующие могут контролировать переполнение буфера, то они могут контролировать и адрес возврата. Если они контролируют адрес возврата, они могут указать процессору, что делать дальше.

У процессора, скорее всего, нет красивой удобной функции „скомпрометировать машину“, которую бы запустил атакующий, но это не слишком важно. Тот же буфер, который используется для изменения адреса возврата, можно использовать для хранения небольшого куска исполнимого кода (shellcode, шеллкод), который, в свою очередь, скачает вредоносный исполнимый файл, или откроет сетевое соединение, или исполнит любые другие пожелания атакующего.

Традиционно, сделать это было тривиально просто, по причине, которая у многих вызывает удивление: обычно, каждая программа будет использовать одни и те же адреса в памяти при каждом запуске, даже если вы перезагружали машину. Это означает, что позиция буфера в стеке всякий раз будет одинакова, а значит и значение, используемое для искажения адреса возврата, каждый раз будет одинаково. Атакующему достаточно лишь выяснить этот адрес однажды, и атака сработает на любом компьютере, исполняющем уязвимый код.

Инструментарий атакующего

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

В других случаях, атакующий должен идти на хитрости. В функциях, обрабатывающих человеко-читаемый текст, байт с нулевым значением (null) часто имеет специальное значение; такой байт обозначает конец строки, и функции используемые для манипуляции строками — копирование, сравнение, совмещение — останавливаются. когда встречают этот символ. Это означает, что если шеллкод содержит ноль, эти процедуры его сломают.

(Примечание переводчика: в этом месте в авторском тексте приводится видео с демонстрацией переполнения. В нём, в буфер помещают шеллкод и переписывают адрес возврата. Шеллкод запускает стандартный калькулятор Windows.)

Чтобы это обойти, атакующий может использовать различные приёмы. Небольшие фрагменты кода для конвертирования шеллкода с нулями в эквивалентную последовательность, избегающую проблемный байт. Так возможно пролезть даже через очень строгие ограничения; например, уязвимая функция принимает на вход только данные, которые можно набрать со стандартной клавиатуры.

Собственно адрес стека часто содержит нули, и здесь есть сходная проблема: это означает, что адрес возврата нельзя записать адрес из стекового буфера. Иногда это не страшно, потому что некоторые из функций, используемых для заполнения (и, потенциально, переполнения) буферов сами пишут нули. Проявляя некоторую осторожность, их можно использовать, чтобы поместить нулевой байт точно в нужное место, устанавливая в адресе возврата адрес стека.

Но даже когда это невозможно, ситуация обходится окольными путями (indirection). Собственно программа со всеми своими библиотеками держит в памяти огромное количество исполнимого кода. Большая часть этого кода будет иметь „безопасный“ адрес, т.е. не будет иметь нулей в адресе.

Тогда, атакующему нужно найти подходящий адрес, содержащий инструкцию вроде call esp (x86), которая использует значение указателя стека в качестве адреса функции и начинает её исполнение, чем идеально подходит для шеллкода спрятанного в стековом буфере. Атакующий использует адрес инструкции call esp для записи в качестве адреса возврата; процессор сделает лишний прыжок через этот адрес, но всё равно попадёт на шеллкод. Этот приём с прыжком через другой адрес называется „трамплином“.

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

Это работает потому, повторюсь, что программа и её библиотеки при каждом запуске размещаются в одни и те же области памяти — даже между перезагрузками и даже на разных машинах. Одним из интересных моментов в этом деле является то, что библиотеке, от которой выполняется трамплин, самой даже не нужно использовать оператор call esp. Достаточно, чтобы в ней были два подходящих байта (в данном случае, со значениями 0xffи 0xd4) идущие друг-за-другом. Они могут быть частью какой-то иной функции, или даже просто числом; x86 не привередлива к таким вещам. Инструкции x86 могут быть очень длинными (до 15 байт!) и могут располагаться по любому адресу. Если процессор начнёт читать инструкцию с середины — со второго байта четырёхбайтной инструкции, к примеру — результат будет интерпретирован как совсем иная, но всё же валидная, инструкция. Это обстоятельство делает нахождение полезных трамплинов достаточно простым.

Иногда, однако, атака не может установить адрес возврата в точности куда требуется. Несмотря на то, что расположение объектов в памяти крайне схоже, оно может слегка отличаться от машины к машине или от запуска к запуску. Например, точное расположение подверженного атаке буфера может варьироваться вверх и вниз на несколько байт, в зависимости от имени системы или её IP-адреса, или потому, что минорное обновление программы внесло незначительное изменение. Чтобы справится с этим, полезно иметь возможность указать адрес возврата который примерно верен, но высокая точность не нужна.

Это легко делается с использованием приёма, называемого „посадочной полосой“ (NOP sled, букв. „сани из NOPов“ (спасибо Halt за корректный русскоязычный термин — прим.пер.)). Вместо того, чтобы писать шеллкод сразу в буфер, атакующий пишет большое число инструкций NOP (означающих „no-op“, т.е. отсутствие операции — говорит процессору ничего не делать), иногда сотни, перед настоящим шеллкодом. Для запуска шеллкода, атакующему нужно установить адрес возврата на позицию где-то посреди этих NOPов. И если мы попали в область NOPов, процессор быстро обработает их и приступит к настоящему шеллкоду.

Иногда сложно переписать адрес возврата адресом из буфера. В качестве решения, мы можем переписать адрес возврата адресом части исполнимого кода в программе-жертве (или её библиотеках). И этот фрагмент уже передаст управление в буфер.

Во всём нужно винить C

Главный баг, который позволяет всё это сделать — записать в буфер больше, чем доступно места — выглядит как что-то, что легко избежать. Это преувеличение (хоть и небольшое) возлагать всю ответственность на язык программирования C, или его более или менее совместимых отпрысков, конкретно C++ и Objective C. Язык C стар, широко используем, и необходим для наших операционных систем и программ. Его дизайн отвратителен, и хотя всех этих багов можно избежать, C делает всё, чтобы подловить неосторожных.

В качестве примера враждебности C к безопасной разработке, взглянем на функцию gets(). Эта функция принимает один параметр — буфер — и считывает строку данных со стандартного ввода (что, обычно, означает „клавиатуру“), и помещает её в буфер. Наблюдательный читатель заметит, что функция gets() не включает параметр размера буфера, и как забавный факт дизайна C, отсутствует способ для функции gets() определить размер буфера самостоятельно. Это потому, что для gets() это просто не важно: функция будет читать из стандартного ввода, пока человек за клавиатурой не нажмёт клавишу Ввод; потом функция попытается запихнуть всё это в буфер, даже если этот человек ввёл много больше, чем помещается в буфер.

Это функция, которую в буквальном смысле нельзя использовать безопасно. Поскольку нет способа ограничить количество набираемого с клавиатуры текста, нет и способа предотвратить переполнение буфера функцией gets(). Создатели стандарта языка C быстро поняли проблему; версия спецификации C от 1999 года выводила gets() из обращения, а обновление от 2011 года полностью убирает её. Но её существование — и периодическое использование — показывают, какого рода ловушки готовит C своим пользователям.


Червь Морриса, первый само-распространяющийся зловред который расползся по раннему Интернету за пару дней в 1988, эксплуатировал эту функцию. Программа fingerd в BSD 4.3 слушает сетевой порт 79, порт finger. Finger является древней программой для Unix и соответствующим сетевым протоколом, используемым для выяснения того, кто из пользователей вошёл в удалённую систему. Есть два варианта использования: удалённую систему можно опросить и узнать всех пользователей, осуществивших вход, или можно сделать запрос о конкретном юзернейме, и программа вернёт некоторую информацию о пользователе.

К сожалению, gets() довольно глупая функция. Достаточно зажать клавишу А на клавиатуре, и она не остановится после заполнения буфера name. Она продолжит писать данные в память, перезаписывая указатель кадра, адрес возврата и всё остальное, до чего сможет дотянуться.

Каждый раз при сетевом подключении к демону finger, он начинал чтение с сети — используя gets() — в стековый буфер длиной 512 байт. При нормальной работе, fingerd затем запускал программу finger, передавая ей имя пользователя (если оно было). Программа finger выполняла реальную работу по перечислению пользователей или предоставлению информации о конкретном пользователе. Fingerd просто отвечала за сетевое соединение и запуск finger.

Учитывая, что единственный „реальный“ параметр это необязательное имя пользователя, 512 байт является достаточно большим буфером. Скорее всего ни у кого нет имени пользователя и близко такой длины. Однако, нигде в системе это ограничение не было жёстким по причине использования ужасной функции gets(). Пошлите больше 512 байт по сети и fingerd переполнит буфер. И именно это сделал Роберт Моррис (Robert Morris): его эксплоит отправлял в fingerd 537 байт (536 байт данных и перевод строки, заставлявший gets() прекратить чтение), переполняя буфер и переписывая адрес возврата. Адрес возврата был установлен просто в области стекового буфера.

Исполнимая нагрузка червя Моррис была простой. Она начиналась с 400 инструкций NOP, на случай если раскладка стека будет слегка отличаться, затем короткий участок кода. Этот код вызывал шелл, /bin/sh. Это типичный вариант атакующей нагрузки; программа fingerd запускалась под рутом, поэтому, когда при атаке она запускала шелл, шелл тоже запускался под рутом. Fingerd была подключена к сети, принимая „клавиатурный ввод“ и аналогично отправляя вывод обратно в сеть. И то и другое наследовал шелл вызванный эксплойтом, и это означало, что рутовый шелл теперь был доступен атакующему удалённо.

Несмотря на то, что использования gets() легко избежать — даже во время распространения червя Морриса была доступна версия fingerd не использовавшая gets() — прочие компоненты C сложнее игнорировать, и они не менее подвержены ошибкам. Типичной причиной проблем является обработка строк в C. Поведение, описанное ранее — останов на нулевых байтах — восходит к поведению строк в C. В языке C, строка представляет собой последовательность символов, завершаемую нулевым байтом. В C существует набор функций для работы со строками. Возможно, лучшим примером являются strcpy(), копирующая строку из одного места в другое, и strcat(), вставляющая исходную строку следом за точкой назначения. Ни одна из этих функций не имеет параметра размера буфера назначения. Обе с радостью будут бесконечно читать из источника, пока не встретят NULL, заполняя буфер назначения и беззаботно переполняя его.

Даже если строковая функция в C имеет параметр размера буфера, она реализует это способом, ведущим к ошибкам и переполнениям. В языке C есть пара функций родственных strcat() и strcpy(), называемых strncat() и strncpy(). Буква n в именах этих функций означает что они, в некотором роде, принимают размер в качестве параметра. Однако n, хотя многие наивные программисты думают иначе, не является размером буфера в который происходит запись — это число символов для считывания из источника. Если в источнике символы закончились (т.е. достигнут нулевой байт), то strncpy() и strncat() заполнят остаток нулями. Ничто в этих функциях не проверяет истинный размер назначения.

В отличии от gets(), эти функции возможно использовать безопасным образом, только это не просто. В языках C++ и Objective-C есть лучшие альтернативы этим функциям C, что делает работу со строками проще и безопаснее, однако функции C также поддерживаются в целях обратной совместимости.

Более того, они сохраняют фундаментальный недостаток языка C: буферы не знают своего размера, и язык никогда не проверяет выполняемые над буферами чтения и записи, допуская переполнение. Именно такое поведение привело к недавнему багу Heartbleed в OpenSSL. То не было переполнение, а перечтение, когда код на C в составе OpenSSL пытался прочитать из буфера больше чем тот содержал, сливая информацию наружу.

Латание дыр

Конечно, человечество разработало множество языков в которых осуществляется проверка чтения и записи в буферы, что защищает от переполнения. Компилируемые языки, такие как поддерживаемый Mozilla язык Rust, защищённые среды исполнения вроде Java и .NET, и практически все скриптовые языки вроде Python, JavaScript, Lua и Perl имеют иммунитет к этой проблеме (хотя в .NET разработчики могут явным образом отключить защиту и подвергнуть себя подобному багу, но это личный выбор).

Тот факт, что переполнение буфера продолжает оставаться частью ландшафта безопасности, говорит о популярности C. Одой из причин этого, конечно, является большое количество унаследованного кода. В мире существует огромное количество кода на C, включая ядра всех основных операционных систем и популярных библиотек, таких как OpenSSL. Даже если разработчики хотят использовать безопасный язык, вроде C#, у них могут оставаться зависимости от сторонних библиотек, написанных на C.

Производительность является другой причиной продолжающегося использования C, хотя смысл такого подхода не всегда понятен. Верно, что компилируемые C и С++ обычно выдают быстрый исполняемый код, и в некоторых случаях это действительно очень важно. Но у многих из нас процессоры большую часть времени простаивают; если бы мы могли пожертвовать, скажем, десятью процентами производительности наших браузеров, но при этом получить железную гарантию невозможности переполнения буфера — и других типичных дыр, мы может быть бы решили, что это не плохой размен. Только никто не торопится создать такой браузер.

Несмотря ни на что, C сотоварищи никуда не уходит; как и переполнение буфера.

Предпринимаются некоторые шаги по предупреждению этого рода ошибок. В ходе разработки, можно использовать специальные средства анализа исходного кода и запущенных программ, стараясь обнаружить опасные конструкции или ошибки переполнения до того, как эти баги пролезут в релиз. Новые средства, такие как AddressSanitizer и более старые, как Valgrind дают такие возможности.

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

Некоторые из этих систем нацелены на усложнение конкретных атак. Один из наборов патчей для Linux делает так, что все системные библиотеки загружаются в нижние адреса таким образом, чтобы содержать, по крайней мере, один нулевой байт в своём адресе; это существенно усложняет их использование в переполнениях эксплуатирующих обработку строк в C.

Другие средства защиты действуют более обще. Во многих компиляторах имеется какой-либо род защиты стека. Определяемое на этапе исполнения значение, называемое „канарейкой“ (canary) пишется в конец стека рядом с адресом возврата. В конце каждой функции, это значение проверяется перед выполнением инструкции возврата. Если значение канарейки изменилось (по причине перезаписи в ходе переполнения), программа немедленно рухнет вместо продолжения.

Возможно, важнейшим из средств защиты является механизм известный под именами W^X (»write exclusive-or execute»), DEP («data execution prevention»), NX («No Xecute»), XD («eXecute Disable»), EVP («Enhanced Virus Protection,» специфичный для AMD термин), XN («eXecute Never»), и, вероятно, другими. Здесь принцип прост. Эти системы стараются разделить память на записываемую (подходящую для буферов) и исполнимую (подходящую для библиотек и программного кода), но не одновременно ту и другую. Таким образом, даже если атакующий может переполнить буфер и контролировать адрес возврата, процессор не будет выполнять шеллкод.

Как бы вы его не назвали, это важный механизм ещё и потому, что он не требует вложений. Этот подход использует защитные меры встроенные в процессор, поскольку это часть механизма аппаратной поддержки виртуальной памяти.

Как уже говорилось ранее, в режиме виртуальной памяти каждый процесс получает свой набор частных адресов памяти. Операционная система и процессор совместно поддерживают соотношение виртуальных адресов к чему-то ещё; иногда, виртуальный адрес отображается на физическую память, иногда в часть файла на диске, а иногда в никуда, просто потому что он не распределён. Это соотнесение гранулярно и обычно происходит частями размером в 4096 байт, именуемыми страницами.

Мастер Йода рекомендует:  Простой эффект боке для текста

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

Одним из интересных моментов NX является то, что его можно применить к существующим программам «задним числом», просто путём обновления операционной системы до той, что поддерживает защиту. Иногда программы налетают на проблемы. JIT (Just-in-time)-компиляторы, используемые в Java и .NET, генерируют исполнимый код в памяти на этапе исполнения, и поэтому требуют память, которую можно и писать и исполнять (хотя, одновременность этих свойств не требуется). Когда ещё не было NX, вы могли исполнять код из любой памяти, которую могли читать, поэтому в таких JIT-компиляторах не было проблемы с особыми буферами чтения-записи. С появлением NX, от них требуется удостовериться, что защита памяти изменена с чтение-запись на чтение-исполнение.

Потребность в чём-то вроде NX была ясна, особенно для Microsoft. В начале 2000-х, пара червей показала, что у компании были серьёзные проблемы с безопасностью кода: Code Red, инфицировавший не менее 359000 систем под управлением Windows 2000 с сервисом Microsoft IIS Web server в июле 2001, и SQL Slammer, инфицировавший более 75000 систем с Microsoft SQL Server в январе 2003. Эти случаи хорошо ударили по репутации.

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

Естественно, эти черви были более продвинуты и в других областях. Нагрузка Code Red не просто самовоспроизводилась; она производила дефейс веб-страниц и пыталась выполнять DoS-атаки. SQL Slammer нёс в себе всё необходимое для поиска новых целей для заражения и распространения по сети — всего в нескольких сотнях байт, при этом не оставляя следов на инфицированных машинах; перезагрузите машину — и его нет. Оба червя также работали в Интернете, который был многократно больше того, в котором распространился червь Морриса, и потому число заражений было сильно выше.

Однако основная проблема — легко эксплуатируемое переполнение стекового буфера — осталась прежней. Эти черви оказались в заголовках новостей и заставили многих сомневаться в возможности использовать Windows любого рода в качестве сервера, смотрящего в Интернет. Ответом Microsoft было начать всерьёз задумываться о безопасности. Windows XP Service Pack 2 была первым продуктом с установкой на безопасность. Было сделано несколько программных изменений, включая добавление программного межсетевого экрана, модификация Internet Explorer, препятствующая тихой установке тулбаров и плагинов, а также — поддержка NX.

Аппаратное обеспечение с поддержкой NX стало входить в быт где-то с 2004 года, когда Intel представила Prescott Pentium 4, поддержка со стороны операционных систем стала обыденностью со времён Windows XP SP2. В Windows 8 они решили ещё больше форсировать этот момент, отказавшись от поддержки процессоров, не умеющих NX.

Что было после NX

Несмотря на распространение поддержки NX, переполнение буфера остаётся актуальной проблемой информационной безопасности. Причиной тому является разработка ряда способов обхода NX.

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

Возможно, лучшим кандидатом на эту роль является Unix-функция system(). Она принимает один параметр: адрес строки, представляющей собой команду для исполнения — и обычно этот параметр передаётся через стек. Атакующий может создать нужную команду и поместить её в переполняемый буфер, а поскольку (традиционно) расположение объектов в памяти неизменно, адрес этой строки будет известен и может быть помещён на стек в ходе атаки. Переписанный адрес возврата в этом случае не указывает на адрес в буфере; он указывает на функцию system(). Когда функция подверженная переполнению завершает работу, вместо возврата в вызывающую функцию она запустит system(), что приведёт к исполнению заданной атакующим команды.

Вот так можно обойти NX. Функция system(), будучи частью системной библиотеки, уже исполнима. Эксплойту не требуется исполнять код из стека; достаточно прочитать команду с него. Этот приём получил название «return-to-libc» (возврат на libc, библиотеки Unix, содержащей множество ключевых функций, включая system(), и обычно загружаемой в каждый Unix-процесс, что делает её подходящей целью для такого использования) и был изобретён в 1997 году русским экспертом по информационной безопасности Solar Designer.

Хотя этот приём и полезен, у него есть ограничения. Часто функции принимают аргумент не со стека, а через регистры. Удобно передавать команды для исполнения, но они часто содержат эти дурацкие нули, что немало мешает. Кроме того, составить последовательность из различных вызовов таким способом весьма непросто. Это возможно — прописать несколько адресов возврата вместо одного — но нет способа изменить порядок следования аргументов, используя возвращаемые значения или что-либо ещё.

Вместо заполнения буфера шелкодом, мы заполняем его последовательностью адресов возврата и данными. Эти адреса возврата передают управление существующим фрагментам исполнимого кода в программе-жертве и её библиотеках. Каждый фрагмент кода выполняет операцию и выполняет возврат, передавая управление по следующему адресу возврата.

За несколько лет, return-to-libc был обобщён для обхода этих ограничений. В конце 2001 было задокументировано несколько вариантов расширения этого способа: возможность нескольких вызовов и решение проблемы нулевых байтов. Более сложный способ, решавший большую часть этих проблем, был формально описан в 2007 году: return-oriented-programming (ROP, возвратно-ориентированное программирование).

Здесь используется тот же принцип что и в return-to-libc и трамплине, но более обобщённый. Там где трамплин использует единственный фрагмент кода для передачи исполнения шеллкоду в буфере, ROP использует много фрагментов кода, называемых «гаджетами» в оригинальной публикации. Каждый гаджет следует определённому шаблону: он выполняет некую операцию (запись значения в регистр, запись в память, сложение регистров, и т.п.), за которой следует команда возврата. То самое свойство, что делает x86 пригодным для трамплина работает и здесь; системные библиотеки, загруженные в память процессом, содержат сотни последовательностей которые можно интерпретировать как «действие и возврат», а значит, могут быть использованы для ROP-атак.

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

Как и в случае с return-to-libc, весь действительно исполнимый код берётся из системных библиотек, и как следствие защита вроде NX бесполезна. Большая гибкость этого подхода означает, что эксплойты могут делать то, что сложно организовать последовательностью return-to-libc, например, вызывая функции принимающие аргументы через регистры, использовать возвращаемые значения одних функций в других и прочее.

Нагрузка в ROP-атаках бывает разной. Иногда это простой код для получения шелла (доступа к командному интерпретатору). Другим распространённым вариантом является использование ROP для вызова системной функции для изменения NX-параметров страницы памяти, меняя их с записываемых на исполнимые. Сделав это, атакующий может использовать обычную, не-ROP нагрузку.

Рандомизация

Эта слабость NX давно известна, и эксплойты такого типа шаблоны: атакующий заранее знает адрес стека и системных библиотек в памяти. Всё зиждется на этом знании, а потому очевидным решением является лишить атакующего этого знания. Именно этим занимается ASLR (Address Space Layout Randomization, Рандомизация развёртки адресного пространства): он делает случайной позицию стека и расположение в памяти библиотек и исполнимого кода. Обычно они меняются при каждом запуске программы, перезагрузке или некоторой их комбинации.

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

ASLR во многом сопутствует NX, закрывая такие крупные дыры как возврат к libc или ROP. К несчастью, он несколько менее прозрачен, чем NX. Не считая JIT-компиляторов и ряда других специфичных случаев, NX может быть безопасно внедрён в существующие программы. ASLR более проблематичен: с ним программы и библиотеки не могут полагаться в своей работе на значение адреса, в который они загружены.

В Windows, например, это не должно быть большой проблемой для DLL. В Windows, DLL всегда поддерживали загрузку в разные адреса, а вот для EXE это может быть проблемой. До ASLR, EXE всегда загружались в адрес 0x0040000 и могли полагаться на этот факт. С внедрением ASLR это уже не так. Чтобы предотвратить возможные проблемы, Windows по умолчанию требует от программ явного указания поддержки ASLR. Люди, думающие о безопасности, могут, однако, изменить это поведение по умолчанию, заставив Windows включить ASLR для всех программ и библиотек. Это почти никогда не вызывает проблем.

Ситуация вероятно хуже в Linux на x86, поскольку подход к реализации ASLR на этой платформе даёт потерю производительности до 26 процентов. Более того, этот подход требует компиляции программ и библиотек с поддержкой ASLR. Нет способа администратору сделать ASLR принудительным, как в Windowsю (на x64 потеря производительности пусть и не уходит совсем, но значительно снижается)

Когда ASLR активен, он даёт сильную защиту от простого взлома. Однако, он не совершенен. Например, одним из ограничений является степень случайности, которую можно получить, что особенно заметно на 32-битных системах. Хотя в адресном пространстве 4 миллиарда различных адресов, не все они доступны для загрузки библиотек или размещения стека.

Для этого существует множество ограничений. Некоторые из них состоят в широте целей. В общем случае, операционная система предпочитает загружать библиотеки близко друг-к-другу на одном из концов адресного пространства процесса, чтобы как можно больше непрерывного места было доступно приложению. Вам не хочется получить по одной библиотеке через каждые 256МБ памяти, поскольку тогда возможное наибольшее унитарное выделение памяти будет меньше 256МБ, что ограничивает возможность приложения работать с данными большого объёма.

Исполнимые файлы и библиотеки обычно должны быть загружены так чтобы начинаться, по крайней мере, на границе страницы. Обычно, это означает, что они должны быть загружены в адрес, делимый на 4096. Различные платформы могут и иметь подобные ограничения для стека; Linux, например, начианет стек на адресе делимом на 16. Системы с ограничением по памяти иногда вынуждены ещё более ограничить случайность, чтобы иметь возможность всё разместить.

Результаты бывают различными, но иногда атакующий могут угадать нужный адрес, с высокой вероятностью попадания. Даже невысокого шанса — скажем, один из 256 — может быть достаточно в некоторых ситуациях. Когда атакуешь веб-сервер, который автоматически перезапустит рухнувший процесс, не важно, что 255 из 256 атак приведут к краху процесса. Он будет перезапущен, и можно попробовать снова.

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

Угадывание и падение не слишком хорошая стратегия для атаки, скажем, браузеров; ни один пользователь не будет перезапускать браузер 256 раз кряду лишь бы дать атакующему шанс. В результате, эксплуатация такой уязвимости в системе с активными NX и ASLR не может быть произведена без посторонней помощи.

Такая помощь может быть нескольких видов. В браузере можно использовать JavaScript или Flash — и то и другое содержит JIT-компиляторы генерирующие исполнимый код — для заполнения памяти аккуратно сконструированным исполнимым кодом. Это создаёт что-то вроде большой посадочной полосы, приём под названием «heap spraying» («напыление кучи»). Другим подходом может быть нахождение вторичного бага, позволяющего раскрыть адреса библиотек или стека в памяти, давая атакующему достаточно информации для создания специфичного набора возвратных адресов для ROP.

Третий подход также был популярен в браузерах: использовать библиотеки, не умеющие ASLR. Старые версии, например, плагинов Adobe PDF или Microsoft Office не поддерживали ASLR, и Windows по умолчанию не форсирует ASLR. Если атакующий может вызвать загрузку такой библиотеки (например, загрузив PDF в скрытом фрейме браузера), то об ASLR можно уже не беспокоиться, а использовать эту библиотеку для целей ROP.

Война без конца

Между теми, кто эксплуатирует уязвимости и теми, кто защищает, идёт постоянная гонка вооружений. Мощные защитные системы, вроде ASLR и NX, поднимают планку, усложняя использование недостатков, и благодаря им мы оставили времена простого переполнения буфера позади, но умные атакующие могут найти комбинацию дыр и обойти эти защитные меры.

Эскалация продолжается. Набор Microsoft EMET («Enhanced Mitigation Experience Toolkit», «расширенный набор инструментов противодействия») включает ряд полу-экспериментальных средств защиты, которые могут обнаруживать heap spraying или попытки вызова определённых критичных функций в ROP-эксплойтах. Но в непрерывной цифровой войне, даже часть этих приёмов уже побеждена. Это не делает их бесполезными — сложность (а значит и цена) эксплуатации уязвимостей возрастает с каждым применённым средством противодействия — но это напоминание о необходимости постоянной бдительности.

Система обнаружила переполнение стекового буфера в этом приложении [FIX]

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

Одна из этих ошибок — « система обнаружила переполнение стекового буфера в этом приложении », но она может не доходить до загрузки вашего компьютера после BSOD.

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

Как я могу исправить ошибку «Система обнаружила переполнение стекового буфера…»?

  1. Сканирование на наличие вредоносных программ
  2. Запустите SFC/DISM
  3. Выполните чистую последовательность загрузки
  4. Ремонт с использованием системных ресурсов
  5. Ремонт с помощью загрузочного диска
  6. Переустановите Windows 10

Решение 1 — Сканирование на наличие вредоносных программ

Как вы уже знаете, полное сообщение об ошибке: «Система обнаружила переполнение стекового буфера в этом приложении. Это превышение может потенциально позволить злоумышленнику получить контроль над этим приложением ».

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

Вот почему мы предлагаем сканирование на наличие вредоносных программ. Конечно, если вы не можете загрузиться, вы можете попробовать в безопасном режиме и использовать автономную проверку Защитника Windows для удаления всех угроз.

Вот что вам нужно сделать:

  1. 3 раза принудительно перезагрузите компьютер, чтобы вызвать меню Расширенное восстановление .
  2. Выберите Troubleshoot .
  3. Выберите Дополнительные параметры , а затем Параметры запуска .
  4. Нажмите Restart .
  5. Выберите Безопасный режим (или Безопасный режим с поддержкой сети).
  6. После загрузки ПК откройте Защитник Windows в области уведомлений панели задач.
  7. Выберите Защита от вирусов и угроз .
  8. Выберите Параметры сканирования .
  9. Установите флажок Автономное сканирование Защитника Windows и нажмите Сканировать сейчас .

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

— СВЯЗАНО: 9 лучших антивирусных программ с шифрованием для защиты ваших данных в 2020 году

Решение 2 — Запустите SFC/DISM

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

Несмотря на то, что System File Checker этого не делает, нам нужно запустить оба инструмента, чтобы исправить возможные повреждения системы. Они работают лучше всего, когда объединены, и поэтому мы будем управлять ими последовательно.

Выполните следующие шаги для запуска SFC и DISM:

    1. Войдите в безопасный режим с поддержкой сети .
    2. Откройте Командную строку в качестве администратора.
    3. В командной строке скопируйте и вставьте следующие строки и нажмите Enter после каждого:
      • SFC/SCANNOW
      • DISM/онлайн/Cleanup-Image/ScanHealth
      • DISM/Online/Cleanup-Image/RestoreHealth
    4. После этого перезагрузите компьютер.

Решение 3 — Выполните чистую последовательность загрузки

Другим жизнеспособным шагом для решения проблем, вызванных мошенническим приложением, является чистая загрузка. Совершенно очевидно, что одно из приложений, которые запускаются с системой, повреждено и, таким образом, вызывает «Система обнаружила переполнение стекового буфера…».

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

Следуйте этим инструкциям, чтобы отключить запуск всех фоновых приложений и служб с системой:

  1. В панели поиска Windows найдите msconfig и откройте Конфигурация системы .
  2. На вкладке «Службы» установите флажок « Скрыть все службы Microsoft ».
  3. Нажмите « Отключить все ».
  4. Теперь перейдите на вкладку Автозагрузка и перейдите в Диспетчер задач .
  5. Запретить запуск всех программ с системой и подтвердить изменения.
  6. Перезагрузите компьютер.

Решение 4 — Ремонт с системными ресурсами

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

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

Вот что вам нужно сделать:

  1. Откройте меню Расширенное восстановление и выберите Устранение неполадок .
  2. Выберите Дополнительные параметры .
  3. Здесь вы можете выбрать Восстановление системы или Восстановление при загрузке .
  4. Попробуйте одно, потом другое, и, надеюсь, вы сможете загрузиться.

— СВЯЗАНО: 5 лучших программ для восстановления загрузки Windows 10, чтобы оживить ваш компьютер в 2020 году

Решение 5 — Ремонт с загрузочного диска

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

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

Выполните следующие действия для восстановления поврежденной Windows 10 с загрузочного носителя:

  1. Отключите все от вашего компьютера, кроме мыши и клавиатуры.
  2. Вставьте загрузочный носитель (USB или DVD) и загрузитесь с ним.
  3. После загрузки диска выберите « Восстановить компьютер ».
  4. Выберите Troubleshoot .
  5. Выберите Дополнительные параметры .
  6. Выберите Восстановление при загрузке .

Решение 6 — Переустановите Windows 10

Наконец, если ни один из предыдущих шагов не помог вам в решении проблемы, мы рекомендуем вам сделать резервную копию ваших данных и переустановить Windows 10.

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

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

Вы можете узнать больше о переустановке Windows 10, выполнив действия, описанные в этой статье.

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

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