R0 CREW

Gray Hat Python: Глава 9 - Sulley (Перевод: Prosper-H)

Перейти к содержанию

Intro

Sulley, названный в честь большого синего монстра из фильма “Корпорация монстров” (Monster, Inc.), является мощным фаззинг фреймворком, который написан на Python. Его разработчиками являются Pedram Amini и Aaron Portnoy из TippingPoint. Sulley – больше чем простой фаззер; он поставляется со множеством возможностей, которые помимо всего прочего включают информативные отчеты и встроенную поддержку взаимодействия с VMware. Он также способен перезапускать тестируемое приложение после сбоев, таким образом, чтобы сессия фаззинга могла продолжить поиск ошибок без остановок. Короче, Sulley – крутой (badass).

Для генерации данных, Sulley использует блоковый подход (block-bassed), тот же самый, что и Dave Aitel использовал в SPIKE [1], первом публичном фаззере использующем этот подход. В подходе, основанном на блоках, описывается общий скелет протокола или формат файла, который вы собрались фаззить, назначая длины и типы данных для полей, которые нужно проверить. После чего, фаззер берет свой внутренний список тест-кейсов и применяет его различными способами для скелета протокола, который вы создали. Этот подход оказался очень эффективным средством для поиска ошибок, потому что фаззер, заранее, получает информацию о строении протокола, который он фаззит.

Для начала мы рассмотрим необходимые шаги, позволяющие установить и настроить Sulley. Затем мы рассмотрим примитивы, которые Sulley использует для создания описаний протокола. Далее мы перейдем к запуску фаззинга, перехвату сетевых пакетов и построению отчетов информирующих о сбоях (crash reporting). Нашей целью фаззинга будет WarFTPD, FTP демон, уязвимый к переполнению стеку. Фаззеро-писателям и тестерам свойственно барть известную уязвимость и проверить, находит ли их фаззер ошибки или нет. В нашем случае, мы будем использовать WarFTPD, чтобы показать, как работает Sulley от начала и до конца. Не стесняйтесь обращаться к руководству Sulley [2], в котором Pedram и Aaron дали детальные инструкции, а также предоставили обширную информацию по всему фреймворку. Давайте приступим к фаззингу!

9.1 Установка

Прежде, чем мы углубимся в изучение строения Sulley, давайте установим и запустим его. Я подготовил zip-архив с исходным кодом Sulley, который можно загрузить по следующему адресу:

http://www.nostarch.com/ghpython.htm

Как только вы загрузите zip-архив, распакуйте его в любую папку. В папке, куда вы распаковали архив, найдите директорию Sulley и скопируйте из нее папки sulley, utils, и requests в каталог “C:\Python25\Lib\site-packages”. Это все, что требуется для установки ядра Sulley. Однако есть еще несколько необходимых пакетов, которые мы должны установить.

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

http://www.winpcap.org/install/bin/WinPcap_4_0_2.exe

После того, как вы установили WinPcap, нужно установить еще две библиотеки: pcapy и impacket, обе поддерживаются CORE Security. Pcap предоставляет Python интерфейс к ранее установленному WinPacp, а impacket является библиотекой, для создания и декодирования сетевых пакетов, которая также написана на Python. Для установки pcapy – загрузите и запустите инсталлер по следующему адресу:

http://oss.coresecurity.com/repo/pcapy-0.10.5.win32-py2.5.exe

После установки pcapy – загрузите impacket по следующему адресу:

http://oss.coresecurity.com/repo/Impacket-stable.zip

Распакуйте zip-архив в корень диска “C:”, перейдите в директорию impacket и выполните следующую команду:

C:\Impacket-stable\Impacket-0.9.6.0> C:\Python25\python.exe setup.py install

Это установит impacket, после чего вы будите полностью готовы к использованию Sulley.

9.2 Примитивы

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

9.2.1 Strings

Строки являются наиболее распространенными примитивами, которые вы будете использовать. Строки можно найти повсюду: имена пользователей, IP-адреса, папки и многие другие вещи, которые можно представить виде строк. Sulley использует директиву s_string(), чтобы обозначить, что данные, которые находятся в примитиве являются строкой. Основным параметром, принимаемым директивой s_string(), является допустимое значение строки, которое будет принято, как обычный ввод (input) для протокола. Например, если бы мы фаззили весь адрес электронной почты, то мы могли бы использовать следующую запись:

