Чтение онлайн

ЖАНРЫ

Техника сетевых атак
Шрифт:

Например, если запустить этот пример под управлением Windows 2000, и в качестве имени пользователя ввести строку “1234567890qwerty” операционная система выдаст следующее сообщение, предлагая либо завершить работу приложения, либо запустить отладчик (если он установлен) для выяснения причин сбоя: «Исключение unknown software exception (0xc000001) в приложении по адресу 0x0012ffc0».

Рисунок 72

Реакция системы на переполнение буфера

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

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

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

Все, сказанное ниже, рассчитано на читателя средней квалификации, как минимум знающего назначение наиболее употребляемых команд микропроцессора Intel 80x86. В качестве дизассемблера выбрана IDA PRO четвертой версии [309], однако, можно воспользоваться и другими инструментами, такими как SOURCER, W32Dasm или на худой конец DumpBin, который поставляется с любым Windows-компилятором.

Результат дизассемблирования buff.demo.exe показан ниже (на диске, прилагаемом к книге, он расположен в файле “/LOG/buff.demo.lst”). Исследователь должен изучить «устройство» функции Auth, (как ее найти во много килобайтовом листинге - тема отдельного разговора). Для облегчения понимания, листинг снабжен подробными комментариями.

·.text:00401000; Segment type: Pure code

·.text:00401000 _text segment para public 'CODE' use32

·.text:00401000 assume cs:_text

·.text:00401000;org 401000h

·.text:00401000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing

·.text:00401000 Root proc near

·.text:00401000; Функции root расположена по адресу 0x401000

·.text:00401000 push ebp

·.text:00401000 ;… назначение процедуры root значение не имеет

·.text:00401000 ;… для ее вызова достаточно знать по какому адресу она расположена в памяти

·.text:00401000;… а расположена она по адресу 0x401000

·.text:00401001 mov ebp, esp

·.text:00401003 push offset aHelloRoot; "Hello, Root!\n"

·.text:00401008 call _printf

·.text:0040100D add esp, 4

·.text:00401010 pop ebp

·.text:00401011 retn

·.text:00401011 Root endp

·.text:00401012

·.text:00401012; --------------- S U B R O U T I N E ---------------------------------------

·.text:00401012

·.text:00401012; Attributes: bp-based frame

·.text:00401012

·.text:00401012 auth proc near; CODE XREF: main+10p

·.text:00401012

·.text:00401012 var_18 = byte ptr -18h

·.text:00401012 var_C = byte ptr -0Ch

·.text:00401012; Так IDA

обозначает локальные переменные, а цифры указывают относительное

·.text:00401012; расположение от конца кадра стека.

·.text:00401012; В Момент вызова функции указатель стека указывает на адрес возврата

·.text:00401012 push ebp

·.text:00401012; В стек заносится регистр ebp, значение указателя стека уменьшается на 4

·.text:00401013 mov ebp, esp

·.text:00401013; Открывается кадр стека:

·.text:00401013; В регистр ebp заносится значение регистра указателя стека esp.

·.text:00401013; Регистр ebp будет использоваться для адресации локальных переменных относительно конца кадра стека

·.text:00401015 sub esp, 18h

·.text:00401015; Резервируется 0x18 (24 в десятичной нотации) байт под локальные переменные

·.text:00401015; Но размер двух буферов равен 10+10=20 байтам! Откуда взялись четрые лишние байта?

·.text:00401015 ; Для ускорения доступа к данным компилятор размещает начала каждого из буферов по адресам, кратным

·.text:00401015; четырем байтам, так называемое выравнивание.

·.text:00401015; Таким образом на данный момент стек выглядит так:

·.text:00401015;

·.text:00401015; Относительный адрес Содержимое ячейки

·.text:00401015; - 0x18 буфер var_18[0]

·.text:00401015; - 0x17 буфер var_18[1]

·.text:00401015; - 0x16 буфер var_18[2]

·.text:00401015; - 0x15 буфер var_18[3]

·.text:00401015; - 0x14 буфер var_18[4]

·.text:00401015; - 0x13 буфер var_18[5]

·.text:00401015; - 0x12 буфер var_18[6]

·.text:00401015; - 0x11 буфер var_18[7]

·.text:00401015; - 0x10 буфер var_18[8]

·.text:00401015; - 0x0F буфер var_18[9]

·.text:00401015; - 0x0E дырка для выравнивания

·.text:00401015; - 0x0D дырка для выравнивания

·.text:00401015; - 0x0С буфер var_С[0] 01

·.text:00401015; - 0x0B буфер var_С[1] 02

·.text:00401015; - 0x0A буфер var_С[2] 03

·.text:00401015; - 0x09 буфер var_С[3] 04

·.text:00401015; - 0x08 буфер var_С[4] 05

·.text:00401015; - 0x07 буфер var_С[5] 06

·.text:00401015; - 0x06 буфер var_С[6] 07

·.text:00401015; - 0x05 буфер var_С[7] 08

·.text:00401015; - 0x04 буфер var_С[8] 09

·.text:00401015; - 0x03 буфер var_С[9] 10

Поделиться с друзьями: