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

Анализ данных машинного кода компиляторов при выполнении сборки программы в различных режимах. Анализ особенностей машинного кода, генерируемого различными компиляторами для Windows и Linux в режимах Debug и Release, обзор уязвимости переполнения буфера.

Рубрика Программирование, компьютеры и кибернетика
Вид статья
Язык русский
Дата добавления 08.03.2019
Размер файла 511,2 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

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

Ревнивых Александр Владимирович

кандидат технических наук 

доцент, кафедра Информационной

безопасности, ФГБОУ ВО

«Новосибирский государственный

университет экономики и управления «НИНХ» 

Велижанин Анатолий Сергеевич

Аннотация

уязвимость буфер windows linux

Предметом исследования является потенциальная уязвимость, в частности на переполнение буфера, в различном программном обеспечении, связанная с функцией стандартной библиотеки языка программирования С/С++ strcpy и подходы и методы поиска таковой уязвимости. Объектом исследования выступают данные машинного кода компиляторов при выполнении сборки программы в различных режимах.Целью исследования является провести анализ некоторых особенностей машинного кода, генерируемого различными компиляторами для Windows и Linux в режимах Debug и Release, в том числе, проведя на основе этого обзор уязвимости переполнения буфера. Методы исследования. В работе рассматриваются и развиваются методы построения алгоритмов поиска уязвимости переполнения буфера, исследуются характеристики данной уязвимости на уровне машинного кода. Для этого используются компиляторы Visual C++, Intel C++, g++, а также отладчики WinDBG, GDB. Ключевые выводы. Сборка программ в различных режимах приводит к формированию различий в исполняемом коде, который сделан из полностью одного и того же кода языка программирования высокого уровня; эти различия проявляются в отличиях в поведении программы. В ходе исследования программного обеспечения в поисках уязвимостей важно проводить анализ машинного кода с целью выявления скрытых закономерностей.Новизна исследования заключается в выявлении отличий в машинном коде, полученном после сборки одинакового высокоуровневого кода, определении «штампов» компиляторов при выполнении сборки программы в различных режимах. Особым вкладом автора в исследование темы является развитие методов построения алгоритмов поиска уязвимости переполнения буфера.

Ключевые слова: Информационная безопасность, Уязвимости, Анализ кода, Дизассемблирование, Переполнение буфера, Штампы компиляторов, Режим Debug, Режим Release, Методы построения алгоритмов, отладчик WinDBG

Abstract

The subject of the study is a potential buffer overflow vulnerability in various software related to the function of the standard C / C ++ strcpy programming language library and approaches and methods for finding such vulnerabilities. The object of the study is the data of the machine code of the compilers when the program is assembled in various modes. The purpose of the study is to analyze some features of the machine code generated by various compilers for Windows and Linux in the Debug and Release modes, including, on the basis of this, a review of the buffer overflow vulnerability. Research methods. The paper reviews and develops methods for constructing algorithms for searching for buffer overflow vulnerabilities, examines the characteristics of this vulnerability at the level of machine code. This is done using the Visual C ++ compilers, Intel C ++ compilers, g ++ compilers, as well as the WinDBG, GDB debuggers. Key findings. Building programs in different modes leads to the formation of differences in the executable code, which is made from the completely same high-level programming language code; these differences manifest themselves in differences in program behavior. In the course of researching software in search of vulnerabilities, it is important to analyze computer code in order to identify hidden patterns. The novelty of the study lies in identifying differences in the machine code obtained after assembling the same high-level code, identifying compiler stamps when executing the assembly of the program in different modes. A special contribution of the author to the study of the topic is the development of methods for constructing algorithms for searching for buffer overflow vulnerabilities. 

Keywords: Debug mode, Compiler stamps, Buffer overflow, Disassembling, Code analysis, Vulnerabilities, Information security, Release mode, Algorithm construction methods, WinDBG debugger 

Введение

Современное программное обеспечение является сложной гетерогенной системой. В связи с всё более возрастающей объёмностью и сложностью программной инфраструктуры компьютерных систем, все большую актуальность приобретают исследования, направленные на поиск уязвимостей в программном обеспечении [1, 6]. Разнообразие типов программных решений и из базовых компонентов приводит к значительным различиям в подходах и методах поиска уязвимостей. Так, некоторые уязвимости характерны по большей части для Web-приложений, в то время как другие - для Desktop-решений. Тем не менее, взаимная интеграция программных систем, вероятно, приводит к миграции некоторых уязвимостей из одного программного компонента в другой [2].

