Nyxstone은 LLVM을 기반으로 한 강력한 어셈블리 및 분해 라이브러리입니다. LLVM 소스 트리에 대한 패치가 필요하지 않으며 대부분의 Linux 배포판에서 사용 가능한 표준 LLVM 라이브러리에 대한 링크가 필요하지 않습니다. C ++ 라이브러리로 구현 된 Nyxstone은 녹 및 파이썬 바인딩도 제공합니다. 모든 공식 LLVM 아키텍처를 지원하고 아키텍처 별 대상 설정을 구성 할 수 있습니다.
X86, ARM, MIPS, RISC-V 등을 포함하여 링크 된 LLVM이 지원하는 모든 아키텍처에 대한 코드를 조립 및 분해합니다.
녹 및 파이썬 바인딩이있는 LLVM을 기반으로 한 C ++ 라이브러리.
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을 지원합니다. 빌드 할 때 시스템의 $PATH 또는 지정된 환경 변수 $NYXSTONE_LLVM_PREFIX/bin 에서 llvm-config 찾습니다.
LLVM 버전의 설치 옵션 15-18 :
sudo apt install llvm- ${version} llvm- ${version} -dev데비안 LLVM 버전 15 및 16은 데비안 리포지토리를 통해 제공됩니다. 설치는 우분투와 동일합니다. 버전 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 명령으로 볼 수 있습니다. 목록이 비어있을 수 있습니다. 우분투/데비안에는 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
또한 다른 명령어 세트에 대한 지침을 분해 할 수 있습니다.
$ ./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를 살펴보십시오.
Python의 Nyxstone을 사용하려면 PIP를 사용하여 설치하십시오.
pip install nyxstone그런 다음 Python에서 사용할 수 있습니다.
$ python -q
>>> from nyxstone import Nyxstone
>>> nyxstone = Nyxstone("x86_64")
>>> nyxstone.assemble("jne .loop", 0x1100, {".loop": 0x1000})
자세한 지침은 해당 ReadMe에서 제공됩니다.
Nyxstone은 Target::createMCAsmParser 및 Target::createMCDisassembler 와 같은 LLVM의 공개 C ++ API 기능을 활용하여 조립 및 분해 작업을 수행합니다. Nyxstone은 또한 MCELFStreamer 와 MCObjectWriter 의 두 LLVM 클래스를 연장하여 사용자 정의 논리를 주입하고 추가 정보를 추출합니다. 특히 Nyxstone은 다음 단계로 조립 프로세스를 보강합니다.
ELFStreamerWrapper::emitInstruction : 사용자가 상세한 명령 개체를 요청하는 경우 조립 표현 및 초기 원시 바이트를 캡처합니다.
ObjectWriterWrapper::writeObject : 최종 원시 바이트 (재배치 조정 포함)를 상세한 명령 개체에 씁니다. 또한 완전한 엘프 파일에서 .text 섹션으로 원시 바이트 출력을 전환합니다.
ObjectWriterWrapper::validate_fixups : 범위 확인 및 재배치 정렬과 같은 추가 점검을 수행합니다.
ObjectWriterWrapper::recordRelocation : 추가 이전을 적용합니다. MCObjectWriter 연결 중에만 적용되는 일부 재배치를 건너 뜁니다. 지금, 이것은 aarch64 명령어 adrp 의 fixup_aarch64_pcrel_adrp_imm21 재배치와 관련이 있습니다.
LLVM 클래스를 확장하면 특정 LLVM 버전에 대한 강한 의존성과 같은 몇 가지 단점이 소개되지만 LLVM 소스 트리에서 패치를 유지하기가 어려운 대안 보다이 접근법이 여전히 바람직하다고 생각합니다.
우리는 프로젝트의 복잡성을 더욱 줄이고 개선을위한 제안에 개방하기 위해 최선을 다하고 있습니다. 앞으로 기존 LLVM 인프라를 더 똑똑한 방식으로 활용하거나 후 처리 단계에 추가 논리를 통합하여 LLVM 클래스를 확장 할 필요가 없을 수 있습니다.
다음은 Nyxstone을 크게 발전시킬 것이라고 생각하는 몇 가지 아이디어와 개선 사항입니다. 항목은 특정 순서로 나열되지 않습니다.
스레드 안전을 확인하십시오
더 많은 LLVM 버전에 대한 지원 추가 (발견 된 LLVM 라이브러리 버전에 따라 자동 선택)
MCObjectWriter adrp 구성하거나 다른 작가를 사용하여 LLVM을 모두 적용하도록하는 옵션 탐색
LLVM 클래스의 확장에 의존하는 대신 어셈블리 프로세스의 원시 바이트 출력을 분해하여 상세한 지침 객체를 생성하는 옵션 탐색
LLVM 클래스의 확장에 의존하는 대신 후 처리 단계에서 추가 범위를 구현하고 재배치 정렬을 구현하는 옵션을 탐색하십시오.
Nyxstone은 MIT 라이센스에 따라 제공됩니다.
우리는 지역 사회의 기여를 환영합니다! Nyxstone과 관련된 문제가 발생하면 Github 문제를 자유롭게 열어주십시오.
프로젝트에 직접 기여하는 데 관심이 있으시면 예를 들어 다음과 같은 경우가 있습니다.
준비가되면 변경 사항에 따라 풀 요청을 제출하십시오. 우리는 당신의 기여를 고대하고 있습니다!
현재 기고자는 다음과 같습니다.
핵심 :
미성년자 :
LLVM을 Rust의 적절한 버전화와 올바르게 연결하기 위해 LLVM-SYS에서 Build.rs를 조정했습니다.