Nyxstone هي مكتبة تجميع وتفكيك قوية على أساس LLVM. لا يتطلب تصحيحات لشجرة مصدر LLVM والروابط مقابل مكتبات LLVM القياسية المتاحة في معظم توزيعات Linux. تم تنفيذه كمكتبة C ++ ، ويقدم Nyxstone أيضًا روابط الصدأ والثعبان. وهو يدعم جميع بنيات 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 ++ و Rust و Python.
قبل بناء 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. التثبيت هو نفسه بالنسبة لأوبونتو. للإصدارات 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 الخاص بك للربط الثابت. يمكن مشاهدتها باستخدام Command 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 كمكتبة Rust ، أضفها إلى 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 -q
>>> from nyxstone import Nyxstone
>>> nyxstone = Nyxstone("x86_64")
>>> nyxstone.assemble("jne .loop", 0x1100, {".loop": 0x1000})
تتوفر إرشادات مفصلة في ReadMe المقابلة.
تقوم NYXSONES بتعزيز وظائف API العامة C ++ من LLVM مثل Target::createMCAsmParser و Target::createMCDisassembler لأداء مهام التجميع والتفكيك. يمتد Nyxstone أيضًا فئتين LLVM ، MCELFStreamer و MCObjectWriter ، لضخ المنطق المخصص واستخراج معلومات إضافية. على وجه التحديد ، يعزز Nyxstone عملية التجميع مع الخطوات التالية:
ELFStreamerWrapper::emitInstruction : التقاط تمثيل التجميع والبايتات الأولية الأولية للتعليمات إذا تم طلب كائنات التعليمات المفصلة من قبل المستخدم.
ObjectWriterWrapper::writeObject : يكتب بايتات RAW النهائية للتعليمات (مع تعديلات النقل) إلى كائنات تعليمية مفصلة. علاوة على ذلك ، فإنه يقوم بتبديل إخراج البايتات الخام من ملف ELF الكامل إلى قسم النص.
ObjectWriterWrapper::validate_fixups : يجري عمليات فحص إضافية ، مثل التحقق من نطاق ومواءمة عمليات النقل.
ObjectWriterWrapper::recordRelocation : يطبق عمليات نقل إضافية. يتخطى MCObjectWriter بعض عمليات الترحيل التي يتم تطبيقها فقط أثناء الارتباط. في الوقت الحالي ، يكون هذا مناسبًا فقط لترحيل fixup_aarch64_pcrel_adrp_imm21 لتعليمات AARCH64 adrp .
في حين أن توسيع فئات LLVM تقدم بعض العيوب ، مثل الاعتماد القوي على إصدار LLVM محدد ، نعتقد أن هذا النهج لا يزال مفضلاً على البدائل التي تتطلب صعوبة في الحفاظ على بقع في شجرة مصدر LLVM.
نحن ملتزمون بزيادة تقليل تعقيد المشروع ومفتوح للاقتراحات للتحسين. بالنظر إلى المستقبل ، قد نقضي على الحاجة إلى تمديد فصول LLVM من خلال الاستفادة من البنية التحتية LLVM الحالية بطريقة أكثر ذكاءً أو دمج منطق إضافي في خطوة ما بعد المعالجة.
فيما يلي بعض الأفكار والتحسينات التي نعتقد أنها ستقدم بشكل كبير Nyxstone. العناصر غير مدرجة بأي ترتيب معين:
تحقق من سلامة الموضوع
أضف دعمًا لمزيد من إصدارات LLVM (حدد تلقائيًا اعتمادًا على إصدار مكتبة LLVM الموجود)
استكشف خيار جعل LLVM تطبيق جميع عمليات نقل (بما في ذلك adrp ) من خلال تكوين MCObjectWriter بشكل مختلف أو باستخدام كاتب مختلف
استكشف خيار إنشاء كائنات تعليمات مفصلة عن طريق تفكيك إخراج البايتات الخام لعملية التجميع بدلاً من الاعتماد على تمديد فئات LLVM
استكشف خيار تنفيذ نطاق إضافي ومحاذاة عمليات نقل في خطوة ما بعد المعالجة بدلاً من الاعتماد على تمديد فئات LLVM
Nyxstone متاح تحت رخصة معهد ماساتشوستس للتكنولوجيا.
نرحب بالمساهمات من المجتمع! إذا واجهت أي مشكلات مع Nyxstone ، فلا تتردد في فتح مشكلة github.
إذا كنت مهتمًا بالمساهمة مباشرة في المشروع ، فيمكنك على سبيل المثال:
بمجرد أن تكون جاهزًا ، أرسل طلب سحب مع تغييراتك. نتطلع إلى مساهمتك!
المساهمون الحاليون هم:
جوهر :
صغير :
للتأكد من أننا نربط LLVM بشكل صحيح مع الإصدار المناسب في الصدأ ، قمنا بتكييف Build.rs من LLVM-SYS.