Nyxstone ist eine leistungsstarke Versammlungs- und Demontage -Bibliothek, die auf LLVM basiert. Es sind keine Patches für den LLVM -Quellbaum erforderlich und Links mit Standard -LLVM -Bibliotheken, die in den meisten Linux -Verteilungen verfügbar sind. Nyxstone wird als C ++ - Bibliothek implementiert und bietet auch Rost- und Python -Bindungen. Es unterstützt alle offiziellen LLVM-Architekturen und ermöglicht die Konfiguration der architekturspezifischen Zieleinstellungen.
Zusammenstellen und Disassembles Code für alle Architekturen, die von der verknüpften LLVM unterstützt werden, einschließlich X86, Arm, MIPS, RISC-V und anderen.
C ++ Bibliothek basierend auf LLVM mit Rost- und Python -Bindungen.
Native Plattform -Unterstützung für Linux und MacOS.
Unterstützt Etiketten im Assembler, einschließlich der Spezifikation von Label-zu-Addesse-Mappings
Montage und Disassembles zu rohen Bytes und Text, enthält jedoch auch detaillierte Befehlsobjekte, die die Adresse, Rohbytes und die Montagedarstellung enthalten.
Die Demontage kann auf eine benutzerdefinierte Anzahl von Anweisungen aus Byte-Sequenzen beschränkt werden.
Ermöglicht die Konfiguration von architekturspezifischen Zielfunktionen wie ISA-Erweiterungen und Hardwarefunktionen.
Für eine umfassende Liste unterstützter Architekturen können Sie clang -print-targets verwenden. Eine umfassende Liste von Funktionen für jede Architektur finden Sie in llc -march=ARCH -mattr=help .
Notiz
Haftungsausschluss: Nyxstone wurde in erster Linie für Architekturen X86_64, AArch64 und ARM32 entwickelt und getestet. Wir haben ein hohes Maß an Vertrauen in seine Fähigkeit, Montage genau zu generieren und Fehler für diese Plattformen zu identifizieren. Für andere Architekturen hängt die Wirksamkeit von Nyxstone von der Zuverlässigkeit und Leistung ihrer jeweiligen LLVM -Backends ab.
Dieser Abschnitt enthält Anweisungen zum Einstieg mit NYXSTONE, der erforderlichen Voraussetzungen, der Verwendung des CLI-Tools und Schritt-für-Schritt-Richtlinien für die Verwendung der Bibliothek mit C ++, Rost und Python.
Stellen Sie vor dem Bau von Nyxstone sicher, dass Clang und LLVM in Ihrem System vorhanden sind. NYXSTONE unterstützt LLVM-Hauptversionen 15-18. Beim Erstellen von llvm-config im $PATH oder der angegebenen Umgebungsvariablen $NYXSTONE_LLVM_PREFIX/bin sucht es nach dem Erstellen von LLVM-Config.
Installationsoptionen für LLVM-Versionen 15-18:
sudo apt install llvm- ${version} llvm- ${version} -devDebian LLVM Version 15 und 16 sind über Debian -Repositories erhältlich. Die Installation ist die gleiche wie bei Ubuntu. Informationen zu den Versionen 17 oder 18 finden Sie unter https://apt.llvm.org/ für Installationsanweisungen.
Bogen
sudo pacman -S llvm llvm-libsbrew install llvm@18
export NYXSTONE_LLVM_PREFIX=/opt/homebrew/opt/llvm@18 Hinweis : Unter Windows müssen Sie diese Befehle aus einer Eingabeaufforderung für Visual Studio 2022 X64 ausführen. Ersetzen Sie zusätzlich ~lib/my-llvm-18 durch einen anderen Weg.
# 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 Stellen Sie außerdem sicher, dass Sie alle systemabhängigen Bibliotheken installieren, die von Ihrer LLVM -Version für die statische Verknüpfung benötigt werden. Sie können mit dem Befehl llvm-config --system-libs betrachtet werden; Die Liste kann leer sein. Auf Ubuntu/Debian benötigen Sie die Pakete zlib1g-dev und zlibstd-dev .
Nyxstone verfügt über ein praktisches CLI -Werkzeug für schnelle Montage- und Demontagesaufgaben. Schauen Sie sich das NYXSTONE -Repository an und erstellen Sie das Tool mit CMake:
# clone directory
git clone https://github.com/emproof-com/nyxstone
cd nyxstone
# build nyxstone
mkdir build && cd build && cmake .. && make Dann kann nyxstone aus der Befehlszeile verwendet werden. Hier ist eine Ausgabe des Hilfesmenüs:
$ ./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'.
Jetzt können wir eine Anweisung für die x86_64 -Architektur zusammenstellen:
$ ./nyxstone -t x86_64 "mov rax, rbx"
0x00000000: mov rax, rbx ; 48 89 d8
Wir können auch eine Folge von Anweisungen zusammenstellen. Im Folgenden verwenden wir eine markierungsbasierte Adressierung und nehmen an, dass die erste Anweisung auf die Adresse 0xdeadbeef zugeordnet ist:
$ ./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
Darüber hinaus können wir Anweisungen für verschiedene Anweisungssätze zerlegen, hier der ARM32 -Daumenanweisungssatz:
$ ./nyxstone -t thumbv8 -d "13 37"
0x00000000: adds r7, #19 ; 13 37
Unter Verwendung der Unterstützung für benutzerdefinierte Beschriftungen können wir dieses Snippet zusammenstellen, das das Label .label nicht enthält, indem wir den Speicherort angeben.
$ ./nyxstone -p "0x1000" -l ".label=0x1238" "jmp .label"
0x00001000: jmp .label ; e9 33 02 00 00
Um NYXstone als C ++ - Bibliothek zu verwenden, muss Ihr C ++ - Code mit NYXstone und LLVM verknüpft werden.
Das folgende CMAKE -Beispiel wird Nyxstone in einem nyxstone in Ihrem Projekt angenommen:
add_subdirectory (nyxstone)
add_executable (my_executable main.cpp)
target_link_libraries (my_executable nyxstone::nyxstone)Das entsprechende C ++ - Verwendungsbeispiel:
# 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 ;
}Für ein umfassendes C ++ - Beispiel sehen Sie sich ein Beispiel an.cpp an.
Um Nyxstone als Rust -Bibliothek zu verwenden, fügen Sie sie Ihrer Cargo.toml hinzu und verwenden Sie sie wie im folgenden Beispiel gezeigt:
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 ( ( ) )
}Weitere Anweisungen zur Rostbindung finden Sie im entsprechenden Readme.
Um Nyxstone von Python zu verwenden, installieren Sie es mit PIP:
pip install nyxstoneDann können Sie es von Python verwenden:
$ python -q
>>> from nyxstone import Nyxstone
>>> nyxstone = Nyxstone("x86_64")
>>> nyxstone.assemble("jne .loop", 0x1100, {".loop": 0x1000})
In der entsprechenden Readme finden Sie detaillierte Anweisungen.
Nyxstone nutzt die öffentlichen C ++ - API -Funktionen von LLVM wie Target::createMCAsmParser und Target::createMCDisassembler , um Assembly- und Demontageaufgaben auszuführen. NYXSTONE erweitert auch zwei LLVM -Klassen, MCELFStreamer und MCObjectWriter , um benutzerdefinierte Logik zu injizieren und zusätzliche Informationen zu extrahieren. Insbesondere erhöht Nyxstone den Montageprozess mit den folgenden Schritten:
ELFStreamerWrapper::emitInstruction : Erfasst die Montagedarstellung und anfängliche Rohbytes von Anweisungen Wenn detaillierte Anweisungsobjekte vom Benutzer angefordert werden.
ObjectWriterWrapper::writeObject : schreibt die endgültigen rohen Bytes von Anweisungen (mit Umzugsanpassungen) in detaillierte Anweisungsobjekte. Darüber hinaus wechselt es die Ausgabe von Roh -Bytes von der vollständigen ELF -Datei auf nur den .Text -Abschnitt.
ObjectWriterWrapper::validate_fixups : Führen Sie zusätzliche Überprüfungen durch, z.
ObjectWriterWrapper::recordRelocation : Wendet zusätzliche Umzugsumschüsse an. MCObjectWriter überspringt einige Umzug, die nur während der Verknüpfung angewendet werden. Derzeit ist dies nur für die Verschiebung des AARCH64 -Anweisungen adrp relevant für die fixup_aarch64_pcrel_adrp_imm21 RELOCATION.
Während die Erweiterung von LLVM -Klassen einige Nachteile einführt, wie z.
Wir sind bestrebt, die Komplexität des Projekts weiter zu reduzieren und für Verbesserungsvorschläge zu offenbaren. Mit Blick auf die Zukunft können wir die Notwendigkeit beseitigen, LLVM-Klassen zu erweitern, indem wir die vorhandene LLVM-Infrastruktur auf intelligentere Weise nutzen oder zusätzliche Logik in einen Nachbearbeitungsschritt einbeziehen.
Im Folgenden finden Sie einige Ideen und Verbesserungen, von denen wir glauben, dass sie Nyxstone erheblich vorantreiben würden. Die Elemente sind nicht in einer bestimmten Reihenfolge aufgeführt:
Überprüfen Sie die Gewindesicherheit
Fügen Sie Unterstützung für weitere LLVM -Versionen hinzu (automatisch wählen Sie abhängig von der gefundenen LLVM -Bibliotheksversion.
Erforschen Sie die Option, um LLVM alle Umzüge (einschließlich adrp ) anzuwenden, indem Sie MCObjectWriter anders konfigurieren oder einen anderen Schriftsteller verwenden
Erforschen
Erforschen
Nyxstone ist unter der MIT -Lizenz erhältlich.
Wir begrüßen Beiträge aus der Community! Wenn Sie auf Probleme mit Nyxstone stoßen, können Sie bitte ein GitHub -Problem eröffnen.
Wenn Sie daran interessiert sind, direkt zum Projekt beizutragen, können Sie beispielsweise:
Sobald Sie fertig sind, senden Sie eine Pull -Anfrage mit Ihren Änderungen. Wir freuen uns auf Ihren Beitrag!
Die aktuellen Mitwirkenden sind:
Kern :
Unerheblich :
Um sicherzustellen, dass wir LLVM korrekt mit ordnungsgemäßem Versioning in Rost verknüpfen, haben wir den Build.rs von LLVM-Sys angepasst.