s_string("justin@immunityinc.com")

Она говорит Sulley, что justin@immunityinc.com является допустимым значением, таким образом, будет происходить фаззинг заданной строки, до тех пор, пока не будут исчерпаны все разумные вариации. Когда же все возможные вариации будут исчерпаны, Sulley, вернется к использованию исходного допустимого значения, которое вы определили. Некоторые возможные значения, которые Sulley смог сгенерировать, используя мой email, представлены ниже:

justin@immunityinc.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
justin@%n%n%n%n%n%n.com%d%d%d@immunityinc.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

9.2.2 Delimiters

Разделители являются не чем иным, как маленькими строками, которые помогают разделить большие строки на управляемые части. Применив директиву s_delim() к используемому нами в предыдущем примере, email-адресу – получим следующую запись для дальнейшего фаззинга:

s_string("justin")
s_delim("@")
s_string("immunityinc")
s_delim(".",fuzzable=False)
s_string("com")

Вы можете видеть, как мы разбили email-адрес на субкомпоненты и сказали Sulley, что в нашем, конкретном, случае мы не хотим фаззить точку “.”, но хотим фаззить разделитель “@”.

9.2.3 Примитивы Static и Random

В Sulley существует возможность задания строк – с изменяемыми, случайным образом (random) данными и не изменяемыми (static). Чтобы использовать статическую строку, нужно использовать директиву s_static(), как показано ниже:

s_static("Hello,world!")
s_static("\x41\x41\x41")

Для генерации случайных данных переменной длины, используйте директиву s_random(). Обратите внимание на то, что директиве требуется несколько дополнительных параметров для того, чтобы Sulley смог определить, как много данных должно быть сгенерировано. Параметр min_length и max_length определяют минимальную и максимальную длину данных, создаваемых на каждой последующей итерации. Так же может быть полезен дополнительный параметр num_mutations, который определяет, сколько раз должна изменяться строка, прежде чем вернуться к исходному (оригинальному) значению; по умолчанию этот параметр равен 25 итерациям. Пример использования:

s_random("Justin",min_length=6, max_length=256, num_mutations=10)

В данном примере будут генерироваться случайные данные, которые будут не менее 6 байт и не более 256 байт. Строка будет изменяться 10 раз, до возвращения к первоначальному значению “Justin”.

9.2.4 Binary Data

В Sulley примитив бинарных данных подобен Швейцарскому ножу. Вы можете вставлять в него практически любые бинарные данные. Sulley, успешно распознает их. Это особенно полезно, когда у вас есть перехваченный пакет неизвестно протокола, а вам всего лишь нужно проверить реакцию сервера на полу-сформированные данные, которые вы отправляете ему. Для двоичных данных используйте директиву s_binary(), например, так:

s_binary("0x00 \\x41\\x42\\x43 0d 0a 0d 0a")

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

9.2.5 Integers

Целые числа повсюду и используются как в бинарных, так и в текстовых протоколах для определения длины данных, предоставления структур данных и т.п. Sulley поддерживает все основные целочисленные типы данных (см. Листинг 9-1).

Листинг 9-1: Различные типы целочисленных данных поддерживаемые Sulley

1 byte – s_byte(), s_char()
2 bytes – s_word(), s_short()
4 bytes – s_dword(), s_long(), s_int()
8 bytes – s_qword(), s_double()

