Skip to content

Commit

Permalink
Update Linux Crusher tests
Browse files Browse the repository at this point in the history
  • Loading branch information
wakolzin committed Feb 5, 2021
1 parent b6d363d commit ea22394
Show file tree
Hide file tree
Showing 157 changed files with 655 additions and 235 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,83 +1,74 @@
Нахождение аварийного завершения OpenSSL-сервера, соответствующего уязвимости `CVE-2016-6309`.

Демонстрируются следующие возможности фаззера:

1) Описание формата данных с помощью `Peach Pit` (модифицированного для `Crusher`);

2) Замена вызовов некоторых функций целевой программы пользовательскими во время фаззинга.
Т.к. речь идёт о сетевых функциях, которые работают медленно - обеспечивается ускорение запусков в десятки раз.
Более подробно - см. раздел `"PRELOAD"` в документации фаззера.

Ниже представлены все этапы от подготовки к фаззингу до воспроизведения креша.

# Сборка OpenSSL со статической инструментацией
Выполните команды в терминале (обратите внимание, что нужно указать актуальный путь до фаззера):
```bash
wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_0a.tar.gz
tar xvf OpenSSL_1_1_0a.tar.gz
mkdir openssl
cd openssl-OpenSSL_1_1_0a
CC=/path/to/crusher/bin_x86-64/isp-gcc ./config --prefix=$PWD/../openssl/
make -j 4
make install
cd ..
```

# Генерация SSL-сертификатов
```bash
mkdir keys
./openssl/bin/openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout keys/key.pem -out keys/cert.pem -batch
```

# Фаззинг
Скомпилировать разделяемую библиотеку для замены некоторых сетевых функций (для ускорения фаззинга):
```bash
cd custom_lib/
make
cd ..
```

Для правильного детектирования аварийных завершений целевой программы со статической инструментацией выполнить:
```bash
sudo su
echo core >/proc/sys/kernel/core_pattern
exit
```

Запустить фаззинг (`"-c 4"` - запуск на 4 ядрах):
```bash
ISP_PRELOAD=$PWD/custom_lib/custom_lib.so ./fuzz.sh -f /path/to/crusher/bin_x86-64/fuzz_manager -c 4
```

Запустить в другом терминале UI фаззера:
```bash
/path/to/crusher/bin_x86-64/ui -o out
```

В правом верхнем углу окна пользовательского интерфейса можно наблюдать окно `Stats`. В нём обратите внимание на поле `unique_crashes`.
Как только будет найдено аварийное завершение, значение поля `unique_crashes` станет ненулевым. Пока значение поля нулевое - не останавливайте фаззинг.
Желательно дождаться, когда значение поля будет больше 1. После этого можно остановить фаззинг:

* в терминале с `UI` (пользовательский интерфейс) - для выхода из `UI` нажмите кнопку `q`;
* в терминале с запущенным фаззингом завершите фаззинг по комбинации клавиш `Ctrl+C`.

# Воспроизведение аварийного завершения
1) Получить список креш-файлов:
```bash
find out -name id_crash_*
```

2) Запуск сервера (будет слушать порт 4444):
````bash
./run_server.sh
````

3) Запуск клиента (в другом терминале):
```bash
python run_client.py --ip 127.0.0.1 --port 4444 --crash-path <crash_path>
```

где `<crash_path>` - один из файлов, полученных в п. 1)

4) В терминале с сервером наблюдаем его аварийное завершение.
Если аварийного завершения не произошло, то повторяем п. 3) с другим файлом из п. 1)
Нахождение аварийного завершения OpenSSL-сервера, соответствующего уязвимости CVE-2016-6309.

Демонстрируются следующие возможности фаззера:

1) Описание формата данных с помощью Peach Pit (модифицированного для Crusher).

2) Замена вызовов некоторых функций целевой программы пользовательскими во время фаззинга.
Т.к. речь идёт о сетевых функциях, которые работают медленно - обеспечивается ускорение запусков в десятки раз.
Более подробно - см. раздел `"PRELOAD"` в документации фаззера.

Ниже представлены все этапы от подготовки к фаззингу до воспроизведения креша.