В настоящее время, несмотря на стремительное развитие Web-технологий, значительное количество программного обеспечения разрабатывается в виде Desktop-решений на различных языках программирования. К ним относятся и компилируемые под определенную платформу языки программирования (такие, как C/C++), так и языки программирования с JIT-компиляцией (например, C#). К сожалению, методы поиска уязвимостей в Native-программном обеспечении часто сводятся к «ручному» поиску, где эксперт вынужден проводить анализ самостоятельно, применяя вспомогательные средства для выполнения базовых задач.

Эффективность автоматизированных систем, реализующих метод «Fuzzing», к сожалению, в общем случае ограничивается набором входных данных. Исследования дизассемблированного представления некоторых типов уязвимостей способствуют развитию методов поиска уязвимостей в программном обеспечении без использования исходных кодов. Несомненно, в современных информационных системах имеется множество различных типов уязвимостей и формирование алгоритма максимально подходящего под каждый из этих типов, вероятно, является неэффективным. [7-21] В связи с этим, для начала мы рассмотрим определённый тип уязвимости и исследуем его характеристики на уровне машинного кода.

Уязвимость переполнения буфера, некоторые особенности кода, генерируемого различными компиляторами

В качестве одного из типов уязвимости рассмотрим переполнение буфера. Переполнение буфера (Buffer Overflow) - явление, возникающее, когда компьютерная программа записывает данные за пределами выделенного в памяти буфера [3]. Следует отметить, что в настоящее время имеется множество технологий защиты от некоторых последствий данного вида атак. В частности, технологии ASLR, DEP и некоторые другие направлены на предотвращение выполнения кода злоумышленника на уязвимой системе. Однако такая защита является лишь частичной, поскольку имеются методики, позволяющие обойти данные виды защиты, а так же ни ASLR, ни DEP, вероятно, не защитят от атаки типа DoS, когда выполнение кода злоумышленника будет предотвращено, но, например, стек программы окажется не корректным, что может привести к невозможности дальнейшего функционирования уязвимого программного обеспечения или его компонента.

Рассмотрим несколько примеров, содержащих уязвимость данного типа. Наиболее простой пример на языке программирования С/С++ изложен в листинге 1.

Листинг 1. Простейший пример уязвимого кода на С/С++.

01: #include <stdio.h>

02: #include <string.h>

03:

04: #define ARRAY_SIZE 10

05:

06: int main(int argc, char *argv[])

07: {

08: char arr[ARRAY_SIZE];

09: if(argc < 2)

10: return -1;

11: else

12: {

13: strcpy(arr, argv[1]);

14: return 0;

15: }

16: }

Создадим приложение типа «Empty project» на С/С++ в среде Visual Studio 2010. Создание именно данного типа проекта необходимо для минимизации встраивания дополнительного кода на С/С++, генерируемого средой Visual Studio 2010, в проект, а также минимизации встраивания в результирующий машинный код дополнительных вызовов. Это даст возможность минимизировать объём результирующего исполняемого файла и увеличить наглядность данного примера. Затем добавим файл с исходным кодом из листинга 1. Данный пример имеет простейшую уязвимость переполнения буфера в строке 13. Рассмотрим дизассемблированное представление наиболее важных участков данного кода в стандартном режиме компиляции Debug x32 (Листинг 2.).

Листинг 2.

. . .(код вырезан) . . .

13: strcpy(arr, argv[1]);

008913E5 8B 45 0C mov eax,dword ptr [ebp+0Ch]

008913E8 8B 48 04 mov ecx,dword ptr [eax+4]

008913EB 51 push ecx

008913EC 8D 55 EC lea edx,[ebp-14h]

008913EF 52 push edx

008913F0 E8 AB FC FF FF call @ILT+155(_strcpy) (8910A0h)

. . .(код вырезан) . . .

Из данного листинга можно сделать вывод о передаче 2-ух параметров через стек, которые были сохранены из регистров процессора ecx и edx. Рассмотрим аналогичный код для платформы x64 (Листинг 3).

Листинг 3.

. . .(код вырезан) . . .

13: strcpy(arr, argv[1]);

000000013FD01050 48 8B 44 24 78 mov rax,qword ptr [rsp+78h]

000000013FD01055 48 8B 50 08 mov rdx,qword ptr [rax+8]

000000013FD01059 48 8D 4C 24 28 lea rcx,[rsp+28h]

000000013FD0105E E8 85 01 00 00 call strcpy (13FD011E8h)

. . .(код вырезан) . . .

В данной архитектуре происходит несколько другой способ передачи параметров в вызываемую функцию. Так, в примере из листинга 3 регистр rdx указывает на копируемую строку, а rcx на буфер, куда будет произведено копирование. Подробнее о соглашениях вызова и программировании на языке Assember для x86_64 можно прочитать в [4], а также в официальной документации на сайте производителя процессора [5].

В результате запуска программы из листинга 1, собранной в режиме Debug x32, с аргументом командной строки длиной 20 символов, мы получаем ошибку, изображенную на рис. 1. Аналогичное поведение мы имеем для Debug x64. Таким образом мы видим работу стандартного встроенного средства проверки, добавленного компилятором Microsoft Visual C++ 2010 в приложения, собранные в режиме Debug. Некоторую часть реализации механизмов защиты мы можем увидеть в листинге 4. При еще более длинном аргументе (скажем, 2000 символов) возникает необрабатываемое исключение вызывающее крах программы, изображенное на рис. 2.

Вкратце рассмотрим отрывок дизассемблированного кода приложения, собранного в режиме Debug x32 (Листинг 4).

Листинг 4.

. . .(код вырезан) . . .

13 012013f0 e8abfcffff call exp_1!ILT+155(_strcpy) (012010a0)

13 012013f5 83c408 add esp,8

14 012013f8 33c0 xor eax,eax

exp_1!main+0x4a [c:usersanatoliydocumentsvisual studio 2010projectsexp_1exp_1main.cpp @ 16]:

16 012013fa 52 push edx

16 012013fb 8bcd mov ecx,ebp

16 012013fd 50 push eax

16 012013fe 8d152c142001 lea edx,[exp_1!main+0x7c (0120142c)]

16 01201404 e879fcffff call exp_1!ILT+125(_RTC_CheckStackVars (01201082)

16 01201409 58 pop eax

16 0120140a 5a pop edx

16 0120140b 5f pop edi

16 0120140c 5e pop esi

16 0120140d 5b pop ebx

16 0120140e 8b4dfc mov ecx,dword ptr [ebp-4]

16 01201411 33cd xor ecx,ebp

16 01201413 e8fcfbffff call exp_1!ILT+15(__security_check_cookie (01201014)

16 01201418 81c4d8000000 add esp,0D8h

16 0120141e 3bec cmp ebp,esp

16 01201420 e811fdffff call exp_1!ILT+305(__RTC_CheckEsp) (01201136)

16 01201425 8be5 mov esp,ebp

16 01201427 5d pop ebp

16 01201428 c3 ret

. . .(код вырезан) . . .

Похожий код (по большому счету основная разницы с х32 кодом лишь в соглашениях вызова и некоторых других деталях) мы можем увидеть при отладке Debug x64. Пример приведен в листинге 5.

Листинг 5.

. . .(код вырезан) . . .

13 000000013f9f11e8)

14 00000001

exp_1!main+0x55 [c:usersanatoliydocumentsvisual studio 2010projectsexp_1exp_1main.cpp @ 16]:

16 00000001

16 00000001

16 000000013f9f67e0)]