Все целочисленные примитивы принимают важные дополнительные параметры.

  • Параметр endian определяет порядок следования байтов, в котором заданное число должно быть представлено. Прямой порядок определяется символом “>”, обратный “<”. По умолчанию установлен обратный порядок байтов “<”.
  • Параметр format имеет два возможных значения “binary” и “ascii”. Он определяет то, как будет использоваться число. Например, число “1” в ASCII формате, будет представлено как “\x31” в бинарном формате.
  • Параметр signed определяет, будет ли использоваться число со знаком или нет. Он применим только, когда используется параметр format со значением ascii. Сам параметр представляет собой булево значение и по умолчанию равен False.
  • Параметр full_range определяет, будет ли Sulley проходить по всем возможным значениям целочисленного числа, которое вы фаззите. Параметр представляет собой булево значение и по умолчанию равен False. Это наиболее интересный флаг из всех перечисленных. Используйте этот флаг рассудительно, потому что его использование может занять очень продолжительное время, поскольку потребует прохода через все значения целого числа. Sulley достаточно умен, чтобы не делать этого, а проверить пограничные значения (значения, которые лежат рядом или равны наибольшим или наименьшим значениям). Например, если наивысшее целочисленное значение без знака может быть равно 65,535, то Sulley может попробовать проверить такие пограничные значения как: 65,534, 65,535, 65,536. По умолчанию параметр full_range равен False, что означает, что вы оставляете выбор значений за Sulley. И лучше, как правило, его оставлять таким и не менять.

Ниже даны примеры, некоторых целочисленных примитивов:

s_word(0x1234, endian=">", fuzzable=False)
s_dword(0xDEADBEEF, format="ascii", signed=True)

В первом примере мы устанавливаем 2-х байтовое значение в 0x1234, зеркально отражая его в прямой порядок следования байтов “>” и оставляем его как статическое значение. Во втором примере мы устанавливаем 4-х байтное DWORD значение в 0xDEADBEEF и делаем его целочисленным числом в ASCII формате.

9.2.6 Blocks и Groups

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

В документации, предлагается следующий пример, фаззинга HTTP, где используются блоки и группы:

# import all of Sulley's functionality.

from sulley import *
# this request is for fuzzing: {GET,HEAD,POST,TRACE} /index.html HTTP/1.1
# define a new block named "HTTP BASIC".

s_initialize("HTTP BASIC")

# define a group primitive listing the various HTTP verbs we wish to fuzz.
s_group("verbs", values=["GET", "HEAD", "POST", "TRACE"])

# define a new block named "body" and associate with the above group.
if s_block_start("body", group="verbs"):

# break the remainder of the HTTP request into individual primitives.
    s_delim(" ")
    s_delim("/")
    s_string("index.html")
    s_delim(" ")
    s_string("HTTP")
    s_delim("/")
    s_string("1")
    s_delim(".")
    s_string("1")

    # end the request with the mandatory static sequence.
    s_static("\r\n\r\n")

# close the open block, the name argument is optional here.
s_block_end("body")

Мы видим, что парни из TippingPoint определили группу verbs в которую входят все общие типы запросов HTTP. Затем они определили блок body, который связывается с группой verbs. Это значит, что каждое значение из verbs (GET, HEAD, POST, TRACE), будет применено ко всем мутациям блока body. Таким образом, Sulley производит тщательный фаззинг протокола HTTP, задействовав все основные типы запросов.

Теперь, когда мы рассмотрели основы, можно перейти к фаззингу с использованием Sulley. В Sulley содержится гораздо больше возможностей, чем те, которые были рассмотрены нами, например: кодировщики данных (data encoders), калькуляторы контрольных сумм (checksum calculator), автоматический подсчет размера данных (automatic data sizes) и др. Для всестороннего рассмотрения Sulley и материала связанного с фаззингом, обратитесь к книге, соавтором которой был Pedram, Fuzzing: Brute Force Vulnerability Discovery (Addison-Wesley, 2007) (Прим. пер. Есть русский вариант «Fuzzing: Исследование уязвимостей методом грубой силы»). Теперь давайте приступим к фаззингу WarFTPD. Вначале мы создадим наборы примитивов, а затем перейдем к созданию сессии, которая будет ответственна за управление тестами.

9.3 Уничтожение WarFTPD с помощью Sulley

Теперь, когда вы владеете общим представлением того, как создать описание протокола, используя примитивы Sulley, давайте применим имеющиеся знания к реальной программе, WarFTPD 1.65. В этой программе имеется переполнения стека, которое возникает при передаче очень больших значений в командах USER или PASS. Обе эти команды используются для аутентификации FTP-пользователя на сервере, чтобы он в дальнейшем мог выполнять операции передачи файлов, между своим компьютером и сервером, где запущен FTP-демон. Загрузите WarFTPD по следующей ссылке:

