NYXSTONE เป็นห้องสมุดที่ทรงพลังและไลบรารี่ถอดชิ้นส่วนตาม LLVM ไม่จำเป็นต้องใช้แพตช์ไปยังแผนผังต้นทาง LLVM และลิงก์กับไลบรารี LLVM มาตรฐานที่มีอยู่ในการแจกแจง Linux ส่วนใหญ่ นำมาใช้เป็นไลบรารี C ++ Nyxstone ยังมีการผูกสนิมและ Python รองรับสถาปัตยกรรม LLVM อย่างเป็นทางการทั้งหมดและอนุญาตให้กำหนดค่าการตั้งค่าเป้าหมายเฉพาะสถาปัตยกรรม
การประกอบและถอดความรหัสสำหรับสถาปัตยกรรมทั้งหมดที่สนับสนุนโดย LLVM ที่เชื่อมโยงรวมถึง X86, ARM, MIPS, RISC-V และอื่น ๆ
ไลบรารี C ++ ขึ้นอยู่กับ LLVM ที่มีการผูกสนิมและงูเหลือม
รองรับแพลตฟอร์มดั้งเดิมสำหรับ Linux และ MacOS
รองรับฉลากในแอสเซมเบลอ
การประกอบและแยกชิ้นส่วนเป็นไบต์และข้อความดิบ แต่ยังให้วัตถุคำสั่งโดยละเอียดที่มีที่อยู่ไบต์ดิบและการเป็นตัวแทนประกอบ
การถอดประกอบสามารถ จำกัด จำนวนคำสั่งที่ระบุจากผู้ใช้จากลำดับ BYTE
อนุญาตให้กำหนดค่าคุณสมบัติเป้าหมายเฉพาะสถาปัตยกรรมเช่นส่วนขยาย ISA และคุณสมบัติฮาร์ดแวร์
สำหรับรายการสถาปัตยกรรมที่รองรับที่ครอบคลุมคุณสามารถใช้ clang -print-targets สำหรับรายการคุณสมบัติที่ครอบคลุมสำหรับแต่ละสถาปัตยกรรมโปรดดูที่ llc -march=ARCH -mattr=help
บันทึก
ข้อจำกัดความรับผิดชอบ: Nyxstone ได้รับการพัฒนาและทดสอบเป็นหลักสำหรับสถาปัตยกรรม X86_64, AARCH64 และ ARM32 เรามีความมั่นใจในระดับสูงในความสามารถในการสร้างแอสเซมบลีอย่างถูกต้องและระบุข้อผิดพลาดสำหรับแพลตฟอร์มเหล่านี้ สำหรับสถาปัตยกรรมอื่น ๆ ประสิทธิภาพของ Nyxstone ขึ้นอยู่กับความน่าเชื่อถือและประสิทธิภาพของแบ็กเอนด์ LLVM ที่เกี่ยวข้อง
ส่วนนี้ให้คำแนะนำเกี่ยวกับวิธีการเริ่มต้นด้วย NYXSTONE ครอบคลุมข้อกำหนดเบื้องต้นที่จำเป็นวิธีใช้เครื่องมือ CLI และแนวทางทีละขั้นตอนสำหรับการใช้ห้องสมุดกับ C ++, Rust และ Python
ก่อนที่จะสร้าง Nyxstone ให้แน่ใจว่ามีการส่งเสียงดังและ LLVM ในระบบของคุณ Nyxstone รองรับ LLVM Major Versions 15-18 เมื่อสร้างมันมองหา llvm-config ใน $PATH ของระบบของคุณหรือตัวแปรสภาพแวดล้อมที่ระบุ $NYXSTONE_LLVM_PREFIX/bin
ตัวเลือกการติดตั้งสำหรับเวอร์ชัน LLVM 15-18:
sudo apt install llvm- ${version} llvm- ${version} -devDebian LLVM เวอร์ชัน 15 และ 16 มีให้บริการผ่าน Debian Repositories การติดตั้งเหมือนกับ 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 ใช้ประโยชน์จากฟังก์ชั่น C ++ API สาธารณะจาก LLVM เช่น Target::createMCAsmParser และ Target::createMCDisassembler เพื่อดำเนินการประกอบงานและถอดชิ้นส่วน NYXSTONE ยังขยายคลาส LLVM สองคลาสคือ MCELFStreamer และ MCObjectWriter เพื่อฉีดตรรกะที่กำหนดเองและแยกข้อมูลเพิ่มเติม โดยเฉพาะ Nyxstone เพิ่มกระบวนการประกอบด้วยขั้นตอนต่อไปนี้:
ELFStreamerWrapper::emitInstruction : จับภาพการเป็นตัวแทนของแอสเซมบลีและคำสั่งดิบเริ่มต้นของคำแนะนำหากผู้ใช้คำสั่งโดยละเอียด
ObjectWriterWrapper::writeObject : เขียนคำแนะนำขั้นสุดท้ายของคำแนะนำ (พร้อมการปรับเปลี่ยนการย้ายถิ่นฐาน) ไปยังวัตถุคำสั่งโดยละเอียด นอกจากนี้ยังเปลี่ยนเอาต์พุตไบต์ดิบจากไฟล์ 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 มีให้บริการภายใต้ใบอนุญาต MIT
เรายินดีต้อนรับการมีส่วนร่วมจากชุมชน! หากคุณพบปัญหาใด ๆ กับ NYXSTONE โปรดเปิดปัญหา GitHub
หากคุณสนใจที่จะมีส่วนร่วมโดยตรงกับโครงการคุณสามารถทำได้เช่น:
เมื่อคุณพร้อมแล้วให้ส่งคำขอดึงพร้อมกับการเปลี่ยนแปลงของคุณ เรารอคอยที่จะมีส่วนร่วมของคุณ!
ผู้มีส่วนร่วมในปัจจุบันคือ:
หลัก :
ส่วนน้อย :
เพื่อให้แน่ใจว่าเราเชื่อมโยง LLVM อย่างถูกต้องด้วยการกำหนดเวอร์ชันที่เหมาะสมในการเกิดสนิมเราได้ปรับสร้าง Build.rs จาก LLVM-SYS