16 000000013f9f1220)

16 00000001

16 00000001

16 00000001

16 000000013f9f1200)

16 00000001

16 00000001

16 00000001

. . .(код вырезан) . . .

В коде из листинга 5 мы так же видим наличие защитных средств, предназначенных для контроля целостности стека.

В листинге 6 приведен пример отладки в WinDBG программы, собранной в режиме Debug х64. В данном случае отладчик сообщает нам о переполнении буфера. Аналогичный результат мы получаем при эксперименте со сборкой Debug x32. Далее отдельные примеры листингов для x32 приводить не будем.

Листинг 6.

Breakpoint 0 hit

exp_1!main:

000000010027f878={exp_1!__xc_z (00000001

0:000> g

Breakpoint 1 hit

exp_1!main+0x62:

000000013f9f1220)

0:000> p

WARNING: This break is not a step/trace completion.

The last command has been cleared to prevent

accidental continuation of this unrelated event.

Check the event, location and thread before resuming.

(1230.1200): Break instruction exception - code 80000003 (first chance)

exp_1!failwithmessage+0x228:

00000001

0:000> g

Breakpoint 2 hit

exp_1!main+0x72:

000000013f9f1200)

0:000> p

STATUS_STACK_BUFFER_OVERRUN encountered

WARNING: This break is not a step/trace completion.

The last command has been cleared to prevent

accidental continuation of this unrelated event.

Check the event, location and thread before resuming.

(1230.1200): Break instruction exception - code 80000003 (first chance)

kernel32!UnhandledExceptionFilter+0x71:

00000000

Таким образом, мы видим, что переполненный буфер был обнаружен с помощью встроенных в исполняемый файл средой Visual Studio 2010 функций, а отладчик WinDBG выдал информацию о соответствующей ошибке.

Теперь рассмотрим дизассемблированный листинг Release х64 версии исследуемого ПО. Пример изображен в листинге 7.

Листинг 7.

. . .(код вырезан) . . .

13 00000001

exp_1!main+0x31 [c:usersanatoliydocumentsvisual studio 2010projectsexp_1exp_1main.cpp @ 13]:

13 00000001

13 00000001

13 00000001

13 000000013fd11031)

. . .(код вырезан) . . .

Обратим внимание, что в приведенном листинге 7 отсутствует непосредственный вызов функций strcpy. Он заменен последовательностью команд по адресам 000000013fd11039, которые производят копирование строки, заменяя собой функционал стандартной функции strcpy. В листинге 8 приведен пример отладки программы, аналогичный листингу 6, но для Release сборки.