http://www.warftp.org/files/1.6_Series/ward165.exe

Затем запустите инсталлер. Это разархивирует WarFTPD в текущий рабочий каталог; после чего вам нужно просто выполнить warftpd.exe, чтобы запустить сервер. Давайте бросим беглый взгляд на FTP-протокол для того, чтобы вы поняли основную структуру протокола, прежде чем описывать его в Sulley.

9.3.1 FTP 101

FTP – это очень простой протокол, который используется для передачи данных из одной системы в другую. Он широко используется в различных средах, начиная с веб-серверов и заканчивая современными сетевыми принтерами. По умолчанию FTP-сервер прослушивает 21 TCP порт и получает команды от FTP-клиента. Мы будем действовать как FTP-клиент, который будет отправлять модифицированные FTP-команды в попытке повредить тестируемый FTP-сервер. Не смотря на то, что мы будем тестировать только WarFTPD, вы сможете взять наш FTP-фаззер и атаковать любой другой FTP-сервер, какой вы захотите!

Любой FTP-сервер настроен либо позволять анонимным пользователям соединяться с сервером, либо требует от них аутентифицироваться. Так как мы знаем, что ошибка WarFTPD связанна с переполнением буфера в командах USER и PASS (обе используются для аутентификации), то мы будем считать, что требуется аутентификация. Формат для этих FTP-комманд выглядит следующим образом:

USER <USERNAME>
PASS <PASSWORD>

После того, как вы ввели правильное имя и пароль, сервер позволит вам использовать полный набор команд для: передачи файлов, изменения каталогов, запросов к файловой системе и др. Так как команды USER и PASS является всего лишь небольшим подмножеством всех возможностей FTP-сервера, давайте добавим еще несколько команд, чтобы проверить наличие других ошибок, после того, как мы аутентифицировались. Взгляните на Листинг 9-2, чтобы видеть, какие дополнительные команды мы включим в описание скелета протокола. Чтобы получить полное представление о всех командах, которые поддерживает FTP-протокол, пожалуйста, обратитесь к RFC [3].

Листинг 9-2: Дополнительные FTP-команды, которые мы собираемся фаззить

CWD <DIRECTORY> - change working directory to DIRECTORY
DELE <FILENAME> - delete a remote file FILENAME
MDTM <FILENAME> - return last modified time for file FILENAME
MKD <DIRECTORY> - create directory DIRECTORY

Это далеко не полный список, но он даст вам некоторое дополнительное представление о протоколе… Давайте возьмем то, что мы уже знаем и преобразуем эти знание в описание скелета протокола для Sulley.

9.3.2 Создание скелета FTP-протокола

Мы воспользуемся знаниями о примитивах, чтобы превратить Sulley в дробильную машину FTP-сервера. Откройте свой любимый редактор кода, создайте новый фал, назвав его ftp.py и введите следующий код:

ftp.py

from sulley import *

s_initialize("user")
s_static("USER")
s_delim(" ")
s_string("justin")
s_static("\r\n")

s_initialize("pass")
s_static("PASS")
s_delim(" ")
s_string("justin")
s_static("\r\n")

s_initialize("cwd")
s_static("CWD")
s_delim(" ")
s_string("c: ")
s_static("\r\n")

s_initialize("dele")
s_static("DELE")
s_delim(" ")
s_string("c:\\test.txt")
s_static("\r\n")

s_initialize("mdtm")
s_static("MDTM")
s_delim(" ")
s_string("C:\\boot.ini")
s_static("\r\n")

s_initialize("mkd")
s_static("MKD")
s_delim(" ")
s_string("C:\\TESTDIR")
s_static("\r\n")

С созданием скелета протокола покончено. Теперь давайте перейдем к созданию фаззинговой сессии, которая свяжет всю имеющуюся информацию, а также настроит сетевой снифер и отладчик (debugging client).

9.3.3 Sulley Sessions

