Nyxstone - это мощная библиотека сборки и разборки на основе LLVM. Он не требует исправлений для дерева источника LLVM и ссылки на стандартные библиотеки LLVM, доступные в большинстве распределений Linux. Реализованный как библиотека C ++, Nyxstone также предлагает привязок Rust и Python. Он поддерживает все официальные архитектуры LLVM и позволяет настроить настройки целевых настройки, специфичных для архитектуры.
Собирает и разбирает код для всех архитектур, поддерживаемых связанным LLVM, включая X86, ARM, MIPS, RISC-V и другие.
Библиотека C ++ на основе LLVM с привязками ржавчины и питона.
Поддержка нативной платформы Linux и MacOS.
Поддерживает этикетки в ассемблере, включая спецификацию отображений с меткой-адресом
Сборка и разобрать в необработанных байтах и текста, но также предоставляет подробные объекты инструкции, содержащие адрес, необработанные байты и представление сборки.
Разборка может быть ограничена определенным пользователем количеством инструкций из байтовых последовательностей.
Позволяет настроить целевые функции, специфичные для архитектуры, такие как расширения ISA и аппаратные функции.
Для комплексного списка поддерживаемых архитектур вы можете использовать clang -print-targets . Для полного списка функций для каждой архитектуры llc -march=ARCH -mattr=help .
Примечание
Отказ от ответственности: Nyxstone был в основном разработан и протестирован для архитектур x86_64, Aarch64 и ARM32. Мы обладаем высокой степенью уверенности в его способности точно генерировать сборку и выявлять ошибки для этих платформ. Для других архитектур эффективность Nyxstone зависит от надежности и эффективности их соответствующих бэкэнд LLVM.
В этом разделе представлены инструкции о том, как начать работу с Nyxstone, охватывая необходимые предпосылки, как использовать инструмент CLI, и пошаговые рекомендации по использованию библиотеки с C ++, ржавчиной и питоном.
Прежде чем строить Nyxstone, убедитесь, что в вашей системе присутствуют Clang и LLVM. Nyxstone поддерживает основные версии LLVM 15-18. При строительстве он ищет llvm-config в $PATH вашей системы или указанной переменной среды $NYXSTONE_LLVM_PREFIX/bin .
Параметры установки для версий LLVM 15-18:
sudo apt install llvm- ${version} llvm- ${version} -devDebian LLVM версии 15 и 16 доступны через репозитории Debian. Установка такая же, как и для Ubuntu. Для версий 17 или 18 см. Https://apt.llvm.org/ для инструкций по установке.
Архи
sudo pacman -S llvm llvm-libsbrew install llvm@18
export NYXSTONE_LLVM_PREFIX=/opt/homebrew/opt/llvm@18 Примечание . В Windows необходимо запустить эти команды из командной строки Visual Studio 2022 X64. Кроме того, замените ~lib/my-llvm-18 на другой путь.
# checkout llvm
git clone -b release/18.x --single-branch https://github.com/llvm/llvm-project.git
cd llvm-project
# build LLVM with custom installation directory
cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_PARALLEL_LINK_JOBS=1
cmake --build build
cmake --install build --prefix ~ /lib/my-llvm-18
# export path
export NYXSTONE_LLVM_PREFIX= ~ /lib/my-llvm-18 Также обязательно установите любые системные библиотеки, необходимые для вашей версии LLVM для статического связывания. Их можно просмотреть с помощью команды llvm-config --system-libs ; Список может быть пустым. На Ubuntu/Debian вам понадобятся пакеты zlib1g-dev и zlibstd-dev .
Nyxstone поставляется с удобным инструментом CLI для быстрой сборки и разборки. Ознакомьтесь с репозиторием Nyxstone и создайте инструмент с Cmake:
# clone directory
git clone https://github.com/emproof-com/nyxstone
cd nyxstone
# build nyxstone
mkdir build && cd build && cmake .. && make Затем nyxstone можно использовать из командной строки. Вот результат его меню помощи:
$ ./nyxstone -h
Usage: nyxstone [-t=<triple>] [-p=<pc>] [-d] <input>
Examples:
# Assemble an instruction with the default architecture ('x86_64').
nyxstone 'push eax'
# Disassemble the bytes 'ffc300d1' as AArch64 code.
nyxstone -t aarch64 -d ffc300d1
Options:
-t, --triple=<triple> LLVM target triple or alias, e.g. 'aarch64'
-c, --cpu=<cpu> LLVM CPU specifier, e.g. 'cortex-a53'
-f, --features=<list> LLVM architecture/CPU feature list, e.g. '+mte,-neon'
-p, --address=<pc> Initial address to assemble/disassemble relative to
-l, --labels=<list> Label-to-address mappings (used when assembling only)
-d, --disassemble Treat <input> as bytes to disassemble instead of assembly
-h, --help Show this help and usage message
Notes:
The '--triple' parameter also supports aliases for common target triples:
'x86_32' -> 'i686-linux-gnu'
'x86_64' -> 'x86_64-linux-gnu'
'armv6m' -> 'armv6m-none-eabi'
'armv7m' -> 'armv7m-none-eabi'
'armv8m' -> 'armv8m.main-none-eabi'
'aarch64' -> 'aarch64-linux-gnueabihf'
The CPUs for a target can be found with 'llc -mtriple=<triple> -mcpu=help'.
The features for a target can be found with 'llc -mtriple=<triple> -mattr=help'.
Теперь мы можем собрать инструкцию для архитектуры x86_64:
$ ./nyxstone -t x86_64 "mov rax, rbx"
0x00000000: mov rax, rbx ; 48 89 d8
Мы также можем собрать последовательность инструкций. Далее мы используем адресацию на основе меток и предполагаем, что первая инструкция отображается для адреса 0xdeadbeef :
$ ./nyxstone -t x86_64 -p 0xdeadbeef "cmp rax, rbx; jz .exit; inc rax; .exit: ret"
0xdeadbeef: cmp rax, rbx ; 48 39 d8
0xdeadbef2: je .exit ; 74 03
0xdeadbef4: inc rax ; 48 ff c0
0xdeadbef7: ret ; c3
Кроме того, мы можем разобрать инструкции для различных наборов инструкций, здесь набор инструкций ARM32
$ ./nyxstone -t thumbv8 -d "13 37"
0x00000000: adds r7, #19 ; 13 37
Используя поддержку пользовательских меток, мы можем собрать этот фрагмент, который не содержит метку .label
$ ./nyxstone -p "0x1000" -l ".label=0x1238" "jmp .label"
0x00001000: jmp .label ; e9 33 02 00 00
Чтобы использовать Nyxstone в качестве библиотеки C ++, ваш код C ++ должен быть связан с Nyxstone и LLVM.
Следующий пример Cmake предполагает Nyxstone в подканальном nyxstone в вашем проекте:
add_subdirectory (nyxstone)
add_executable (my_executable main.cpp)
target_link_libraries (my_executable nyxstone::nyxstone)Соответствующий пример использования C ++:
# include < cassert >
# include < iostream >
# include " nyxstone.h "
int main ( int , char **) {
// Create the nyxstone instance:
auto nyxstone {
NyxstoneBuilder ( " x86_64 " )
. build ()
. value ()
};
// Assemble to bytes
std::vector< uint8_t > bytes =
nyxstone-> assemble ( /* assembly= */ " mov rax, rbx " , /* address= */ 0x1000 , /* labels= */ {}). value ();
std::vector< uint8_t > expected { 0x48 , 0x89 , 0xd8 };
assert (bytes == expected);
return 0 ;
}Для получения комплексного примера C ++ взгляните на example.cpp.
Чтобы использовать Nyxstone в качестве библиотеки ржавчины, добавьте его в свой Cargo.toml и используйте его, как показано в следующем примере:
use anyhow :: Result ;
use nyxstone :: { Nyxstone , NyxstoneConfig } ;
use std :: collections :: HashMap ;
fn main ( ) -> Result < ( ) > {
let nyxstone = Nyxstone :: new ( "x86_64" , NyxstoneConfig :: default ( ) ) ? ;
let bytes = nyxstone . assemble_with (
"mov rax, rbx; cmp rax, rdx; jne .label" ,
0x1000 ,
& HashMap :: from ( [ ( ".label" , 0x1200 ) ] ) ,
) ? ;
println ! ( "Bytes: {:x?}" , bytes ) ;
Ok ( ( ) )
}Для получения дополнительных инструкций, касающихся привязки ржавчины, посмотрите на соответствующую Readme.
Чтобы использовать Nyxstone из Python, установите его с помощью PIP:
pip install nyxstoneЗатем вы можете использовать его из Python:
$ python -q
>>> from nyxstone import Nyxstone
>>> nyxstone = Nyxstone("x86_64")
>>> nyxstone.assemble("jne .loop", 0x1100, {".loop": 0x1000})
Подробные инструкции доступны в соответствующем Readme.
Nyxstone использует публичные функции API C ++ от LLVM, такие как Target::createMCAsmParser и Target::createMCDisassembler для выполнения задач сборки и разборки. Nyxstone также расширяет два класса LLVM, MCELFStreamer и MCObjectWriter , чтобы внедрить пользовательскую логику и извлечь дополнительную информацию. В частности, Nyxstone увеличивает процесс сборки следующими шагами:
ELFStreamerWrapper::emitInstruction : захватывает представление об сборе и начальные необработанные байты инструкций, если пользователь запрашивается подробные объекты инструкции.
ObjectWriterWrapper::writeObject : записывает окончательные необработанные байты инструкций (с настройками перемещения) для подробных объектов инструкции. Кроме того, он переключает вывод необработанных байтов из полного файла ELF только на раздел .Text.
ObjectWriterWrapper::validate_fixups : проводят дополнительные проверки, такие как проверка диапазона и выравнивание переездов.
ObjectWriterWrapper::recordRelocation : применяет дополнительные переезды. MCObjectWriter пропускает некоторые перемещения, которые применяются только во время связывания. Прямо сейчас это имеет значение только для fixup_aarch64_pcrel_adrp_imm21 Перемещение инструкции AARCH64 adrp .
Хотя расширение классов LLVM представляет некоторые недостатки, например, сильную зависимость от конкретной версии LLVM, мы считаем, что этот подход по -прежнему предпочтительнее по сравнению с альтернативами, которые требуют трудных для поддержания пятен в дереве источника LLVM.
Мы стремимся к дальнейшему сокращению сложности проекта и открыты для предложений по улучшению. Заглядывая в будущее, мы можем устранить необходимость расширения классов LLVM путем более умного использования существующей инфраструктуры LLVM или включить дополнительную логику на шаг после обработки.
Ниже приведены некоторые идеи и улучшения, которые, по нашему мнению, будут значительно продвигать Nyxstone. Элементы не указаны в каком -либо конкретном порядке:
Проверьте безопасность потока
Добавьте поддержку для большего количества версий LLVM (Auto Select в зависимости от найденной версии библиотеки LLVM)
Изучите опцию, чтобы заставить LLVM применить все перемещения (включая adrp ) путем настройки MCObjectWriter по -разному или используя другого автора
Изучите опцию для создания подробных инструкций объектов путем разборки вывода необработанных байтов процесса сборки вместо того, чтобы полагаться на расширение классов LLVM
Изучите опцию для реализации дополнительного диапазона и выравнивания переездов на этапе после обработки, а не полагаться на расширение классов LLVM
Nyxstone доступен по лицензии MIT.
Мы приветствуем вклад сообщества! Если вы столкнетесь с какими -либо проблемами с Nyxstone, пожалуйста, не стесняйтесь открывать проблему GitHub.
Если вы заинтересованы в том, чтобы внести непосредственный вклад в проект, вы можете, например:
Как только вы будете готовы, отправьте запрос на привлечение с вашими изменениями. Мы с нетерпением ждем вашего вклада!
Текущие участники:
Основной :
Незначительный :
Чтобы убедиться, что мы правильно связываем LLVM с правильным управлением версией в Rust, мы адаптировали Build.rs из LLVM-Sys.