Листинг 8.

Breakpoint 0 hit

exp_1!main:

00000001

0:000> p

exp_1!main+0x13:

00000001

0:000> g

Breakpoint 1 hit

exp_1!main+0x2d:

00000001000d2408=00000000000d246c

0:000> g

Breakpoint 2 hit

exp_1!main+0x45:

000000013fd11060)

0:000> g

Breakpoint 3 hit

exp_1!main+0x4e:

00000001

Рис. 1. Исключение, вызванное переполнением буфера строкой 20 символов для Debug сборки

Рис. 2. Исключение, вызванное переполнением буфера, длиной 2000 символов для Debug сборки

Таким образом, при сборке проекта в режиме Release, наблюдается несколько иная ситуация. Сообщение из рис. 1 не появляется. Отметим, что на рис. 2. выделено значение Exception Offset равное 61616161. Обратим внимание, что строка, вызвавшая переполнение, состояла из множества символов «a», а 61 является шестнадцатеричным представлением данного символа. Это является классическим переполнением буфера, когда адрес возврата из функции был перезаписан данными, отправленными злоумышленником в систему. Отсутствие многих защитных механизмов, которые мы могли увидеть в листингах для Debug сборок можно объяснить тем, что тип сборки Release предназначен для распространения приложения, а значит такая сборка должна обладать наибольшей производительностью, что требует оптимизацией кода в том числе за счет уменьшения количества встраиваемых компилятором проверок вплоть до полного их исключения.

Сравнив особенности переполнения для Debug и Release сборок приложений, скомпилированных с помощью Microsoft Visual C++ 2010, можем отметить, что для успешного использования уязвимостей необходимо учитывать тип сборки проекта . Кроме того, некоторые функции могут быть развернуты компилятором в собираемый модуль. Так, например, функция стандартной библиотеки strcpy была развернута в последовательность команд по адресам 000000013fd11039 из листинга 7. Данный факт показывает необходимость разработки средств для автоматизированной идентификации подобных встроенных функций. Похожее развертывание может быть следствием статической линковки отдельных или всех библиотек к исполняемому файлу.

Рассмотрим результаты экспериментов, проведенных с использованием компилятора Intel C++, входящего в стандартную поставку Intel Parallel Studio XE. Данный программный продукт совместим с Microsoft Visual Studio 2005-2010, а так же имеет встроенные средства интеграции. Для начала приведем пример дизассемблированного в WinDBG листинга части функции main, собранного из среды Visual Studio 2010 компилятором C++ от Intel (Листинг 9).

Листинг 9.

. . .(код вырезан) . . .

13 000000013f8c1360)

13 00000001

14 00000001

14 00000001

14 00000001

. . .(код вырезан) . . .

Сравним листинг, полученный при дизассемблировании части функции «main» в диапазоне от функции «strcpy» до конца функции «main» файла, собранного при помощи компилятора Intel C++ Debug x64 в среде Visual Studio 2010, и соответствующую часть листинга, полученную после дизассемблирования аналогичной функции файла, собранного компилятором Visual C++ Debug x64. Первое, что бросается в глаза - небольшая разница в объеме кода, что может объяснять и несколько разный объем, занимаемый на жестком диске исполняемыми файлами, полученными в результате компиляции. Сравнив полный код функции «main», разница в объеме будет заметна сильнее.

Однако, сравнивая листинги, мы можем также заметить различные способы выполнения некоторых действий. Так, например, в листинге 9, полученном при сборке программы компилятором от Intel, мы можем наблюдать обнуление регистра процессора eax, прямой записью в него нулевого значения в строке по адресу 000000013f9f1063. Кроме того, в компиляторе Visual C++ обращение к стековым переменным происходит через регистр rdi, в то время как Intel C++ для данной операции использует смещения от регистра rbp. Для большей ясности приведем отрывок дизассемблированного листинга (листинг 10) функции «main», где происходит формирование значения регистра rdi (компилятор Microsoft Visual C++).

Листинг 10.

. . .(код вырезан) . . .

7 00000001

7 00000001

7 00000001

7 00000001

7 00000001

. . .(код вырезан) . . .

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

В листинге 10 было показано начало функции «main» для компилятора от Microsoft. Приведем аналогичный участок кода для компилятора от Intel в листинге 11.

Листинг 11.

. . .(код вырезан) . . .

7 00000001

7 00000001

. . .(код вырезан) . . .

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

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

