<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://course.secsem.ru/w/index.php?action=history&amp;feed=atom&amp;title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8%2FStack_overflow</id>
	<title>Бинарные уязвимости/Stack overflow - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://course.secsem.ru/w/index.php?action=history&amp;feed=atom&amp;title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8%2FStack_overflow"/>
	<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;action=history"/>
	<updated>2026-07-01T10:30:19Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=612&amp;oldid=prev</id>
		<title>Dzeni: /* Эксплуатация */</title>
		<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=612&amp;oldid=prev"/>
		<updated>2021-11-24T13:09:29Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Эксплуатация&lt;/span&gt;&lt;/p&gt;
&lt;a href=&quot;https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;amp;diff=612&amp;amp;oldid=380&quot;&gt;Внесённые изменения&lt;/a&gt;</summary>
		<author><name>Dzeni</name></author>
	</entry>
	<entry>
		<id>https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=380&amp;oldid=prev</id>
		<title>Dzeni: /* Способы защиты */</title>
		<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=380&amp;oldid=prev"/>
		<updated>2020-11-27T13:18:51Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Способы защиты&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 13:18, 27 ноября 2020&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l99&quot;&gt;Строка 99:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 99:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Данный способ защиты используется в компиляторы clang и должен быть активирован при компиляции с помощью специального [https://clang.llvm.org/docs/SafeStack.html ключа].&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Данный способ защиты используется в компиляторы clang и должен быть активирован при компиляции с помощью специального [https://clang.llvm.org/docs/SafeStack.html ключа].&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;==Ссылки==&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* [https://drive.google.com/file/d/1UlUUXtivj2IcCcgr-mhsvaFHNlHrLqVh/view?usp=sharing презентация &quot;Stack overflow&quot;]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Dzeni</name></author>
	</entry>
	<entry>
		<id>https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=371&amp;oldid=prev</id>
		<title>Dzeni: Новая страница: «=Адресное пространство процесса=  Файл:address_space_1.png|500px|right|thumb|Пример содержимого адресно…»</title>
		<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%91%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D0%B5_%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8/Stack_overflow&amp;diff=371&amp;oldid=prev"/>
		<updated>2020-11-27T10:42:48Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «=Адресное пространство процесса=  Файл:address_space_1.png|500px|right|thumb|Пример содержимого адресно…»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Адресное пространство процесса=&lt;br /&gt;
&lt;br /&gt;
[[Файл:address_space_1.png|500px|right|thumb|Пример содержимого адресного пространства процесса на x86]]&lt;br /&gt;
&lt;br /&gt;
Адресное пространство процесса на x86/amd64 - это совокупность виртуальных адресов, доступная программе. Размер адресного пространства на x86 без дополнительных способов расширения - 4 Гб, он разделённый на kernel-space (2/1 Гб) и user-space (2/3 Гб). На x86-64 размер адресного пространства 2**48 - старшие 16 бит адреса все равны или 0, или 1. Такие адреса называются каноничными, все другие - неканоничными. В случае попытки обращения к неканоничному адресу возникает general protection exception ([https://stackoverflow.com/questions/8997044/x86-64-linux-3-0-invalid-memory-addresses/8997388#8997388 #GP]). В случае x86-64 каноничность адресов можно использовать при проведении анализа содержимого памяти (так адрес из адресного пространства ядра будет иметь префикс 0xFFF, а из пользовательского - 0x000).&lt;br /&gt;
&lt;br /&gt;
В *nix в user-space части адресного пространства содержится:&amp;lt;br /&amp;gt;&lt;br /&gt;
- запускаемый исполняемый файл&amp;lt;br /&amp;gt;&lt;br /&gt;
- динамические *.so библиотеки&amp;lt;br /&amp;gt;&lt;br /&gt;
- mmap() области (анонимные аллокации и отмапленные файлы)&amp;lt;br /&amp;gt;&lt;br /&gt;
- стек&amp;lt;br /&amp;gt;&lt;br /&gt;
- куча&amp;lt;br /&amp;gt;&lt;br /&gt;
- отмапленные из ядра области (vsyscall/vvar/vdso)&amp;lt;br /&amp;gt;&lt;br /&gt;
- различные служебные структуры&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В pwndbg/gef/peda содержимое адресного пространства можно посмотреть с помощью команды vmmap:&lt;br /&gt;
&lt;br /&gt;
[[Файл:address_space_2.png|800px|border|Вывод команды vmmap в pwndbg]]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В gdb можно использовать команду &amp;#039;&amp;#039;&amp;#039;info proc map&amp;#039;&amp;#039;&amp;#039;, а без отладчика содержимое можно посмотреть через файловую систему /proc с помощью команды &amp;#039;&amp;#039;&amp;#039;cat /proc/&amp;lt;self&amp;gt;/maps&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Stack buffer overflow=&lt;br /&gt;
&lt;br /&gt;
Переполнение буфера в стеке происходит, когда программа не проверяет должным образом размер буфера, выделенного на стеке, при записи в него. Например, так делают известные функции &amp;#039;&amp;#039;&amp;#039;gets&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;strcpy&amp;#039;&amp;#039;&amp;#039;. Рассмотрим пример функции с таким типом уязвимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void foo(char *arg) {&lt;br /&gt;
  char local[256];&lt;br /&gt;
  strcpy(local, arg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной функции определяется локальный массив &amp;#039;&amp;#039;&amp;#039;local&amp;#039;&amp;#039;&amp;#039;, размещающийся на стеке и содержащий 256 элементов, и функция копирует аргумент &amp;#039;&amp;#039;&amp;#039;arg&amp;#039;&amp;#039;&amp;#039; с помощью функции strcpy. Данная функция копирует &amp;#039;&amp;#039;&amp;#039;arg&amp;#039;&amp;#039;&amp;#039;, переданный во втором аргументе, в &amp;#039;&amp;#039;&amp;#039;local&amp;#039;&amp;#039;&amp;#039; до тех пор пока не встретит в ней нулевой байт. При этом сам нулевой байт также будет скопирован. Чтобы понять, почему это может быть опасно, нужно рассмотреть содержимое стекового кадра функции &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039;. Предположим, что мы скомпилировали данный код в 32-битную программу и соглашение о вызовах функции - &amp;#039;&amp;#039;&amp;#039;cdecl&amp;#039;&amp;#039;&amp;#039;. Тогда стековый кадр будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
[[Файл:stack_frame.png|400px|border|Стековый кадр функции foo]]&lt;br /&gt;
&lt;br /&gt;
На данной схеме стрелочкой показано направление роста стека в адресном пространстве (от старших к младшим адресам). Далее последовательно в стеке располагаются:&amp;lt;br /&amp;gt;&lt;br /&gt;
- аргумент функции &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
- адрес возврата - адрес, на который перейдет управление после окончания исполнения функции &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
- значение регистра &amp;#039;&amp;#039;&amp;#039;ebp&amp;#039;&amp;#039;&amp;#039;, являющееся указателем стекового кадра вызывающей &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039; функции&amp;lt;br /&amp;gt;&lt;br /&gt;
- опциональный паддинг (обычно используется, что локальные аргументы были выравнены по 16 байт)&amp;lt;br /&amp;gt;&lt;br /&gt;
- локальный массив &amp;#039;&amp;#039;&amp;#039;local&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Функция &amp;#039;&amp;#039;&amp;#039;strcpy&amp;#039;&amp;#039;&amp;#039; осуществляет копирование в сторону противоположную росту стека. Таким образом при достаточном размере копируемой строки она может перетереть данные, хранящиеся после &amp;#039;&amp;#039;&amp;#039;local&amp;#039;&amp;#039;&amp;#039;: &amp;#039;&amp;#039;&amp;#039;ebp&amp;#039;&amp;#039;&amp;#039;, адрес возврата, аргументы и стековый кадр другой функции. Самым интересным с точки зрения эксплуатации является изменения адреса возврата, т.к. это значение полностью определяет, какой участок кода будет выполняться после завершения данной функции.&lt;br /&gt;
&lt;br /&gt;
==Эксплуатация==&lt;br /&gt;
&lt;br /&gt;
Самый простой способ эксплуатации данной уязвимости заключается в том, чтобы поместить в стек шеллкод (набор опкодов, которые исполняют нужное нам, например, вызывают командный интерпретатор&amp;#039;&amp;#039;&amp;#039;/bin/sh&amp;#039;&amp;#039;&amp;#039;) и записать в качестве адреса возврата его адрес:&lt;br /&gt;
[[Файл:stack_overflow_exploitation_scheme.png|400px|border|Возможный способ эксплуатации уязвимости в функции foo]]&lt;br /&gt;
&lt;br /&gt;
Тогда после завершения функции &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039; управление перейдет на шеллкод.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Способы защиты=&lt;br /&gt;
&lt;br /&gt;
Существует большое количество различных средств защиты от эксплойтов (exploit mitigations) как на уровне компилятора, так и операционной системы. Рассмотрим некоторые их них.&lt;br /&gt;
&lt;br /&gt;
==Stack guard value==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Guard value (cookie/canary)&amp;#039;&amp;#039;&amp;#039; в общем смысле - это значение, которое помещается между буфером и данными, которые нужно защитить. Таким образом, любое переполнение буфера ведёт к перетиранию этого значения. И перед любым использованием защищаемых данных необходимо проверить это значение. В случае стека данное значение помещается между локальными данными и сохраненным регистром (r/e)bp:&lt;br /&gt;
[[Файл:Stack_frame_with_cookie.jpg|400px|border|Место размещения stack cookie в стековом кадре функции foo]]&lt;br /&gt;
&lt;br /&gt;
Заметим, что было неправильно помещать его между адресом возврата и (r/e)bp, т.к. его изменение тоже может привести к эксплуатации. [https://wiki.osdev.org/Stack_Smashing_Protector Stack guard value] также называется stack cookie, stack canary или stack smashing protector.&lt;br /&gt;
&lt;br /&gt;
Данное значение обычно формируется один раз случайным образом (при этом почти всегда содержит нулевой байт) при запуске программы и сохраняется в структуру под названием [https://github.com/bminor/glibc/blob/e4a399921390509418826e8e8995d2441f29e243/sysdeps/x86_64/nptl/tls.h#L51 thread control block (TCB)]. Указатель на данную структуру хранится в регистре &amp;#039;&amp;#039;&amp;#039;fs&amp;#039;&amp;#039;&amp;#039; в случае x86-64 и &amp;#039;&amp;#039;&amp;#039;gs&amp;#039;&amp;#039;&amp;#039; в x86. В &amp;#039;&amp;#039;&amp;#039;pwndbg&amp;#039;&amp;#039;&amp;#039; есть специальные команды &amp;#039;&amp;#039;&amp;#039;gsbase&amp;#039;&amp;#039;&amp;#039;/&amp;#039;&amp;#039;&amp;#039;fsbase&amp;#039;&amp;#039;&amp;#039;, которые можно использовать для просмотра значения в данных регистрах:&lt;br /&gt;
[[Файл:gsbase.png|500px|left|border|Пример использования команды gsbase для просмотра stack cookie]]&lt;br /&gt;
[[Файл:fsbase.png|560px|right|border|Пример использования команды fsbase для просмотра stack cookie]]&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также для получения содержимого данных регистров может использоваться метод, описанный [https://unix.stackexchange.com/a/453772 здесь]. Из данных рисунков видно, что TCB замаплен с правами на запись - это означает, что при наличии соответствующей уязвимости и знания адреса TCB можно переписать stack cookie.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим, как же именно используется stack cookie: в прологе функции stack cookie сохраняется в стек сразу после (r/e)bp и проверяется перед выходом из функции. Ниже приведены ассемблерные листинги функции &amp;#039;&amp;#039;&amp;#039;foo&amp;#039;&amp;#039;&amp;#039;, скомпилированной соответственно без и с stack guard value:&lt;br /&gt;
[[Файл:foo_without_cookie.png|500px|left|border|Дизассемблированный листинг фукнции foo без stack cookie]]&lt;br /&gt;
[[Файл:foo_with_cookie.png|500px|right|border|Дизассемблированный листинг фукнции foo со stack cookie]]&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видно из листинга справа в прологе функции на стек сохраняется значение из регистра &amp;#039;&amp;#039;&amp;#039;gs&amp;#039;&amp;#039;&amp;#039; по смещению 0x14 - как раз по данному смещению в случае x86 располагается поле &amp;#039;&amp;#039;&amp;#039;stack_guard&amp;#039;&amp;#039;&amp;#039;, содержащие [https://github.com/bminor/glibc/blob/e4a399921390509418826e8e8995d2441f29e243/sysdeps/x86_64/nptl/tls.h#L51 cookie]. В эпилоге функции перед выполнением инструкции &amp;#039;&amp;#039;&amp;#039;ret&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;cookie&amp;#039;&amp;#039;&amp;#039;, сохраненные на стеке, сравниваются со значением, сохраненным в &amp;#039;&amp;#039;&amp;#039;TCB&amp;#039;&amp;#039;&amp;#039;. В случае, если они не совпадают, выполняется функция &amp;#039;&amp;#039;&amp;#039;__stack_check_fail&amp;#039;&amp;#039;&amp;#039;, выводящая сообщение об ошибке и завершающая программу.&lt;br /&gt;
&lt;br /&gt;
==ASLR==&lt;br /&gt;
&lt;br /&gt;
Чтобы затруднить атаки класса переиспользования кода (code reuse), такие как возврат в libc, адреса стека, кучи, и загрузки библиотек рандомизируются при каждом запуске программы. Это называется address space layout randomization.&lt;br /&gt;
&lt;br /&gt;
Например, если в программе есть уязвимость, позволяющая переписать указатель на функцию, вы не можете записать туда адрес функции system просто потому, что вы не знаете адрес этой функции. Похожая ситуация будет, если есть указатель на какую-то структуру (например, содержащую в себе флаг is_admin): возможно вы и можете создать фейковую структуру с правильными полями на стеке, но вы не знаете, по какому адресу она окажется, чтобы записать этот адрес в тот указатель.&lt;br /&gt;
&lt;br /&gt;
Как и многие другие защиты, ASLR не является абсолютной. Если в программе есть баг, позволяющий читать память за границей массива на стеке, с большой вероятностью вы там найдете адрес, ведущий в libc. Например, функция main возвращается куда-то в недра __libc_start_main, и если получится узнать адрес возврата, то посчитав смещение этого места относительно начала libc (для этой конкретной версии libc!), вы сможете узнать адрес загрузки библиотеки - и, соответственно, адреса всех функций, смещения которых фиксированы относительно базового адреса загрузки.&lt;br /&gt;
&lt;br /&gt;
==NX==&lt;br /&gt;
&lt;br /&gt;
Средства ОС и процессора позволяют гибко настраивать права доступа на страницы виртуальной памяти. Эти права доступа позволяют запрещать выполнять данные как инструкции процессора. Напрмер, даже если записать шеллкод на стек, в память, выделенную через malloc или в статический глобальный буфер, при попытке выполнить этот код произойдет SIGSEGV.&lt;br /&gt;
&lt;br /&gt;
На уровне пользовательской программы это реализовано флагом prot в системных вызовах mmap и mprotect. Сам пользовательский код редко использует эти системные вызовы напрямую: ядро системы, динамический загрузчик (ld.so) и libc сами выделяют память с правильными правами доступа.&lt;br /&gt;
&lt;br /&gt;
Фактически это означает, что чтобы в таких условиях добиться выполнения произвольного кода (или хотя бы выходящего за спецификацию исходной программы), придется провести атаку переиспользования кода (code reuse) в том или ином виде. Например, переписать указатель на какую-то безобидную функцую на system.&lt;br /&gt;
&lt;br /&gt;
==Safe stack==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Safe stack&amp;#039;&amp;#039;&amp;#039; – механизм сохранения указателей (адреса возврата, указатели на функции и т.п.) в отдельной изолированной области памяти, доступ к которой производится только с использованием специальных проверок корректности обращения к памяти.&lt;br /&gt;
&lt;br /&gt;
Таким образом, стек приложения разделяется на две части - защищённый стек для хранения указателей, адресов из регистров и локальных переменных, и незащищённый стек, в котором сохраняется всё остальное. В защищённый стек данные добавляются только после статической проверки и доступ к ним ограничен.&lt;br /&gt;
&lt;br /&gt;
Данный способ защиты используется в компиляторы clang и должен быть активирован при компиляции с помощью специального [https://clang.llvm.org/docs/SafeStack.html ключа].&lt;/div&gt;</summary>
		<author><name>Dzeni</name></author>
	</entry>
</feed>