Add RISC-V support to libafl_unicorn (#3134)
This commit is contained in:
parent
8426ba5d58
commit
ec24513c95
@ -12,7 +12,7 @@ runs:
|
|||||||
with: { shared-key: "${{ runner.os }}-shared-fuzzer-cache" }
|
with: { shared-key: "${{ runner.os }}-shared-fuzzer-cache" }
|
||||||
- name: Install fuzzers deps
|
- name: Install fuzzers deps
|
||||||
shell: bash
|
shell: bash
|
||||||
run: sudo apt-get update && sudo apt-get install -y nasm nlohmann-json3-dev gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils python3-msgpack python3-jinja2
|
run: sudo apt-get update && sudo apt-get install -y nasm nlohmann-json3-dev gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-riscv64-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils python3-msgpack python3-jinja2
|
||||||
- name: enable mult-thread for `make`
|
- name: enable mult-thread for `make`
|
||||||
shell: bash
|
shell: bash
|
||||||
run: export MAKEFLAGS="-j$(expr $(nproc) \+ 1)"
|
run: export MAKEFLAGS="-j$(expr $(nproc) \+ 1)"
|
||||||
|
@ -48,6 +48,7 @@ RUN apt-get update && \
|
|||||||
gcc-i686-linux-gnu \
|
gcc-i686-linux-gnu \
|
||||||
gcc-mipsel-linux-gnu \
|
gcc-mipsel-linux-gnu \
|
||||||
gcc-powerpc-linux-gnu \
|
gcc-powerpc-linux-gnu \
|
||||||
|
gcc-riscv64-linux-gnu \
|
||||||
gdb \
|
gdb \
|
||||||
gdb-multiarch \
|
gdb-multiarch \
|
||||||
git \
|
git \
|
||||||
|
@ -20,7 +20,7 @@ build_bin:
|
|||||||
|
|
||||||
[linux]
|
[linux]
|
||||||
[macos]
|
[macos]
|
||||||
test: fuzzer build_bin (test_single "arm") (test_single "arm64") (test_single "x86")
|
test: fuzzer build_bin (test_single "arm") (test_single "arm64") (test_single "riscv64") (test_single "x86")
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|
||||||
test_single arch="arm":
|
test_single arch="arm":
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
arm64 := "aarch64-linux-gnu"
|
arm64 := "aarch64-linux-gnu"
|
||||||
arm := "arm-linux-gnueabihf"
|
arm := "arm-linux-gnueabihf"
|
||||||
|
riscv64 := "riscv64-linux-gnu"
|
||||||
x64 := "x86_64-linux-gnu"
|
x64 := "x86_64-linux-gnu"
|
||||||
|
|
||||||
assembly_arm64:
|
assembly_arm64:
|
||||||
@ -16,6 +17,13 @@ binary_arm:
|
|||||||
{{arm}}-as foo_arm.s -o foo_arm.elf
|
{{arm}}-as foo_arm.s -o foo_arm.elf
|
||||||
{{arm}}-objcopy -O binary foo_arm.elf foo_arm.bin
|
{{arm}}-objcopy -O binary foo_arm.elf foo_arm.bin
|
||||||
|
|
||||||
|
assembly_riscv64:
|
||||||
|
{{riscv64}}-gcc -O2 -S -c foo.c -o foo_riscv64.s
|
||||||
|
|
||||||
|
binary_riscv64:
|
||||||
|
{{riscv64}}-as foo_riscv64.s -o foo_riscv64.elf
|
||||||
|
{{riscv64}}-objcopy -O binary -j .text.startup foo_riscv64.elf foo_riscv64.bin
|
||||||
|
|
||||||
assembly_x86:
|
assembly_x86:
|
||||||
{{x64}}-gcc -O2 -S -c foo.c -o foo_x86.s
|
{{x64}}-gcc -O2 -S -c foo.c -o foo_x86.s
|
||||||
|
|
||||||
@ -26,11 +34,12 @@ binary_x86:
|
|||||||
|
|
||||||
build_arm: assembly_arm binary_arm
|
build_arm: assembly_arm binary_arm
|
||||||
build_arm64: assembly_arm64 binary_arm64
|
build_arm64: assembly_arm64 binary_arm64
|
||||||
|
build_riscv64: assembly_riscv64 binary_riscv64
|
||||||
build_x86: assembly_x86 binary_x86
|
build_x86: assembly_x86 binary_x86
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm foo_*
|
rm foo_*
|
||||||
|
|
||||||
|
|
||||||
all: build_arm build_arm64 build_x86
|
all: build_arm build_arm64 build_riscv64 build_x86
|
||||||
# sudo apt install gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu
|
# sudo apt install gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu gcc-riscv64-linux-gnu
|
||||||
|
@ -36,7 +36,7 @@ use libafl_unicorn::{
|
|||||||
use unicorn_engine::{unicorn_const::MemType, HookType};
|
use unicorn_engine::{unicorn_const::MemType, HookType};
|
||||||
use unicorn_engine::{
|
use unicorn_engine::{
|
||||||
unicorn_const::{Arch, SECOND_SCALE},
|
unicorn_const::{Arch, SECOND_SCALE},
|
||||||
Mode, Permission, RegisterARM, RegisterARM64, RegisterX86, Unicorn,
|
Mode, Permission, RegisterARM, RegisterARM64, RegisterRISCV, RegisterX86, Unicorn,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CODE_ADDRESS: u64 = 0x9000;
|
pub const CODE_ADDRESS: u64 = 0x9000;
|
||||||
@ -64,6 +64,7 @@ fn main() {
|
|||||||
let arch = match args[1].as_str() {
|
let arch = match args[1].as_str() {
|
||||||
"arm" => Arch::ARM,
|
"arm" => Arch::ARM,
|
||||||
"arm64" => Arch::ARM64,
|
"arm64" => Arch::ARM64,
|
||||||
|
"riscv64" => Arch::RISCV,
|
||||||
"x86" => Arch::X86,
|
"x86" => Arch::X86,
|
||||||
_ => {
|
_ => {
|
||||||
panic!("This arcghitecture is not supported")
|
panic!("This arcghitecture is not supported")
|
||||||
@ -86,6 +87,10 @@ pub fn init_registers(emu: &mut Unicorn<()>, sp: u64) {
|
|||||||
emu.reg_write(RegisterARM64::SP, sp)
|
emu.reg_write(RegisterARM64::SP, sp)
|
||||||
.expect("Could not setup register");
|
.expect("Could not setup register");
|
||||||
}
|
}
|
||||||
|
Arch::RISCV => {
|
||||||
|
emu.reg_write(RegisterRISCV::SP, sp)
|
||||||
|
.expect("Could not setup register");
|
||||||
|
}
|
||||||
Arch::X86 => {
|
Arch::X86 => {
|
||||||
emu.reg_write(RegisterX86::ESP, sp)
|
emu.reg_write(RegisterX86::ESP, sp)
|
||||||
.expect("Could not setup register");
|
.expect("Could not setup register");
|
||||||
@ -99,6 +104,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) {
|
|||||||
let mode = match arch {
|
let mode = match arch {
|
||||||
Arch::ARM => Mode::ARM,
|
Arch::ARM => Mode::ARM,
|
||||||
Arch::ARM64 => Mode::ARM926,
|
Arch::ARM64 => Mode::ARM926,
|
||||||
|
Arch::RISCV => Mode::RISCV64,
|
||||||
Arch::X86 => Mode::MODE_64,
|
Arch::X86 => Mode::MODE_64,
|
||||||
_ => Mode::MODE_64,
|
_ => Mode::MODE_64,
|
||||||
};
|
};
|
||||||
@ -112,6 +118,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) {
|
|||||||
match arch {
|
match arch {
|
||||||
Arch::ARM => "bin/foo_arm.bin",
|
Arch::ARM => "bin/foo_arm.bin",
|
||||||
Arch::ARM64 => "bin/foo_arm64.bin",
|
Arch::ARM64 => "bin/foo_arm64.bin",
|
||||||
|
Arch::RISCV => "bin/foo_riscv64.bin",
|
||||||
Arch::X86 => "bin/foo_x86.bin",
|
Arch::X86 => "bin/foo_x86.bin",
|
||||||
_ => "",
|
_ => "",
|
||||||
},
|
},
|
||||||
@ -191,6 +198,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) {
|
|||||||
match arch {
|
match arch {
|
||||||
Arch::ARM => emu.reg_write(RegisterARM::LR, RETURN_ADDRESS).unwrap(),
|
Arch::ARM => emu.reg_write(RegisterARM::LR, RETURN_ADDRESS).unwrap(),
|
||||||
Arch::ARM64 => emu.reg_write(RegisterARM64::LR, RETURN_ADDRESS).unwrap(),
|
Arch::ARM64 => emu.reg_write(RegisterARM64::LR, RETURN_ADDRESS).unwrap(),
|
||||||
|
Arch::RISCV => emu.reg_write(RegisterRISCV::RA, RETURN_ADDRESS).unwrap(),
|
||||||
Arch::X86 => {
|
Arch::X86 => {
|
||||||
let bytes = u64::to_le_bytes(RETURN_ADDRESS);
|
let bytes = u64::to_le_bytes(RETURN_ADDRESS);
|
||||||
|
|
||||||
@ -213,6 +221,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) {
|
|||||||
let result_value = match arch {
|
let result_value = match arch {
|
||||||
Arch::ARM => emu.reg_read(RegisterARM::R0).unwrap(),
|
Arch::ARM => emu.reg_read(RegisterARM::R0).unwrap(),
|
||||||
Arch::ARM64 => emu.reg_read(RegisterARM64::W0).unwrap(),
|
Arch::ARM64 => emu.reg_read(RegisterARM64::W0).unwrap(),
|
||||||
|
Arch::RISCV => emu.reg_read(RegisterRISCV::A0).unwrap(),
|
||||||
Arch::X86 => emu.reg_read(RegisterX86::EAX).unwrap(),
|
Arch::X86 => emu.reg_read(RegisterX86::EAX).unwrap(),
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ use capstone::{
|
|||||||
};
|
};
|
||||||
pub use libafl_targets::{EDGES_MAP, EDGES_MAP_PTR};
|
pub use libafl_targets::{EDGES_MAP, EDGES_MAP_PTR};
|
||||||
use unicorn_engine::{
|
use unicorn_engine::{
|
||||||
RegisterARM, RegisterARM64, RegisterX86, Unicorn,
|
RegisterARM, RegisterARM64, RegisterRISCV, RegisterX86, Unicorn,
|
||||||
unicorn_const::{Arch, Permission},
|
unicorn_const::{Arch, Permission},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,6 +57,14 @@ pub fn debug_print(emu: &Unicorn<()>, thumb_mode: bool) {
|
|||||||
log::debug!("X2: {:X}", emu.reg_read(RegisterARM64::X2).unwrap());
|
log::debug!("X2: {:X}", emu.reg_read(RegisterARM64::X2).unwrap());
|
||||||
log::debug!("X3: {:X}", emu.reg_read(RegisterARM64::X3).unwrap());
|
log::debug!("X3: {:X}", emu.reg_read(RegisterARM64::X3).unwrap());
|
||||||
}
|
}
|
||||||
|
Arch::RISCV => {
|
||||||
|
log::debug!("SP: {:X}", emu.reg_read(RegisterRISCV::SP).unwrap());
|
||||||
|
log::debug!("RA: {:X}", emu.reg_read(RegisterRISCV::RA).unwrap());
|
||||||
|
log::debug!("GP: {:X}", emu.reg_read(RegisterRISCV::GP).unwrap());
|
||||||
|
log::debug!("TP: {:X}", emu.reg_read(RegisterRISCV::TP).unwrap());
|
||||||
|
log::debug!("A0: {:X}", emu.reg_read(RegisterRISCV::A0).unwrap());
|
||||||
|
log::debug!("A1: {:X}", emu.reg_read(RegisterRISCV::A1).unwrap());
|
||||||
|
}
|
||||||
Arch::X86 => {
|
Arch::X86 => {
|
||||||
log::debug!("ESP: {:X}", emu.reg_read(RegisterX86::ESP).unwrap());
|
log::debug!("ESP: {:X}", emu.reg_read(RegisterX86::ESP).unwrap());
|
||||||
log::debug!("RAX: {:X}", emu.reg_read(RegisterX86::RAX).unwrap());
|
log::debug!("RAX: {:X}", emu.reg_read(RegisterX86::RAX).unwrap());
|
||||||
@ -100,6 +108,12 @@ pub fn debug_print(emu: &Unicorn<()>, thumb_mode: bool) {
|
|||||||
.detail(true)
|
.detail(true)
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to create Capstone object"),
|
.expect("Failed to create Capstone object"),
|
||||||
|
Arch::RISCV => Capstone::new()
|
||||||
|
.riscv()
|
||||||
|
.mode(arch::riscv::ArchMode::RiscV64)
|
||||||
|
.detail(true)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Capstone object"),
|
||||||
|
|
||||||
_ => Capstone::new()
|
_ => Capstone::new()
|
||||||
.x86()
|
.x86()
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use unicorn_engine::{RegisterARM, RegisterARM64, RegisterX86, unicorn_const::Arch};
|
use unicorn_engine::{RegisterARM, RegisterARM64, RegisterRISCV, RegisterX86, unicorn_const::Arch};
|
||||||
|
|
||||||
pub fn get_stack_pointer(emu: &unicorn_engine::Unicorn<()>) -> u64 {
|
pub fn get_stack_pointer(emu: &unicorn_engine::Unicorn<()>) -> u64 {
|
||||||
match emu.get_arch() {
|
match emu.get_arch() {
|
||||||
Arch::ARM => emu.reg_read(RegisterARM::SP).unwrap(),
|
Arch::ARM => emu.reg_read(RegisterARM::SP).unwrap(),
|
||||||
Arch::ARM64 => emu.reg_read(RegisterARM64::SP).unwrap(),
|
Arch::ARM64 => emu.reg_read(RegisterARM64::SP).unwrap(),
|
||||||
|
Arch::RISCV => emu.reg_read(RegisterRISCV::SP).unwrap(),
|
||||||
Arch::X86 => emu.reg_read(RegisterX86::ESP).unwrap(),
|
Arch::X86 => emu.reg_read(RegisterX86::ESP).unwrap(),
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user