Вернемся к рассмотрению уязвимости, вызванной использованием функции «strcpy». Рассмотрим ситуацию с компилятором g++ 4.6.3 в Linux. В наших экспериментах будет использоваться дистрибутив Ubuntu 12.04. В качестве отладчика будем использовать GDB 7.4-2012.04. NetBeans 7.2 возьмем как интегрированную среду разработки. Создадим проект типа C/C++ Application. Интегрированная среда разработки автоматически сгенерирует Makefile. Проведем сборку проекта в стандартных конфигурациях Debug и Release. NetBeans сохранит результирующие исполняемые файлы в каталог ./dist/Debug/GNU-Linux-x86/. Проверим, что мы получили файлы для х64 (Листинг 12).

Листинг 12.

anatoliy@QRt62Mto7:~/Documents/NetBeansProjects/exp_1$ file ./dist/Debug/GNU-Linux-x86/exp_1

./dist/Debug/GNU-Linux-x86/exp_1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x55aba3afa1735b359b250309a5da228d28378e1b, not stripped

anatoliy@QRt62Mto7:~$ file ./Documents/NetBeansProjects/exp_1/dist/Release/GNU-Linux-x86/exp_1

./Documents/NetBeansProjects/exp_1/dist/Release/GNU-Linux-x86/exp_1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x39db2aecacbf46f59a4cfdf672804c1ca7431452, not stripped

anatoliy@QRt62Mto7:~$

Аналогичную проверку можно провести и для Release версии сборки. Посмотрим на дизассемблированный в отладчике GDB код функции main (Листинг 13).

Листинг 13.

. . .(код вырезан) . . .

0x000000000040058f <+43>: mov rax,QWORD PTR [rbp-0x30]

0x0000000000400593 <+47>: add rax,0x8

0x0000000000400597 <+51>: mov rdx,QWORD PTR [rax]

0x000000000040059a <+54>: lea rax,[rbp-0x20]

0x000000000040059e <+58>: mov rsi,rdx

0x00000000004005a1 <+61>: mov rdi,rax

0x00000000004005a4 <+64>: call 0x400450 <strcpy@plt>

0x00000000004005a9 <+69>: mov eax,0x0

. . .(код вырезан) . . .

Вызов уязвимой функции происходит по адресу 0x00000000004005a4. Регистр rsi в строке по адресу 0x000000000040059e получает значение, принятое в качестве параметра функцией main и являющееся буфером-источником по отношению к функции strcpy. В регистр rdi командой по адресу 0x00000000004005a1 заносится адрес буфера-назначения. Так же обратим внимание на несколько многоступенчатое формирование адреса в регистре rdi.

Запустим программу, собранную в режиме Debug x64, передав в качестве параметра строку, размер которой значительно превышает объем буфера-приемника (Листинг 14).

Листинг 14.

anatoliy@QRt62Mto7:~/Documents/NetBeansProjects/exp_1$ ./dist/Debug/GNU-Linux-x86/exp_1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

*** stack smashing detected ***: ./dist/Debug/GNU-Linux-x86/exp_1 terminated

Segmentation fault (core dumped)

anatoliy@QRt62Mto7:~/Documents/NetBeansProjects/exp_1$

Как мы видим, программа завершила свою работу с фатальной ошибкой, и был создан аварийный дамп. Отметим, что подобные дампы эффективно используются для поиска причины аварийного завершения работы приложения, как для программ пользовательского уровня, так и для отладки кода ядра операционной системы. Для операционной системы Linux подобные дампы памяти можно рассматривать с использованием отладчика GBD, а в Windows это может быть, например, WinDBG.

Для сравнения в листинге 15 приведен код дизассемблированной функции «main» сборки типа Release x64 в отладчике GDB.

Листинг 15.

Dump of assembler code for function main:

. . .(код вырезан) . . .

0x00000000004004be <+30>: mov rsi,QWORD PTR [rsi+0x8]

0x00000000004004c2 <+34>: mov edx,0xa

0x00000000004004c7 <+39>: mov rdi,rsp

0x00000000004004ca <+42>: call 0x400490 <__strcpy_chk@plt>

0x00000000004004cf <+47>: xor eax,eax

. . .(код вырезан) . . .

В данном листинге мы можем отметить разницу в объеме кода. Наиболее интересным является факт, что непосредственно до вызова (когда параметры для вызова функции копирования уже помещены в регистры rsi и rdi), значения этих регистров приведены в листинге 16.

Листинг 16.

(gdb) x $rsi

0x7fffffffe451: "AAAAA"

(gdb) x $rdi

0x7fffffffe040: ""

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

Листинг 17.

(gdb) x $rsi

0x7fffffffe456: ""

(gdb) x $rdi

0x7fffffffe045: ""

Рассмотрев листинги 16 и 17, мы можем заметить, что регистры rsi и rdi начали указывать на другие адреса памяти, с чем связан и вывод команд из листинга 17. Указав же команде «х» отладчика GDB в качестве адресов в памяти предыдущие (уменьшив текущие значения регистров на 5 байт, что соответствовало количеству символов в строке, указанной в качестве входного параметра запускаемой программе), мы получим, как и следовало ожидать, результат из листинга 18.