# Подготовка OpenSSL сервера для фаззинга
Включает следующие этапы:
1) Сборка компилятора для статической инструментации OpenSSL.
`Crusher` совместим со статической инструментацией, реализованной в `AFL++`.
На этом этапе скачивается и собирается `AFL++` - в нём будет нужен только `afl-gcc`.
2) Сборка OpenSSL со статической инструментацией.
Скачивается (уязвимая) версия OpenSSL v1.1.0a и собирается с помощью `afl-gcc`.
3) Генерация SSL-сертификата и ключа.
Необходимы для работы OpenSSL сервера.
4) Компиляция разделяемой библиотеки для замены некоторых сетевых функций (для ускорения фаззинга).

Для выполнения этих действий запустите:
```shell
./build.sh
```

# Запуск фаззинга
Для правильного детектирования аварийных завершений целевой программы со статической инструментацией выполнить:
```shell
sudo su
echo core >/proc/sys/kernel/core_pattern
exit
```

Запустите фаззинг через `fuzz.sh`, указав путь до `fuzz_manager` (опция `-f`) и число ядер для фаззинга (опция `-c`):
```shell
ISP_PRELOAD=$PWD/custom_lib/custom_lib.so ./fuzz.sh -f /path/to/crusher/bin_x86-64/fuzz_manager -c 4
```

# Мониторинг фаззинга
Запустите в другом терминале UI фаззера:
```shell
/path/to/crusher/bin_x86-64/ui -o out
```

В правом верхнем углу окна пользовательского интерфейса можно наблюдать окно `Stats`. В нём обратите внимание на поле `unique_crashes`.
Как только будет найдено аварийное завершение, значение поля `unique_crashes` станет ненулевым. Пока значение поля нулевое - не останавливайте фаззинг.
Желательно дождаться, когда значение поля будет больше 1. После этого можно остановить фаззинг:

* в терминале с `UI` (пользовательский интерфейс) - для выхода из `UI` нажмите кнопку `q`;
* в терминале с запущенным фаззингом завершите фаззинг по комбинации клавиш `Ctrl+C`.

# Воспроизведение аварийного завершения
1) Получить список креш-файлов:
```shell
find out -name id_crash_*
```

2) Запуск сервера (будет слушать порт 4444):
````shell
./run_server.sh
````

3) Запуск клиента (в другом терминале):
```shell
python run_client.py --ip 127.0.0.1 --port 4444 --crash-path <crash_path>
```

где `<crash_path>` - один из файлов, полученных в п. 1)

4) В терминале с сервером наблюдаем его аварийное завершение.
Если аварийного завершения не произошло, то повторяем п. 3) с другим файлом из п. 1)
25 changes: 25 additions & 0 deletions Examples/Crusher/Linux/OpenSSL/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Download & build afl-gcc
wget https://github.com/AFLplusplus/AFLplusplus/archive/3.0c.tar.gz
tar xvf 3.0c.tar.gz
cd AFLplusplus-3.0c/
make -j4
cd ..

# Build OpenSSL
wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_0a.tar.gz
tar xvf OpenSSL_1_1_0a.tar.gz
mkdir openssl
cd openssl-OpenSSL_1_1_0a
CC=../AFLplusplus-3.0c/afl-gcc ./config --prefix=$PWD/../openssl/ no-shared
make -j4
make install
cd ..

# Create SSL certificate & key
mkdir keys
./openssl/bin/openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout keys/key.pem -out keys/cert.pem -batch

# Compile custom library (for ISP_PRELOAD)
cd custom_lib/
make
cd -
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ echo "OpenSSL analysis"
echo ""
clean_result

