ArticlePDF Available

Dynamic detection of Use After Free Bugs

Authors:
  • Institute for System Programming, Russian Academy of Sciences

Abstract

The article describes new method of use after free bug detection using program dynamic analysis. In memory-unsafe programming languages such as C/C++ this class of bugs mainly accurse when program tries to access specific area of dynamically allocated memory that has been already freed. This method is based on combination of two basic components. The first component tracks all memory operations through dynamic binary instrumentation and searches for inappropriate memory access. It preserves two sets of memory address for all allocation and free instructions. Using both sets this component checks whether current memory is accessible through its address or it has been already freed. It is based on dynamic symbolic execution and code coverage algorithm. It is used to maximize the number of execution paths of the program. Using initial input, it starts symbolic execution of the target program and gathers input constraints from conditional statements. The new inputs are generated by systematically solving saved constraints using constraint solver and then sorted by number of basic blocks they cover. Proposed method detects use after free bugs by applying first component each time when second one was able to open new path of the program. It was tested on our synthetic tests that were created based on well-known use after free bug patterns. The method was also tested on couple of real projects by injecting bugs on different levels of execution.
7
Обнаружение ошибок, возникающих при
использовании динамической памяти
после её освобождения*
2 С.А. Асрян <asryan@ispras.ru>
1,3,5,6 С.С. Гайсарян <ssg@ispras.ru>
1 Ш.Ф. Курмангалеев <kursh@ispras.ru>
4А.М. Агабалян <anna.aghabalyan@ispras.ru>
4Н.Г. Овсепян <narekhnh@ispras.ru>
4С.С. Саргсян <sevaksargsyan@ispras.ru>
1 Институт системного программирования им. В.П. Иванникова РАН,
109004, Россия, г. Москва, ул. А. Солженицына, д. 25
2 Институт проблем информатики и автоматизации НАН РА,
Республика Армения, Ереван, 0014, ул. П.Севака, 1
3 МГУ имени М.В. Ломоносова, факультет ВМК,
2119991 ГСП-1 Москва, Ленинские горы, 2-й учебный корпус
4 Ереванский государственный университет
Республика Армения, г. Ереван, 0025, ул. Алека Манукяна, 1
5 Московский физико-технический институт,
141700, Московская облаcть, г. Долгопрудный, Институтский пер., 9
6 Национальный исследовательский университет «Высшая школа экономики»
101000, Россия, г. Москва, ул. Мясницкая, д. 20
Аннотация. Существенная часть программного обеспечения написана на языках
программирования C/C++. Программы на этих языках часто содержат ошибки:
использования памяти после освобождения (Use After Free, UAF), переполнения буфера
(Buffer Overflow) и др. В статье предложен метод обнаружения ошибок UAF,
основанный на динамическом анализе. Для каждого пути выполнения программы
предлагаемый метод проверяет корректность операций создания и доступа, а также
освобождения динамической памяти. Поскольку применяется динамический анализ,
поиск ошибок производится только в той части кода, которая была непосредственно
выполнена. Используется символьное исполнение программы с применением решателей
SMT (Satisfiability Modulo Theories) [12]. Это позволяет сгенерировать данные,
обработка которых приводит к обнаружению нового пути выполнения.
* Работа поддержана грантом РФФИ 17-01-00600
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
8
Ключевые слова: динамический анализ программ; покрытие кода; use-after-free.
DOI: 10.15514/ISPRAS-2018-30(3)-1
Для цитирования: Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М.,
Овсепян Н.Г., Саргсян С.С. Обнаружение ошибок, возникающих при использовании
динамической памяти после освобождения. Труды ИСП РАН, том 30, вып. 3, 2018 г.,
стр. 7-20. DOI: 10.15514/ISPRAS-2018-30(3)-1
1. Введение
В программном обеспечении могут содержаться такие ошибки, как:
использование динамической памяти после ее освобождения (Use After
Free, UAF),
переполнение буфера или кучи (buffer/heap overflow).
Поскольку огромная часть программного обеспечения используется в
критически-важных областях человеческой деятельности, наличие ошибок
может привести к серьезным последствиям. Существует ряд инструментов,
помогающих решить эту проблему, используя методы статического [1, 2] и
динамического анализа [3, 4, 5, 6, 7].
Статический анализ предоставляет возможность исследования программного
кода без его выполнения. Недостатком этого метода является отсутствие
информации о состоянии программы (регистры, трасса программы, входные
данные и т.д.) во время выполнения. Это приводит к большому количеству
ложных срабатываний. Поэтому данный метод в большинстве случаев
используется до применения динамического анализа для выявления
фрагментов программы, содержащих потенциальные ошибки.
Для поиска ошибок UAF инструмент [1] выполняет анализ, похожий на анализ
доступных выражений (выражение x+y является доступным в точке p, если
вдоль любого пути от входной точки до точки p данное выражение
вычисляется, а между этими вычислениями значения x и y остаются
неизменными [11]). Производится обход всех путей в программе, чтобы
обеспечить выполнение условия «определение объектов до их использования».
В случаи неудовлетворения данного условия считается, что было выполнено
ошибочное использование памяти и выводится ошибка.
Инструмент GUEB [2] основан на исследовании бинарного кода программы.
Процесс анализа разделяется на два основных этапа. На первом этапе
отслеживаются операции обращения к куче и присваивания адресов для
проведения анализа набора данных (какой указатель к какому элементу кучи
относится). На этом этапе информация {адрес, размер} сохраняется в
множествах alloc_set и free_set при создании и освобождении памяти
соответственно.
На втором этапе выполняется поиск ошибок UAF. Используя собранную
информацию для каждой точки программы, инструмент строит множество
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
9
access_heap, которое содержит все элементы {адрес, размер} кучи, доступные
в этой точке. Если пересечение access_heap и free_set является непустом
множеством, считается, что найдена ошибка UAF.
Одной из причин популярности динамического анализа является возможность
исследования программ во время выполнения. Благодаря этому возможен
доступ к значениям регистров и содержимому памяти. Инструмент Avalanche
[3] реализует итеративный анализ исполняемого кода программы, основанный
на динамической бинарной трансляции. В процессе анализа инструмент
вычисляет входные данные анализируемой программы с целью
автоматического обхода всех достижимых путей в программе и обнаружения
аварийных завершений программы.
Инструменты DangNull [4] и FreeSentry [5] фокусируются на обнаружении и
обнулении указателей на динамическую область программы после их
освобождения, предотвращая появление ошибок. Оба инструмента используют
статическую инструментацию программ.
Undangle [6] также предотвращает ошибки использования памяти после
освобождения. Этот инструмент помечает возвращаемые значения каждой
функции распределения памяти и использует анализ помеченных данных для
отслеживания этих меток. Далее при освобождении памяти проверяются, какие
ячейки памяти ассоциированы с соответствующей меткой, и определяются
висячие указатели (указатель с ненулевым значением, ссылающийся на
освобожденный область памяти).
Инструмент Mayhem [7] основан на методе поиска ошибок в бинарном коде,
объединяющем офлайн- и онлайн-подходы к символьному выполнению
программы. Офлайн-подход предполагает последовательное исследование
путей программы: при каждом новом запуске инструмент покрывает только
один путь выполнения. Недостатком является повторное выполнение общего
начального фрагмента пути при каждом запуске программы. Онлайн-подход, в
свою очередь, исследует все возможные пути выполнения программы
одновременно, что приводит к нехватке памяти в определенный момент
времени.
Объединение этих двух подходов заключается в следующем: при достижении
граничного значения расхода памяти создаются контрольные точки,
исследование некоторых путей останавливается с сохранением информации о
текущем состоянии выполнения, контекста символьного выполнения и
конкретных входных данных. После освобождения ресурсов (завершились
исследование некоторых путей), восстанавливается одна из контрольных точек
(с использованием сохраненных данных воспроизводится конкретное
выполнение до контрольной точки). Далее выполняется загрузка контекста
символьного выполнения и начинается анализ нового пути. Данный подход
позволяет избежать повторного символьного выполнения программы до места
создания контрольной точки.
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
10
В данной статье мы будем рассматривать подход, основанный на динамическом
анализе программы с использованием динамической инструментации [8, 9]. В
работе описывается метод обнаружения ошибок UAF, который проверяет
корректность использования указателей для всех возможных путей выполнения
программы. Этот метод основан на алгоритме покрытия кода, используемом в
SAGE [10], и использует инфраструктуру динамического анализатора Triton [9].
В рамках данной работы была выполнена модификация алгоритма покрытия
кода, используемого в Triton, что привело к значительному росту
производительности, а также была добавлена поддержка анализа программ,
работающих с файловыми входными данными, которая отсутствовала в
реализации Triton.
Второй раздел статьи посвящена описанию алгоритма покрытия кода
программы в Triton и предлагаемой модификации. В третьем разделе
рассматривается исходная реализация обнаружения ошибок UAF и ее
объединение с динамическим покрытием кода. В четвертом разделе
представлены результаты.
2. Алгоритм покрытия кода
2.1 Покрытие кода в Triton
В данной статье используется алгоритм увеличения покрытия кода программы,
разработанный в компании Microsoft и используемый в инструменте SAGE
[10]. Этот алгоритм частично реализован в Triton. Он состоит из двух этапов:
выбор начальных входных данных и сборка ограничений для каждого
пути выполнения программы;
получение новых входных данных с помощью решения логических
выражений, состоящих из ограничений, собранных на предыдущем
этапе.
Рассмотрим пример программы на рис. 1.
Рис. 1. Пример программы из статьи [10]
Fig. 1. An example of a program from [10]
Чтобы можно было исследовать все пути этой программы, на вход она должна
получить строку “bad!”. Чтобы получить нужные данные, алгоритм начинает
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
11
свою работу, запуская программу на начальной входной строке, которая
помещается в список входных данных. После первого запуска программы
получается набор ограничений < i0 b, i1 a, i2 d, i3 ! >, где i0, i1, i2, i3
представляют ячейки памяти input [0], input [1], input [2] и input [3]
соответственно.
В ходе работы алгоритма с помощью решения этих ограничений для каждого
элемента из списка входных данных генерируются дочерние данные,
удовлетворяющие этим ограничениям, которые далее помещаются в список
входных данных. Для каждого элемента из этого списка программа заново
запускается, и работа алгоритма возобновляется.
Этот процесс продолжается до тех пор, пока все элементы из списка входных
данных не будут поочередно рассмотрены (псевдокод алгоритма приведен на
рис. 3). Применив алгоритм для программы на рис. 1 с начальной входной
строкой “good”, мы получим набор решений, представленный на рис. 2.
Рис. 2. Входные данные после каждой итерации алгоритма
Fig. 2. Input data after each iteration of the algorithm
Рис. 3. Псевдокод алгоритма покрытия кода программы
Fig. 3. Pseudo code of a program code coverage algorithm
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
12
Поскольку работа данного алгоритма требует неоднократного запуска
программы, в Triton реализована возможность сохранения состояния
программы. Это позволяет значительно улучшить производительность
выполнения. Кроме того, в Triton отсутствует часть алгоритма SAGE [10],
предназначенная для уменьшения набора входных данных. Поэтому
инструмент неоднократно запускает анализируемую программы на входных
данных, которые не открывают новых путей. В описываемой работе в алгоритм
покрытия кода был добавлен новый функционал, который позволяет достичь
значительного роста производительности.
2.2 Модификация алгоритма покрытия
В оригинальной реализации алгоритма SAGE [10] в Triton после каждой
итерации программа всегда получала на вход последний элемент из списка
входных данных, не учитывая при этом количество открытых базовых блоков
программы с помощью данного элемента. Это приводило к тому, что вместе с
обработкой входных данных, которые имеют воздействие на покрытие кода
программы, рассматриваются и те входные данные, с помощью которых не
были открыты никакие новые пути в программе.
Поскольку в ходе работы алгоритма для каждого входного элемента
генерируются ее дочерние данные, количество элементов в списке входных
данных значительно увеличивается. Следовательно, для эффективного
выполнения алгоритма требуется определение приоритетов для
сгенерированных входных данных.
В предлагаемой модификации алгоритма каждому элементу из списка входных
данных мы присваиваем вес, который представляет из себя количество базовых
блоков программы, открытых этим элементом. В начале работы алгоритма
входным данным присваивается нулевой вес. Во время первой итерации
алгоритма подсчитываются весовые значения начальных входных данных.
После каждой итерации весовые значения обновляются следующим образом:
весовые значения уже рассмотренных элементов передаются их дочерним
элементам (входные данные, которые получились с помощью решения
логических уравнений). Таким образом, применяется иерархический обход
входных данных. Перед очередным запуском программы из списка выбирается
элемент с наибольшим весом. Это позволяет значительно упростить дерево
решений, как показано на рис. 4.
На рисунке видно, что после добавления весовых значений количество
рассматриваемых входных данных уменьшилось почти вдвое, что в свою
очередь приводит к существенному увеличению производительности работы
алгоритма (на некоторых тестах производительность выросла почти на 90%).
Еще одним недостатком Triton была поддержка программ, принимающих на
вход только аргументы командной строки. Для расширения набора
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
13
анализируемых программ нами была добавлена поддержка программ,
использующих файлы как источник входных данных. Кроме того, была
добавлена возможность определения конкретных диапазонов входных данных,
которые в ходе анализа будут помечены как символьные.
Описанный подход к подсчету весовых значений не является единственным
возможным, поэтому в дальнейших исследованиях будут рассматриваться и
другие варианты определения этих значений.
Рис. 4. Входные данные после каждой итерации алгоритма после добавления весов
Fig. 4. Input data after each iteration of the algorithm, after adding weight values
3. Поиск ошибок
Динамический анализ программы основан на исследовании программного
обеспечения в процессе выполнения. Это дает возможность исследования
программ с учетом определенных условий выполнения, а также позволяет
использовать конкретные значения указателей. Одним из недостатков
динамического анализа является требование наличия качественного покрытия
кода. Однако в большинстве случаев для найденных ошибок возможна
генерация входных данных, которые позволяют воспроизвести ошибку.
Ошибка UAF характеризуется возникновением двух последовательных
событий:
создание висящих указателей (dangling pointers);
доступ к памяти с использованием висящего указателя.
На рис. 5 приведён пример UAF. После проверки условия на строке 3
происходит освобождение памяти на который указывает переменная ptr (строка
4), затем управление переходит на строку 12, вследствие чего происходит
повторное освобождение памяти.
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
14
3.1 Алгоритм поиска ошибок в Triton
Используя инструментацию программы, алгоритм отслеживает функции
выделения (malloc) и освобождения (free) памяти. В начале работы алгоритма
создаются два множества (allocSET и freeSET) для отслеживания участков
памяти, которые были выделены и освобождены во время выполнения
программы. Элементами данных множеств являются парами, имеющие вид
адрес, размер»).
Каждый раз при вызове malloc/free множества allocSET и freeSET обновляются
путем добавления или удаления элементов с соответствующим адресом и
размером выделенной памяти. При вызове функции malloc новый элемент
адрес_2, размер_2») добавляется в множество allocSET и удаляется из
второго множества если данный элемент присутствует в множестве freeSET (т.е.
есть совпадение как по адресу, так и по размеру).
Рис. 5. Использование памяти после освобождения
Fog. 5. An example of UAF
Если данный элемент совпадает только по адресу, то перед обновлением
множеств, выполняются дополнительные действия для обработки значений
адреса и размера (если размер_2 < размер_1, то в freeSET добавляется элемент
«адрес_2 + размер_2, размер_1 - размер_2»). При вызове функции free
соответствующий элемент перемещается из множества allocSET в множество
freeSET.
Во время выполнения инструкций, осуществляющих доступ к памяти,
проверяется наличие указателя в обоих множествах. Ошибки UAF
фиксируются в двух случаях: элемент найден в множестве freeSET и его нет в
множестве allocSet; один и тот же элемент встречается в freeSET больше одного
раза. Работа алгоритма проиллюстрирована на рис. 6.
3.2 Предлагаемый метод
Для повышения эффективности поиска ошибок предлагается объединить два
вышеописанных алгоритма. Объединенный метод позволяет искать ошибки
UAF на разных путях программы, которые получаются из-за внедренных и
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
15
нетривиальных проверок в коде. На рис. 7 приведены примеры программ, на
которых обнаружение повторного освобождения памяти невозможно без
использования информации о покрытии кода (из-за присутствия условных
переходов, которые будут выполнены только при выполнении программы с
определенными входными данными).
Рис. 6. Пример работы алгоритма
Fig. 6. An example of operation of the algorithm
Рис. 7. Ошибки повторного освобождения памяти. Первый пример основан на ошибке
UAF в программе libssh. На первом примере ошибка может возникнуть на строке 26,
а на втором примере на строке 27
Fig. 7. Errors of double memory freeing. The first example is based on the UAF error in the
libssh program. In the first example, an error may occur on line 26, and in the second
example on line 27
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
16
Для примеров, приведенных на рис. 7, ошибка UAF произойдет, если
выполнение программ достигнет строк 21 и 23 для первой и второй программы
соответственно. Использование предлагаемого метода позволяет найти
входные данные для достижения нужного блока в коде (строки 20-21 и 22-23,
рис. 7) и потом проверить данную часть на наличие ошибок UAF.
3.3 Сравнение подходов динамического анализа
В табл. 1 подход, описываемый в данной статье, сравнивается в подходами,
применяемыми в Mayhem и Triton.
Табл. 1. Результаты сравнения
Table 1. Results of comparison
Предлагаемый
подход Mayhem Triton
UAF
Использование покрытия кода + + -
Офлайн-подход символьного
выполнения + + +
Онлайн-подход символьного
выполнения - + -
Приоритеты обрабатываемых
входных данных + + -
Поддержка файлов, в качестве
входных данных + + -
4. Результаты
Предлагаемый метод был протестирован на синтетических тестах, в том числе
и на приведённых примерах (рис. 1, 7), результаты тестирования приведены на
рис. 8. Данные результаты показывают, что на синтетических тестах, по
сравнению с реализацией Triton, производительность выросла примерно на
80%. Запуск анализа на реальных программах показал, что в большинстве
случаев количество символьных уравнений становится настолько большим, что
алгоритм покрытия кода Triton не может решить полученные уравнения для
всех путей.
Для проверки предложенного подхода нами были специально внесены ошибки
UAF в исходный код реальных проектов. Были исследованы проекты: gvgen из
пакета graphviz, jasper из пакета libjasper-runtime и gif2rgb из пакета giflib. На
данных проектах ошибки были найдены на различных уровнях встраивания. В
случае программы gvgen встраивание было выполнено за пределами одной
функции, максимальная глубина составляло три уровня (функции). Код
встраивания в данном случае представлял с собой условное выражение,
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
17
связанное с входными данными, и код самой ошибки. Выполнение этого
условия приводило к воспроизведению данной ошибки.
В проектах jasper и gif2rgb из-за сложности полученных символьных уравнений
встраивание было выполнено в пределах только одной функции. Код
встраивания был непосредственно кодом ошибки. Также были выделены
отдельные участки кода из реальных программ содержащие UAF на которых
данный подход смог найти соответствующие ошибки.
Рис. 8. Результаты сравнения относительно времени выполнения анализа
Fig. 8. Comparison results relative to the analysis execution time
5. Заключение
В статье представлен метод обнаружения ошибок UAF, возникающих при
неправильной обработке указателей на динамическую память. Метод
реализован с помощью инфраструктуры Triton [9] на базе алгоритма [10] и
алгоритма обнаружения ошибок UAF. После проведенных модификаций и
улучшений существующей реализации был получен прирост
производительности выполнения анализа.
Список литературы
[1]. D. Dewey, B. Reaves, P. Trainor. Uncovering Use-After-Free Conditions in Compiled
Code. In Proc of the 10th International Conference on Availability, Reliability and
Security (ARES), 2015, pp. 90-99
[2]. J. Feist, L. Mounier, ML. Potet. Statically detecting use after free on binary code. Journal
of Computer Virology and Hacking Techniques, vol. 10, issue 3, 2014, pp 211-217
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
18
[3]. И.К. Исаев, Д.В. Сидоров, А.Ю. Герасимов, М.К. Ермаков. Avalanche: Применение
динамического анализа для автоматического обнаружения ошибок в программах,
использующих сетевые сокеты. Труды ИСП РАН, том 21, 2011 г., стр. 55-70.
[4]. B. Lee, Ch. Song, Y. Jang, T. Wang. Preventing Use-after-free with Dangling Pointers
Nullification. In Proc of the Network and Distributed System Security Symposium, 2015,
https://www.ndss-symposium.org/ndss2015/ndss-2015-programme/preventing-use-after-
free-dangling-pointers-nullification/, дата обращения 05.05.2018
[5]. Yves Younan. FreeSentry: Protecting Against Use-After-Free Vulnerabilities Due to
Dangling Pointers. In Proc of the Network and Distributed System Security Symposium,
2015, https://www.ndss-symposium.org/ndss2015/ndss-2015-programme/freesentry-
protecting-against-use-after-free-vulnerabilities-due-dangling-pointers/, дата обращения
05.05.2018
[6]. J. Caballero, G. Grieco, M. Marron, A. Nappa. Undangle: Early Detection of Dangling
Pointers in Use-After-Free and Double-Free Vulnerabilities. In Proceedings of the 2012
International Symposium on Software Testing and Analysis, 2012, pp. 133-143
[7]. Sang Kil Cha, Thanassis Avgerinos, Alexandre Rebert and David Brumley. Unleashing
MAYHEM on Binary Code. In Proceedings of the 2012 IEEE Symposium on Security
and Privacy, 2012, pp. 380-394
[8]. Pin – A Dynamic Binary Instrumentation Tool, https://software.intel.com/en-
us/articles/pin-a-dynamic-binary-instrumentation-tool, дата обращения 05.05.2018
[9]. Triton – Dynamic Binary Analysis Framework, https://triton.quarkslab.com/, дата
обращения 05.05.2018
[10]. P. Godefroid, M. Y. Levin, D. Molnar. Automated Whitebox Fuzz Testing. In Proceedings
of NDSS'2008 (Network and Distributed Systems Security), 2008, pp. 151-166.
[11]. A. Aho, J. Ullman, R. Sethi, M. S. Lam. Compilers: Principles, Techniques, and Tools.
Addison Wesley; 2nd edition, September 10, 2006, 1000 p.
[12]. Leonardo de Moura, Nikolaj Bjørner. Z3: an efficient SMT solver. In Proceedings of the
14th international conference on Tools and algorithms for the construction and analysis
of systems, 2008, pp. 337-340
Асрян С.А., Гайсарян С.С., Курмангалеев Ш.Ф., Агабалян А.М., Овсепян Н.Г., Саргсян С.С. Обнаружение
ошибок, возникающих при использовании динамической памяти после освобождения. Труды ИСП РАН, том 30,
вып. 3, 2018 г., стр. 7-20
19
Dynamic Detection of Use After Free Bugs
2 S.A Asryan <asryan@ispras.ru>
1,3,5,6 S.S. Gaissaryan <ssg@ispras.ru>
1 Sh. F. Kurmangaleev <kursh@ispras.ru>
4A.М. Aghabalyan <anna.aghabalyan @ispras.ru>
4N.H. Hovsepyan <narekhnh@ispras.ru>
4S.S Sargsyan <sevaksargsyan@ispras.ru>
1 Ivannikov Institute for System Programming of RAS,
25, Alexander Solzhenitsyn str., Moscow, 109004, Russia
2Institute for Informatics and Automation Problems of NAS RA,
1, P. Sevak str., Yerevan, 0014, Republic of Armenia,
3 Lomonosov Moscow State University,
GSP-1, Leninskie Gory, Moscow, 119991, Russia
4Yerevan State University
1, Alex Manoogian str., Yerevan, 0025, Republic of Armenia
5 Moscow Institute of Physics and Technology (State University),
9 Institutskiy per., Dolgoprudny, Moscow Region, 141700, Russia
6 National Research University Higher School of Economics (HSE)
11 Myasnitskaya str., Moscow, 101000, Russia
Abstract. The article describes new method of use after free bug detection using program
dynamic analysis. In memory-unsafe programming languages such as C/C++ this class of bugs
mainly accurse when program tries to access specific area of dynamically allocated memory
that has been already freed. This method is based on combination of two basic components.
The first component tracks all memory operations through dynamic binary instrumentation and
searches for inappropriate memory access. It preserves two sets of memory address for all
allocation and free instructions. Using both sets this component checks whether current
memory is accessible through its address or it has been already freed. It is based on dynamic
symbolic execution and code coverage algorithm. It is used to maximize the number of
execution paths of the program. Using initial input, it starts symbolic execution of the target
program and gathers input constraints from conditional statements. The new inputs are
generated by systematically solving saved constraints using constraint solver and then sorted
by number of basic blocks they cover. Proposed method detects use after free bugs by applying
first component each time when second one was able to open new path of the program. It was
tested on our synthetic tests that were created based on well-known use after free bug patterns.
The method was also tested on couple of real projects by injecting bugs on different levels of
execution.
Keywords: program dynamic analysis; use after free bug; dynamic symbolic execution; code
coverage; instrumentation.
DOI: 10.15514/ISPRAS-2018-30(3)-1
Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh. F., Aghabalyan A.М., Hovsepyan N.H., Sargsyan S.S. Dynamic
detection of Use After Free bugs. Trudy ISP RAN/Proc. ISP RAS, vol. 30, issue 3, 2018, pp. 7-20
20
For citation: Asryan S.A., Gaissaryan S.S., Kurmangaleev Sh.F., Aghabalyan A.М.,
Hovsepyan N.H., Sargsyan S.S. Dynamic detection of Use After Free bugs. Trudy ISP
RAN/Proc. ISP RAS, vol. 30, issue 3, 2018. pp. 7-20 (in Russian). DOI: 10.15514/ISPRAS-
2018-30(3)-1
References
[1]. D. Dewey, B. Reaves, P. Trainor. Uncovering Use-After-Free Conditions in Compiled
Code. In Proc of the 10th International Conference on Availability, Reliability and
Security (ARES), 2015, pp. 90-99
[2]. J. Feist, L. Mounier, ML. Potet. Statically detecting use after free on binary code. Journal
of Computer Virology and Hacking Techniques, vol. 10, issue 3, 2014, pp 211-217
[3]. Ildar Isaev, Denis Sidorov, Alexander Gerasimov, Mikhail Ermakov. Avalanche: Using
dynamic analysis for automatic defect detection in programs based on network sockets.
Trudy ISP RAN/Proc. ISP RAS, vol. 21, 2011, pp. 55-70 (in Russian).
[4]. B. Lee, Ch. Song, Y. Jang, T. Wang. Preventing Use-after-free with Dangling Pointers
Nullification. In Proc of the Network and Distributed System Security Symposium, 2015,
https://www.ndss-symposium.org/ndss2015/ndss-2015-programme/preventing-use-after-
free-dangling-pointers-nullification/, accessed at 05.05.2018
[5]. Yves Younan. FreeSentry: Protecting Against Use-After-Free Vulnerabilities Due to
Dangling Pointers. In Proc of the Network and Distributed System Security Symposium,
2015, https://www.ndss-symposium.org/ndss2015/ndss-2015-programme/freesentry-
protecting-against-use-after-free-vulnerabilities-due-dangling-pointers/, accessed at
05.05.2018
[6]. J. Caballero, G. Grieco, M. Marron, A. Nappa. Undangle: Early Detection of Dangling
Pointers in Use-After-Free and Double-Free Vulnerabilities. In Proceedings of the 2012
International Symposium on Software Testing and Analysis, 2012, pp. 133-143
[7]. Sang Kil Cha, Thanassis Avgerinos, Alexandre Rebert and David Brumley. Unleashing
MAYHEM on Binary Code. In Proceedings of the 2012 IEEE Symposium on Security
and Privacy, 2012, pp. 380-394
[8]. Pin – A Dynamic Binary Instrumentation Tool, https://software.intel.com/en-
us/articles/pin-a-dynamic-binary-instrumentation-tool, accessed at 05.05.2018
[9]. Triton – Dynamic Binary Analysis Framework, https://triton.quarkslab.com/, accessed at
05.05.2018
[10]. P. Godefroid, M. Y. Levin, D. Molnar. Automated Whitebox Fuzz Testing. In Proceedings
of NDSS'2008 (Network and Distributed Systems Security), 2008, pp. 151-166.
[11]. A. Aho, J. Ullman, R. Sethi, M. S. Lam. Compilers: Principles, Techniques, and Tools.
Addison Wesley; 2nd edition, September 10, 2006, 1000 p.
[12]. Leonardo de Moura, Nikolaj Bjørner. Z3: an efficient SMT solver. In Proceedings of the
14th international conference on Tools and algorithms for the construction and analysis
of systems, 2008, pp. 337-340
Article
Full-text available
A novel method for detecting use-after-free bugs based on the program dynamic analysis is described. In memory unsafe programming languages, such as C or C++, this class of bugs mainly occurs when the program tries to access an area of dynamically allocated memory that has been already freed. For each program execution path, the method checks the correction of the allocation, deallocation, and access operations. Since the dynamic analysis is used, bugs can be found only in the parts of the code that was actually executed. The symbolic program execution with the help of SMT (Satisfiability Modulo Theories) solvers is used. This allows us to generate data the processing of which produces new execution paths.
Conference Paper
Full-text available
Many system components and network applications are written in languages that are prone to memory corruption vulnerabilities. There have been countless cases where simple mistakes by developers resulted in memory corruption vulnera-bilities and consequently security exploits. While there have been tremendous research efforts to mitigate these vulnerabilities, use-after-free still remains one of the most critical and popular attack vectors because existing proposals have not adequately addressed the challenging program analysis and runtime performance issues. In this paper we present DANGNULL, a system that detects temporal memory safety violations—in particular, use-after-free and double-free—during runtime. DANGNULL relies on the key observation that the root cause of these violations is that pointers are not nullified after the target object is freed. Based on this observation, DANGNULL automatically traces the object's relationships via pointers and automatically nullifies all pointers when the target object is freed. DANGNULL offers several benefits. First, DANGNULL addresses the root cause of temporal memory safety violations. It does not rely on the side effects of violations, which can vary and may be masked by attacks. Thus, DANGNULL is effective against even the most sophisticated exploitation techniques. Second, DANGNULL checks object relationship information using runtime object range analysis on pointers, and thus is able to keep track of pointer semantics more robustly even in complex and large scale software. Lastly, DANGNULL does not require numerous explicit sanity checks on memory accesses because it can detect a violation with implicit exception handling, and thus its detection capabilities only incur moderate performance overhead.
Article
Full-text available
We present GUEB a static tool detecting Use after Free vulnerabilities on disassembled code. This tool has been evaluated on a real vulnerability in the ProFTPD application (CVE-2011-4130).
Conference Paper
Full-text available
Satisfiability Modulo Theories (SMT) problem is a decision problem for logical first order formulas with respect to combinations of background theories such as: arithmetic, bit-vectors, arrays, and uninterpreted functions. Z3 is a new and efficient SMT Solver freely available from Microsoft Research. It is used in various software verification and analysis applications.
Conference Paper
Full-text available
Fuzz testing is an effective technique for finding security vulnerabilities in software. Traditionally, fuzz testing tools apply random mutations to well-formed inputs of a pro- gram and test the resulting values. We present an alterna- tive whitebox fuzz testing approach inspired by recent ad- vances in symbolic execution and dynamic test generation. Our approach records an actual run of the program un- der test on a well-formed input, symbolically evaluates the recorded trace, and gathers constraints on inputs capturing how the program uses these. The collected constraints are then negated one by one and solved with a constraint solver, producing new inputs that exercise different control paths in the program. This process is repeated with the help of a code-coverage maximizing heuristic designed tofind defects as fast as possible. We have implemented this algorithm in SAGE (Scalable, Automated, Guided Execution), a new tool employing x86 instruction-level tracing and emulation for whitebox fuzzing of arbitrary file-reading Windows ap- plications. We describe key optimizations needed to make dynamic test generation scale to large input files and long execution traces with hundreds of millions of instructions. We then present detailed experiments with several Windows applications. Notably, without any format-specific knowl- edge, SAGE detects the MS07-017 ANI vulnerability, which was missed by extensive blackbox fuzzing and static analy- sis tools. Furthermore, while still in an early stage of de- velopment, SAGE has already discovered 30+ new bugs in large shipped Windows applications including image pro- cessors, media players, and file decoders. Several of these bugs are potentially exploitable memory access violations.
Conference Paper
Use-after-free conditions occur when an execution path of a process accesses an incorrectly deal located object. Such access is problematic because it may potentially allow for the execution of arbitrary code by an adversary. However, while increasingly common, such flaws are rarely detected by compilers in even the most obvious instances. In this paper, we design and implement a static analysis method for the detection of use-after-free conditions in binary code. Our new analysis is similar to available expression analysis and traverses all code paths to ensure that every object is defined before each use. Failure to achieve this property indicates that an object is improperly freed and potentially vulnerable to compromise. After discussing the details of our algorithm, we implement a tool and run it against a set of enterprise-grade, publicly available binaries. We show that our tool can not only catch textbook and recently released in-situ examples of this flaw, but that it has also identified 127 additional use-after-free conditions in a search of 652 compiled binaries in the Windows system32 directory. In so doing, we demonstrate not only the power of this approach in combating this increasingly common vulnerability, but also the ability to identify such problems in software for which the source code is not necessarily publicly available.
Avalanche: Применение динамического анализа для автоматического обнаружения ошибок в программах, использующих сетевые сокеты. Труды ИСП РАН, том 21
  • И К Исаев
  • Д В Сидоров
  • А Ю Герасимов
  • М К Ермаков
И.К. Исаев, Д.В. Сидоров, А.Ю. Герасимов, М.К. Ермаков. Avalanche: Применение динамического анализа для автоматического обнаружения ошибок в программах, использующих сетевые сокеты. Труды ИСП РАН, том 21, 2011 г., стр. 55-70.
Undangle: Early Detection of Dangling Pointers in Use-After-Free and Double-Free Vulnerabilities
  • J Caballero
  • G Grieco
  • M Marron
  • A Nappa
J. Caballero, G. Grieco, M. Marron, A. Nappa. Undangle: Early Detection of Dangling Pointers in Use-After-Free and Double-Free Vulnerabilities. In Proceedings of the 2012 International Symposium on Software Testing and Analysis, 2012, pp. 133-143
Unleashing MAYHEM on Binary Code
  • Thanassis Sang Kil Cha
  • Alexandre Avgerinos
  • David Rebert
  • Brumley
Sang Kil Cha, Thanassis Avgerinos, Alexandre Rebert and David Brumley. Unleashing MAYHEM on Binary Code. In Proceedings of the 2012 IEEE Symposium on Security and Privacy, 2012, pp. 380-394