Листинг 18.

(gdb) x $rsi-0x5

0x7fffffffe451: "AAAAA"

(gdb) x $rdi-0x5

0x7fffffffe040: "AAAAA"

Как мы видим, произошло копирование строки, но регистры rsi и rdi поменяли хранимые в них значения внутри функции <__strcpy_chk@plt>, вызываемой по адресу 0x00000000004004ca в листинге 15. Такое поведение показывает, что содержимое некоторых регистров может быть модифицировано в вызываемой функции, что приводит к сохранению модифицированного результата непосредственно после вызова.

Так же отметим, что регистры, через которые производится передача параметров, могут быть несколько отличными. Так, например, в Windows параметры обычно передавались через регистры rcx, rdx, а в экспериментах с Linux передача производилась через rsi, rdi. В общем случае данное различие не является критичным.

Заключение

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

Отметим, что возникновение подобной уязвимости может быть вызвано не только непосредственно копированием строки с выходом за границу буфера-приёмника. Уязвимость на переполнение может являться следствием вполне корректной по объему записи. Например, записав полностью весь объем буфера-приёмника, но, не установив в конце завершающий нуль-символ, мы можем получить переполнение при чтении данного буфера функциями, ожидающими в конце строки обнаружить завершающий нуль символ. Т. о. переполнение в данном случае при записи не возникает, а вот некоторые функции чтения будут продолжать считывать данные до тех пор, пока не встретят признак завершения конца строки в виде кода «». Прочитав лишние данные, они будут направлены на дальнейшую обработку, что в некоторых случаях может быть использовано злоумышленником или попросту привести к сбою или аварийному завершению работы системы.

Результирующий машинный код для сборок режима Debug и Release может иметь в значительной степени различную структуру. В частности, Release сборки при компиляции Visual C++ 2010 не содержат многих защитных механизмов. Это так же является причиной, обосновывающей необходимость учитывать тип сборки при эксплуатации уязвимостей. Кроме того, в ходе компиляции некоторые функции могут быть развернуты компилятором в соответствующий программный код. Отличия особенностей дизассемблированного представления кода, собранного различными компиляторами, формируют предположение о возможности определить тип используемого при сборке какой-либо программы компилятора интеллектуально, основываясь на структуре кода и других отличительных особенностях дизассемблированного представления бинарного файла. Помимо прочего, исходные коды исследуемых на уязвимости программных решений доступны не всегда. В совокупности с выявленными различиями, в результирующем машинном коде в зависимости от режима компиляции это обосновывает необходимость развития средств поиска уязвимостей в программном обеспечении без использования исходного кода. Также, из изложенного материала видно, что реакция на возникновения ошибки (согласно предложенным примерам, на переполнение буфера) может так же быть разнообразной. Этот факт может послужить причиной, которая не позволит обнаружить наличие ошибки в минимальные сроки; и это подтверждает необходимость проведения качественного статического анализа дизассемблированных листингов перед началом динамического анализа.

Библиография

1. Муханова А. А., Ревнивых А. В., Федотов А. М. Классификация угроз и уязвимостей информационной безопасности в корпоративных системах // Вестник НГУ. Сер.: Информационные технологии. - 2013. - Т. 11. - №

2. --С. 55-72. - ISSN 1818-7900. 2.Велижанин А. С., Ревнивых А. В. Эвристический метод поиска уязвимостей в ПО без использования исходного кода // XIV Российская конференция с международным участием "Распределенные информационные и вычислительные ресурсы" (DICR-2012). - ISBN 978-5-905569-05-0.

3. Википедия. Переполнение буфера [Электронный ресурс] URL: http://en.wikipedia.org/wiki/Переполнение_буфера

4. Аблязов Р. З. Программирование на ассемблере на платформе х86_64. Учеб. пособие / Р. З. Аблязов. - Москва: ДМК Пресс, 2011. - 305 c. - ISBN: 978-5-94074-676-8

5. Официальный сайт компании Intel. [Электронный ресурс] URL: www.intel.com

6. Ревнивых А. В., Федотов А. М. Мониторинг информационной инфраструктуры организации // Вестник НГУ. Сер.: Информационные технологии. - 2013. - Т. 11. - № 4. - С. 84-91. - URL: https://nsu.ru/xmlui/bitstream/handle/nsu/1295/2013_V11_N4_8.pdf.

7. Воропаев Д. П., Зауголков И. А. Исследование программных уязвимостей в компьютерных системах и анализ применяемого программного обеспечения для проведения атак на вычислительную систему // Вестник Тамбовского университета. Серия: Естественные и технические науки. - 2014. - Т. 19. - № 2. - С. 637-638. - ISSN 1810-0198. -URL: https://cyberleninka.ru/article/v/issledovanie-programmnyh-uyazvimostey-v-kompyuternyh-sistemah-i-analiz-primenyaemogo-programmnogo-obespecheniya-dlya-provedeniya-atak