Сессии в Sulley является механизмом, который связывает фаззинговые запросы и заботится о: перехвате сетевых пакетов, отладке процесса, создании отчетов об ошибках и управлении виртуальной машинной. Для начала, давайте создадим файл для управления сессией, а затем разберем различные его части. Создайте новый файл Python, назвав его ftp_session.py и введите следующий код:

ftp_session.py

from sulley import *
from requests import ftp # this is our ftp.py file

(#1): def receive_ftp_banner(sock):
sock.recv(1024)

(#2):  sess = sessions.session(session_filename="audits/warftpd.session")
(#3):  target = sessions.target("192.168.244.133", 21)
(#4):  target.netmon = pedrpc.client("192.168.244.133", 26001)
(#5):  target.procmon = pedrpc.client("192.168.244.133", 26002)
target.procmon_options = { "proc_name" : "war-ftpd.exe" }

# Here we tie in the receive_ftp_banner function which receives
# a socket.socket() object from Sulley as its only parameter
sess.pre_send = receive_ftp_banner
(#6):  sess.add_target(target)
(#7):  sess.connect(s_get("user"))
sess.connect(s_get("user"), s_get("pass"))
sess.connect(s_get("pass"), s_get("cwd"))
sess.connect(s_get("pass"), s_get("dele"))
sess.connect(s_get("pass"), s_get("mdtm"))
sess.connect(s_get("pass"), s_get("mkd"))

sess.fuzz()

Функция receive_ftp_banner() (#1) необходима, потому что каждый FTP-сервер имеет баннер, который он отображает при подключении клиента. Мы связываем эту функцию со свойством sess.pre_send, которое говорит Sulley получить FTP-баннер до отправки каких-либо фаззинговых данных. Также свойство pre_send передает действительный объект сокета Python, так что наша функция принимает его в качестве единственного параметра. На первом шаге, при создании сессии, нужно определить файл сессии (#2), который будет отслеживать текущее состояние фаззера. Этот постоянный файл позволяет запускать и останавливать фаззер, когда нам угодно. На втором шаге (#3) нужно определить цель для атаки, которая представляет собой IP-адрес и номер порта. Мы будем атаковать адрес 192.168.244.133 и порт 21, на котором находится наш WarFTPD (запущенный в нутрии виртуальной машины в нашем случае). Третий шаг (#4) говорит Sulley, что наш снифер установлен на том же самом компьютере и слушает TCP-порт 26001, который является портом, на котором он принимает команды от Sulley. Четвертый шаг (#5) говорит Sulley, что наш отладчик тоже установлен на компьютере с адресом 192.168.244.133, но прослушивает TCP-порт 26002; и также как и со снифером, Sulley использует этот порт для отправки команд отладчику. Мы также передаем дополнительную опцию, которая говорит отладчику, что имя процесса, которым мы интересуемся, является war-ftpd.exe. Затем добавляем настройки для тестируемого приложения в нашу сессию (#6). Следующий шаг (#7) должен связать наши FTP-запросы вместе, придав им логическую форму. Можно видеть, как мы объединили в цепочку команды аутентификации (USER, PASS), а затем все остальные команды, которые требуют от пользователя быть аутентифицированным, мы присоединили к команде PASS. В заключение, говорим Sulley начать фаззинг.

Теперь у нас есть полностью определенная сессия с хорошим набором запросов, поэтому давайте посмотрим, как установить наши network и monitor скрипты. Как только закончим делать это, мы будем готовы запустить Sulley и посмотреть, что он сможет сделать с нашим подопытным WarFTPD.

9.3.4 Network и Process Monitoring

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

Агенты network-monitor и process-monitor являются Python сценариями, которые поставляются с Sulley. С ними очень легко работать. Давайте начнем с process-monitor (process_monitor.py), который расположен в основном каталоге Sulley. Просто запустите его, чтобы увидеть справочную информацию:

python process_monitor.py

Output:

ERR> USAGE: process_monitor.py
     <-c|--crash_bin FILENAME> filename to serialize crash bin class to
     [-p|--proc_name NAME] process name to search for and attach to
     [-i|--ignore_pid PID] ignore this PID when searching for the target process
     [-l|--log_level LEVEL] log level (default 1), increase for more verbosity
     [--port PORT] TCP port to bind this agent to

Мы будем выполнять скрипт process_monitor.py со следующими параметрами командной строки:

python process_monitor.py -c C:\warftpd.crash -p war-ftpd.exe

Теперь мы контролируем (monitoring) наш целевой процесс, поэтому давайте рассмотрим скрипт network_monitor.py. Для его работы требуется несколько обязательных библиотек, таких как: WinPcap 4.0 [4], pcapy [5] и impacket [6]. Все они предоставляют инструкции по установке, которые расположены на их официальных сайтах.

python network_monitor.py

Output:

ERR> USAGE: network_monitor.py
     <-d|--device DEVICE #> device to sniff on (see list below)
     [-f|--filter PCAP FILTER] BPF filter string
     [-P|--log_path PATH] log directory to store pcaps to
     [-l|--log_level LEVEL] log level (default 1), increase for more verbosity
     [--port PORT] TCP port to bind this agent to

Network Device List:
     [0] \Device\NPF_GenericDialupAdapter
     (#1): [1] {83071A13-14A7-468C-B27E-24D47CB8E9A4} 192.168.244.133

После того, как мы запустили скрипт мониторинга процесса (process_monitor.py), нам нужно просто передать этому (network_monitor.py) скрипту несколько допустимых параметров. Видно, что сетевой интерфейс, который мы хотим использовать (#1) установлен в “[1]” на выходе. Мы передадим его, когда определим параметры командной строки для network_monitor.py так, как показано тут:

python network_monitor.py -d 1 -f "src or dst port 21" -P C:\pcaps\

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

9.3.5 Фаззинг и веб-интерфейс Sulley

Теперь мы готовы запустить Sulley. Мы будем использовать веб-интерфейс, чтобы следить за процессом фаззинга. Для начала запустите ftp_session.py, следующим образом:

python ftp_session.py

Он начнет производить вывод так, как показано тут:

[07:42.47] current fuzz path: -> user
[07:42.47] fuzzed 0 of 6726 total cases
[07:42.47] fuzzing 1 of 1121
[07:42.47] xmitting: [1.1]
[07:42.49] fuzzing 2 of 1121
[07:42.49] xmitting: [1.2]
[07:42.50] fuzzing 3 of 1121
[07:42.50] xmitting: [1.3]

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

Откройте ваш любимый браузер и перейдите по следующей ссылке http://127.0.0.1:26000. Вы должны увидеть похожий экран, как на Рисунке 9-1.

Рисунок 9-1: Веб-интерфейс Sulley

Чтобы видеть обновления веб-интерфейса, обновите страницу браузера, и он покажет какой тест-кейс, и какой примитив в данный момент обрабатывается фаззером. На Рисунке 9-1 вы можете видеть, что происходит фаззинг пользовательских примитивов (прим. пер. Не для всех очевидно, поэтому подсказываю. Вывод сделан на основании строки “user: 29 of 1,121”), которые, как мы знаем, должны давать сбои (crash). Через некоторое время, если продолжите обновлять браузер, то вы должны увидеть экран веб-интерфейса очень похожий на тот, что изображен на Рисунке 9-2.

Рисунок 9-2: Веб-интерфейс Sulley отображающий информацию о сбоях

Отлично! Мы сумели вызвать ошибку в WarFTPD, и Sulley собрал всю уместную информацию о ней. В обоих тест-кейсах мы видим, что WarFTPD не смог дизассемблировать инструкцию по адресу 0x5c5c5c5c. Отдельный байт 0x5c представляет ASCII символ “”, поэтому можно с уверенностью предположить, что мы полностью переписали буфер с помощью последовательности символов “”. Когда наш отладчик не смог дизассемблировать данные по адресу, на который указывал EIP, это вызвало фолт (failed), так как 0x5c5c5c5c не является допустимым адресом. Это наглядно демонстрирует возможность управления регистром EIP, что означает, что мы нашли эксплуатируемую ошибку! Не стоит слишком радоваться, поскольку мы нашли ошибку, о которой знали, что она там есть. Но это показывает, что наши навыки использования Sulley достаточно хороши, так что теперь мы можем применить разработанные FTP-примитивы к другим программам и возможно найти там новые ошибки.

Если вы сейчас нажмете на номер тест-кейса, то вы должны увидеть более подробную информацию о сбое, как показано в Листинге 9-3:

Отчеты об ошибках, генерируемые PyDbg, были рассмотрены в “Gray Hat Python: Глава 4 - PyDbg - Windows отладчик на чистом Python (Перевод: Prosper-H)”]Главе 4.2[/URL]. Обратитесь к этому разделу, если вам не понятны значения, которые вы видите.

Листинг 9-3: Подробный отчет об ошибке для теста #437

[INVALID]:5c5c5c5c Unable to disassemble at 5c5c5c5c from thread 252
caused access violation when attempting to read from 0x5c5c5c5c
CONTEXT DUMP
    EIP: 5c5c5c5c Unable to disassemble at 5c5c5c5c
    EAX: 00000001 ( 1) -> N/A
    EBX: 5f4a9358 (1598722904) -> N/A
    ECX: 00000001 ( 1) -> N/A
    EDX: 00000000 ( 0) -> N/A
    EDI: 00000111 ( 273) -> N/A
    ESI: 008a64f0 ( 9069808) -> PC (heap)
    EBP: 00a6fb9c ( 10943388) -> BXJ_\'CD@U=@_@N=@_@NsA_@N0GrA_@N*A_0_C@N0_Ct^J_@_0_C@N (stack)
    ESP: 00a6fb44 ( 10943300) -> ,,,,,,,,,,,,,,,,,, cntr User from 192.168.244.128 logged out (stack)
    +00: 5c5c5c5c ( 741092396) -> N/A
    +04: 5c5c5c5c ( 741092396) -> N/A
    +08: 5c5c5c5c ( 741092396) -> N/A
    +0c: 5c5c5c5c ( 741092396) -> N/A
    +10: 20205c5c ( 538979372) -> N/A
    +14: 72746e63 (1920233059) -> N/A

disasm around:
    0x5c5c5c5c Unable to disassemble

stack unwind:
    war-ftpd.exe:0042e6fa
    MFC42.DLL:5f403d0e
    MFC42.DLL:5f417247
    MFC42.DLL:5f412adb
    MFC42.DLL:5f401bfd
    MFC42.DLL:5f401b1c
    MFC42.DLL:5f401a96
    MFC42.DLL:5f401a20
    MFC42.DLL:5f4019ca
    USER32.dll:77d48709
    USER32.dll:77d487eb
    USER32.dll:77d489a5
    USER32.dll:77d4bccc
    MFC42.DLL:5f40116f

SEH unwind:
    00a6fcf4 -> war-ftpd.exe:0042e38c mov eax,0x43e548
    00a6fd84 -> MFC42.DLL:5f41ccfa mov eax,0x5f4be868
    00a6fdcc -> MFC42.DLL:5f41cc85 mov eax,0x5f4be6c0
    00a6fe5c -> MFC42.DLL:5f41cc4d mov eax,0x5f4be3d8
    00a6febc -> USER32.dll:77d70494 push ebp
    00a6ff74 -> USER32.dll:77d70494 push ebp
    00a6ffa4 -> MFC42.DLL:5f424364 mov eax,0x5f4c23b0
    00a6ffdc -> MSVCRT.dll:77c35c94 push ebp
    ffffffff -> kernel32.dll:7c8399f3 push ebp

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

© Translated by Prosper-H from r0 Crew

[1] For the SPIKE download, go to:
http://immunityinc.com/resources-freesoftware.shtml
[2] To download the Sulley: Fuzzing Framework manual, go to: http://www.fuzzing.org/wp-content/SulleyManual.pdf
[3] See RFC959—File Transfer Protocol:
http://www.faqs.org/rfcs/rfc959.html

[4] The WinPcap 4.0 download is available at: http://www.winpcap.org/install/bin/WinPcap_4_0_2.exe

[5] See CORE Security pcapy:
http://oss.coresecurity.com/repo/pcapy-0.10.5.win32-py2.5.exe

[6] Impacket is a requirement for pcapy to function; see http://oss.coresecurity.com/repo/Impacket-0.9.6.0.zip