COMMAND="$FUZZMANAGER --start $CORES -T IspPreloadNetworkToFile -I StaticForkSrv --port __free_port -t 2000 -o out --peach-pit $PWD/ClientHello.xml -F -i in -- $PWD/openssl/bin/openssl s_server -cert $PWD/keys/cert.pem -key $PWD/keys/key.pem -accept __free_port -www -naccept 1 @@"
COMMAND="$FUZZMANAGER --start $CORES --eat-cores 1 --dse-cores 1 --dse-threads 0 -T File -I StaticForkSrv -t 2000 -o out --peach-pit $PWD/ClientHello.xml -F -i in -- $PWD/openssl/bin/openssl s_server -cert $PWD/keys/cert.pem -key $PWD/keys/key.pem -accept 1111 -www -naccept 1"
echo $COMMAND
$COMMAND
File renamed without changes.
File renamed without changes.
File renamed without changes.
32 changes: 17 additions & 15 deletions Examples/Linux/README.md → Examples/Crusher/Linux/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
## Набор примеров
Набор примеров фаззинга Linux-приложений, в которых демонстрируется часть функционала `Crusher`:
Набор примеров фаззинга на Linux, в которых демонстрируется часть функционала `Crusher`:

1) `faad` - фаззинг аргументов командной строки;
2) `gpg` - фаззинг файла + ДСВ (динамическое символьное выполнение);
3) `jasper` - фаззинг файла + ДСВ;
4) `python` - фаззинг файла;
5) `stm32` - фаззинг ПО устройства ARM (на основе частичной эмуляции с Lua-Qemu);
6) `OpenSSL` - фаззинг OpenSSL-сервера: Peach Pit + ISP_PRELOAD.
1) `python` - фаззинг через файл;
2) `jasper` - фаззинг через файл с использованием ДСВ (динамическое символьное выполнение);
3) `faad` - фаззинг через аргументы командной строки;
4) `OpenSSL` - фаззинг OpenSSL-сервера: Peach Pit + ISP_PRELOAD;
5) `stm32` - фаззинг ПО устройства ARM (на основе частичной эмуляции с Lua-Qemu);
6) `firmware_x86_32` - фаззинг ПО устройства x86 (32-бит) (на основе частичной эмуляции с Lua-Qemu);
7) `firmware_x86_64` - фаззинг ПО устройства x86 (64-бит) (на основе частичной эмуляции с Lua-Qemu).

Далее приведена последовательность действия по фаззингу, мониторингу и воспроизведению аварийных завершений (крешей) для следующих примеров: `faad`, `gpg`, `jasper` и `python`.
Для примеров `stm32` и `OpenSSL` подробные инструкции можно найти в фалах `README.md` в соответствующих директориях.
Далее приведена последовательность действия по фаззингу, мониторингу и воспроизведению аварийных завершений (крешей) для следующих примеров: `python`, `jasper` и `faad`.

Для остальных примеров подробные инструкции можно найти в файлах `README.md` в соответствующих директориях.

## Запуск фаззинга
В директории примера есть скрипт `fuzz.sh` для запуска фаззинга.
Expand Down Expand Up @@ -46,18 +48,18 @@
find out -name id_crash_*
```

2) В скрипте `fuzz.sh` после символов `--` прописана команда запуска приложения. Например, для `gpg` она выглаядит так:
2) В скрипте `fuzz.sh` после символов `--` прописана команда запуска приложения. Например, для `python` она выглаядит так:
```bash
./gpg @@
./python-2.5 __DATA__
```

Далее возможны 2 случая:
а) в случае фаззинга файла (как в примере `gpg`) - выполните вышеуказанную команду, заменив последовательность символов `@@` на один из путей к креш-файлу, полученных в пункте 1), например:
а) в случае фаззинга файла (как в примере `python`) - выполните вышеуказанную команду, заменив последовательность символов `__DATA__` на один из путей к креш-файлу, полученных в пункте 1), например:
```bash
./gpg out/FUZZ-MASTER_0/crashes/id_crash_0
./python-2.5 out/FUZZ-MASTER_0/crashes/id_crash_0
```

б) в случае фаззинга argv (аргументов командной строки, как в примере `faad`) - выполните вышеуказанную команду, заменив последовательность символов `@@` на `$(cat out/FUZZ-MASTER_0/crashes/id_crash_0)`,
б) в случае фаззинга argv (аргументов командной строки, как в примере `faad`) - выполните вышеуказанную команду, заменив последовательность символов `__DATA__` на `$(cat out/FUZZ-MASTER_0/crashes/id_crash_0)`,
где `out/FUZZ-MASTER_0/crashes/id_crash_0` - пример пути к креш-файлу, полученному в пункте 1).

Пример команды:
Expand All @@ -66,4 +68,4 @@ find out -name id_crash_*
```