8. Нурмухаметов А. Р., Курмангалеев Ш. Ф., Каушан В. В., Гайсарян С. С. Применение компиляторных преобразований для противодействия эксплуатации уязвимостей программного обеспечения // Труды института системного программирования РАН. - 2014. - Т. 26. - № 3. - С. 113-124. - ISSN 2079-8156.

9. Федотов А. Н. Метод оценки эксплуатируемости программных дефектов // Труды института системного программирования РАН. - 2016. - Т. 28. - № 4. - С. 137-148. - DOI: 10.15514/ISPRAS-2016-28(4)-8.

10. Федотов А. Н., Каушан В. В., Гайсарян С. С., Курмангалеев Ш. Ф. Построение предикатов безопасности для некоторых типов программных дефектов // Труды института системного программирования РАН. - 2017. - Т. 29. - № 6. - С. 151-162. - DOI: 10.15514/ISPRAS-2017-29(6)-8.

11. Шудрак М. О., Хеирхабаров Т. С. Автоматизированный поиск уязвимостей в бинарном коде // Решетневские чтения. Сибирский государственный аэрокосмический университет им. акад. М. Ф. Решетнева. - 2012. -Т. 16. - № 2. - С. 691-692.

12. Вахрушев И. А., Каушан В. В., Падарян В. А., Федотов А. Н. Метод поиска уязвимости форматной строки // Труды института системного программирования РАН. - 2015 - Т. 27. - № 4. - С. 23-34. - ISSN 2079-8156. - DOI: 10.15514/ISPRAS-2015-27(4)-2

13. Падарян В. А., Каушан В. В., Федотов А. Н. Автоматизированный метод построения эксплойтов для уязвимости переполнения буфера на стеке // Труды института системного программирования РАН. - 2014. - Т. 26. - № 6. - С. 127-144. - ISSN 2079-8156.

14. Нурмухаметов А. Р., Жаботинский Е. А., Курмангалеев Ш. Ф., Гайсарян С. С., Вишняков А. В. Мелкогранулярная рандомизация адресного пространства программы при запуске // Труды института системного программирования РАН. - 2014. - Т. 29. - № 6. - С. 163-182. - ISSN 2079-8156.

15. Федотов А. Н., Падарян В. А., Каушан В. В., Курмангалеев Ш. Ф., Вишняков А. В., Нурмухаметов А. Р. Оценка критичности программных дефектов в условиях работы современных защитных механизмов // Труды института системного программирования РАН. - 2016. - Т. 28. - № 5. - С. 73-92. - DOI: 10.15514/ISPRAS-2016-28(5)-4.

16. Надеждин Е. Н., Щипцова Е. И., Шершакова Т. Л. Анализ уязвимостей программного обеспечения при проектировании механизма интегрированной защиты корпоративной информационной системы // Современные наукоёмкие технологии. - 2017. - № 10. - С. 32-38. - ISSN 1812-7320. - URL: http://www.top-technologies.ru/ru/article/view?id=36824

17. Миронов С. В., Куликов Г. В. Технологии контроля безопасности автоматизированных систем на основе структурного и поведенческого тестирования программного обеспечения // Кибернетика и программирование. - 2015. - № 5. - С.158-172. - ISSN 2306-4196. - DOI: 10.7256/2306-4196.2017.1.20351

18. Азымшин И. М., Чуканов В. О. Анализ безопасности программного обеспечения // Безопасность информационных технологий. - 2014. -№ 1. - С. 45-47. - ISSN 2074-7136.

19. Соснин Ю. В., Куликов Г. В., Непомнящих А. В. Комплекс математических моделей оптимизации конфигурации средств защиты информации от несанкционированного доступа // Программные системы и вычислительные методы. - 2015. - № 1. - С. 32-44. - ISSN 2305-6061. - DOI: 10.7256/2305-6061.2015.1.14124

20. Непомнящих А. В., Куликов Г. В., Соснин Ю. В., Нащёкин П. А. Методы оценивания защищённости информации в автоматизированных системах от несанкционированного доступа // Вопросы защиты информации. - 2014. - № 1 (104). - С. 3-12. - ISSN 2073-2600.

21. Козачок А. В., Кочетков Е. В. Обоснование возможности применения верификации программ для обнаружения вредоносного кода. Вопросы кибербезопасности. - 2016. - Bып. 3(16). - С. 25-32. - ISSN 2311-3456. - URL: https://cyberleninka.ru/article/v/obosnovanie-vozmozhnosti-primeneniya-verifikatsii-programm-dlya-obnaruzheniya-vredonosnogo-kod

Размещено на Allbest.ru

...

