Компания Amazon открыла исходные тексты инструментария Snapchange с реализацией метода fuzzing-тестирования срезов памяти, позволяющего организовать проверку исполняемых файлов без их модификации и без наличия исходного кода приложения. Snapchange даёт возможность загрузить дамп физической памяти с производным исполняемым кодом и организовать при помощи гипервизора KVM циклическое выполнение присутствующего в дампе кода, перебирая различных комбинации входных данных, отслеживая возникающие сбои или аномалии и перезапуская проверку после очередной итерации, каждый раз сбрасывая срез памяти и регистров CPU в исходное состояние. Код проекта написан на языке Rust и распространяется под лицензией Apache 2.0.
Сброс в исходное состояние и перезапуск итерации производится после аварийного завершения, таймаута или наступления определённого события. Входные данные подставляются непосредственно в память (вычисляется адрес памяти, куда записываются изменяемые параметры), а для экономии ресурсов при инициализации в исходное состояние памяти после выполнения очередной итерации определяется какие данные в памяти изменились и восстанавливается не вся память, а только изменившиеся области.
Исходный дамп памяти создаётся через сохранение снапшота виртуальной машины, в которой выполняется окружение с тестируемым приложением, запущенной под управлением VirtualBox или QEMU. Логика подстановки входных данных определяется через создание специальных сценариев, а позиция начала цикличного выполнения задаётся через выставление точки останова в отладчике.
Например, при необходимости проверки обработки различных состояний сетевого запроса, разработчик запускает приложение в гостевой системе
в VirtualBox или QEMU, в отладчике находит начало выполнение процедуры обработки запроса (например, следом за вызовом функции recv), ставит на него точку останова и определяет область памяти, в которой загружен полученный сетевой пакет. После этого создаётся снапшот гостевой системы и загружается в Snapchange. Для проверки пишется сценарий, который записывает данные при переборе непосредственно в буфер для сетевого пакета, что позволяет симулировать обработку реальных сетевых пакетов. Snapchange циклично возобновляет исполнение с прерванной позиции, каждый раз меняя содержимое данных в буфере и сбрасывая состояние памяти в исходное состояние.
Поддерживаются различные стратегии генерации входных данных. Возможен перебор с параллельным исполнением нескольких окружений, привязанным к разным ядрам CPU. Кроме выявления сбоев во время выполнения кода дополнительно поддерживается сбор метрик о производительности, накопление coverage-статистики для оценки охвата исполняемого кода или пошаговая трассировка исполняемого кода.
Одновременно компания Google опубликовала инструментарий Buzzer, предназначенный для fizzung-тестирования подсистемы eBPF, позволяющей запускать приложения внутри ядра Linux в специальной виртуальной машине с JIT. Buzzer генерирует случайные eBPF-программы, отслеживает реакцию ядра Linux при их выполнении и выявляет возникающие аномалии. Код проекта написан на языке Go и распространяется под лицензией Apache 2.0.
В качестве эффективности работы Buzzer продемонстрировано выявление в ядре Linux новой уязвимости (CVE-2023-2163), позволяющей локальному непривилегированному пользователю, имеющему возможность загрузки своей BPF-программы, записать (или прочитать) данные в любую область памяти ядра из-за ошибки при проверке передаваемых для выполнения eBPF-программ верификатором eBPF.
eBPF предоставляет встроенный в ядро интерпретатор байткода, дающий возможность через загружаемые из пространства пользователя обработчики на лету менять поведение системы без необходимости изменения кода ядра, что позволяет добавлять эффективные обработчики без усложнения самой системы. В том числе на базе eBPF можно создавать обработчики сетевых операций, управлять пропускной способностью, контролировать доступ, отслеживать работу систем и выполнять трассировку. Благодаря применению JIT-компиляции, байткод на лету транслируется в машинные инструкции и выполняется с производительностью нативного кода.