3) Наблюдаем аварийное завершение: сообщение в терминале, содержащее `Segmentation fault` или `Aborted`.
Если соответствующих сообщений не было выведено, то нужно повторить пункты 1)-3) на другом файле из списка, полученного в пункте 1).
Если соответствующих сообщений не было выведено, то нужно повторить пункты 1)-3) на другом файле из списка, полученного в пункте 1).
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ echo ""
clean_result

export LD_PRELOAD=./libfaad.so.2
COMMAND="$FUZZMANAGER --start $CORES -i in -o out -T Argv --config-file config_faad.json --no-inst-libs -- ./faad @@"
COMMAND="$FUZZMANAGER --start $CORES --eat-cores 1 --dse-cores 0 --dse-threads 0 -i in -o out -T Argv --config-file config_faad.json --no-inst-libs -- ./faad __DATA__"
echo $COMMAND
$COMMAND

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
52 changes: 52 additions & 0 deletions Examples/Crusher/Linux/firmware_x86_32/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Общее описание

Этот пример показывает фаззинг встраиваемого ПО архитектуры `x86-32`
на основе частичной эмуляции с помощью модифицированной `QEMU` и скриптов на языке `Lua`.

В поддиректории `firmware` находится тестируемое ПО (исходный и бинарный код).
В поддиректории `testing` - скрипты и материалы для запуска частичной эмуляции и фаззинга.

# Сборка

```shell
cd firmware
./build.sh
cd ..
```

В ходе эмуляции выполняется функция `func`

# Фаззинг

Находясь в директории `testing/`, запустить скрипт `./fuzz.sh`;
он принимает один аргумент - путь до `fuzz_manager`.

Запустить в другом терминале `UI` фаззера (укажите актуальные пути):
```shell
/path/to/crusher/bin_x86-64/ui --outdir /path/to/out
```

Как только будут найдены аварийные завершения, значение поля `unique_crashes` (в окне `UI` - наверху справа) станет ненулевым.

Прервать фаззинг (в первом терминале, `Ctrl + C`).

В данном примере фаззер обнаруживает два уникальных аварийных завершения,
соответствующие двум дефектам в ПО (см. исходный код).

# Эмуляция

Для запуска эмуляции - скрипт `./emulate.sh`;
он принимает один аргумент - путь до исполняемого файла `QEMU`;
входные данные находятся в файле `input`.

QEMU x86-32: `/path/to/crusher/bin_x86-64/QIT/QemuX86/qemu-system-i386`

# Воспроизведение аварийного завершения

Записать найденные фаззером вх.данные ав.завершения (например, `out/EAT_OUT/crashes/id_crash_0`)
в файл `input` и запустить эмуляцию (как описано выше).
В случае ав.завершения, т.е. при возникновении исключения,
будет напечатана информация об этом исключении
(слово `Exception`, значения регистров в этот момент и т.п.)

Более подробное описание см. в документации.
4 changes: 4 additions & 0 deletions Examples/Crusher/Linux/firmware_x86_32/firmware/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
gcc -m32 -c -no-pie -fno-pic test.c && \
ld -m elf_i386 -T test.ld test.o -o test.elf && \
objcopy -O binary test.elf test.bin && \
echo "OK"
Binary file not shown.
21 changes: 21 additions & 0 deletions Examples/Crusher/Linux/firmware_x86_32/firmware/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

void f(void) {
return;
}

void func(char *input) {
int *ptr = 0x41414141;
if (input[0] % 3 == 1) {
*ptr = 1;
}
if (input[0] % 3 == 2) {
*ptr = 2;
}
}

void entry()
{
func(0x20002000);
while(1);
}

Binary file not shown.
11 changes: 11 additions & 0 deletions Examples/Crusher/Linux/firmware_x86_32/firmware/test.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@


SECTIONS
{

. = 0x08000000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }

}
1 change: 1 addition & 0 deletions Examples/Crusher/Linux/firmware_x86_32/in/seed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c
Loading

0 comments on commit ea22394

Please sign in to comment.