Подобные документы

  • Создание программы для хранения и обработки данных о съеме/сдаче жилья. Написание программы на языке C++ с использованием библиотеки Qt; использование исходного кода для создания приложения под Windows, Linux, Mac OS X без дополнительных изменений кода.

    курсовая работа [60,4 K], добавлен 07.03.2013

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

    реферат [58,9 K], добавлен 04.10.2010

  • Характеристика буфера обмена как области памяти, резервируемой системой Windows для организации обмена данными между приложениями. Копирование и перемещение файлов как функции буфера обмена. Изучение абсолютной и относительной адресации ячеек MS Excel.

    контрольная работа [13,9 K], добавлен 11.09.2011

  • Использование в программах, написанных на языке C, Windows application programming interfaces. Роль центрального процессора. Архитектура Фон Неймана. Оперативная память. Графическая плата. Создание интерфейса программы. Разработка машинного кода.

    реферат [101,5 K], добавлен 15.05.2014

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

    дипломная работа [512,4 K], добавлен 28.08.2012

  • Определение буфера обмена, его расположение, правила работы, форматы хранимых данных. WIN API функции, используемые в данном проекте. Модульная структура программы, краткое описание подпрограмм и их назначение, причины использования многопоточности.

    курсовая работа [872,5 K], добавлен 24.06.2011

  • Рассмотрение принципов работы руткита. Изучение особенностей захвата в режиме пользователя. Анализ модификации машинного кода прикладной программы. Оценка механизма работы руткита в режиме ядра. Характеристика методов обнаружения rootkit в системе.

    дипломная работа [241,9 K], добавлен 12.05.2019

  • Исследование наиболее распространенных видов сетевых атак. Сетевая разведка. Характеристика способов защиты от сетевых атак с использованием специальных программ. Изучение преимуществ и недостатков сетевых экранов. Переполнение буфера. Вирусные программы.

    реферат [329,2 K], добавлен 23.12.2014

  • Анализ модели политики безопасности. Программы сетевого общения (Instant Messengers и чаты). Удаление информации без возможности восстановления. Устройства хранения, файловые системы, уязвимости. Пример защиты ПК методом фильтрации сетевого трафика.

    курсовая работа [97,2 K], добавлен 17.12.2015

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

    курсовая работа [26,4 K], добавлен 01.12.2009

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

    курсовая работа [582,8 K], добавлен 24.03.2013

  • Описание компиляторов языка С/С++: MinGW, Borland Builder, Watcom, Intel C++, Visual. Сравнение характеристик выполнения программ на примере простого кода. Проведение тестов для компиляторов, оценка скорости выполнения и компилирования, их опций.

    курсовая работа [1,6 M], добавлен 05.10.2012

  • Иерархия типов данных. Определение понятий "указатель", "массив". Получение количества машинных слов, отведенных под каждый тип данных. Проверка программы на переполнение типа int. Анализ заданных выражений на предмет из синтаксической корректности.

    лабораторная работа [176,6 K], добавлен 07.06.2014

  • Просмотр, запись и чтение данных буфера обмена. Динамический обмен данными (DDE), способы его организации. Атомы в Windows, их понятие и функции. Особенности задания параметра lParam сообщений DDE. Обмен и передача данных между клиентом и сервером.

    лекция [303,7 K], добавлен 24.06.2009

  • Обзор технологии COM (Component Object Technology). Особенности графического интерфейса пользователя и методы его реализации. Интерфейс операционных систем Microsoft Windows: работа с папками, файлами и окнами, использование буфера обмена, проводник.

    контрольная работа [6,4 M], добавлен 16.04.2011

  • История автоматизированного перевода. Современные компьютерные программы перевода. Сфера использования машинного перевода. Формы организации взаимодействия человека и ЭВМ в машинном переводе. Интерредактирование и постредактирование машинного перевода.

    курсовая работа [30,0 K], добавлен 19.06.2015

  • Разработка кода на С++, реализующего простой интерфейс СОМ без динамической компоновки, результаты работы программы. Объявление интерфейсов IX, IY, IZ и IUnknown. Добавление подсчета ссылок с помощью реализации двух методов IUnknown – AddRef и Release.

    контрольная работа [1,6 M], добавлен 14.11.2010

  • Архитектура ввода/вывода Windows NT. Внутренняя организация шины USB. Сущностная характеристика драйверной модели WDM. Точки входа разрабатываемого драйвера, размещение кода в памяти, установка драйвера в системе. Реализация кода драйвера на языке C.

    курсовая работа [1,2 M], добавлен 27.09.2014

  • Анализ графического модуля "graphics.h". Анализ функции модуля, констант, типов и его глобальных переменных. Реализация пользовательской библиотеки "mouse.h". Особенности работы с мышкой в графическом и обычном режимах, разработка программного кода.

    курсовая работа [36,5 K], добавлен 02.12.2009

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

    курсовая работа [248,0 K], добавлен 25.12.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.