Compare commits

...

3 Commits

6 changed files with 343 additions and 28 deletions

235
Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.20" version = "0.6.20"
@ -70,6 +79,26 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bindgen"
version = "0.72.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f"
dependencies = [
"bitflags 2.9.1",
"cexpr",
"clang-sys",
"itertools",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.104",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -122,12 +151,32 @@ dependencies = [
"shlex", "shlex",
] ]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.42" version = "4.5.42"
@ -163,6 +212,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "cmake"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.4" version = "1.0.4"
@ -207,6 +265,26 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "derive_more"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "discard" name = "discard"
version = "1.0.4" version = "1.0.4"
@ -219,6 +297,12 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -331,6 +415,15 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.15" version = "1.0.15"
@ -349,6 +442,38 @@ version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "libipt"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c3143c4dae9794d23fa2bbc6315847fdf3ef718caa09a7ba09238bce19fe9d4"
dependencies = [
"bitflags 2.9.1",
"derive_more",
"libipt-sys",
"num_enum",
]
[[package]]
name = "libipt-sys"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7609ac7c13e6e9e97027559ee7d1b093013e72996c78ba1f0e37c53b3dc090bb"
dependencies = [
"bindgen",
"cmake",
]
[[package]]
name = "libloading"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.3",
]
[[package]] [[package]]
name = "libnyx" name = "libnyx"
version = "0.1.0" version = "0.1.0"
@ -378,6 +503,15 @@ version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "memmap2"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.7.1" version = "0.7.1"
@ -387,6 +521,12 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.26.4" version = "0.26.4"
@ -400,6 +540,38 @@ dependencies = [
"pin-utils", "pin-utils",
] ]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.3" version = "1.21.3"
@ -427,6 +599,25 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "prettyplease"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2"
dependencies = [
"proc-macro2",
"syn 2.0.104",
]
[[package]]
name = "proc-macro-crate"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
dependencies = [
"toml_edit",
]
[[package]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.5.20+deprecated" version = "0.5.20+deprecated"
@ -442,11 +633,20 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "pt-dump-decoder"
version = "0.1.0"
dependencies = [
"libipt",
"memmap2",
]
[[package]] [[package]]
name = "qemu-nyx-runner" name = "qemu-nyx-runner"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"libnyx", "libnyx",
"pt-dump-decoder",
] ]
[[package]] [[package]]
@ -511,6 +711,35 @@ dependencies = [
"rand_core", "rand_core",
] ]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.6.6" version = "0.6.6"
@ -522,6 +751,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"

View File

@ -1,6 +1,6 @@
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["client"] members = ["client", "pt-dump-decoder"]
[package] [package]
name = "qemu-nyx-runner" name = "qemu-nyx-runner"
@ -9,3 +9,4 @@ edition = "2024"
[dependencies] [dependencies]
libnyx = { git = "https://git.cs.tu-dortmund.de/david.venhoff/libnyx-fork" } libnyx = { git = "https://git.cs.tu-dortmund.de/david.venhoff/libnyx-fork" }
pt-dump-decoder = { path = "pt-dump-decoder" }

View File

@ -4,16 +4,21 @@ use std::process::Command;
fn main() { fn main() {
println!("cargo:rerun-if-changed=client"); println!("cargo:rerun-if-changed=client");
build_client();
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let client_bin = build_client(&out_dir);
setup_nyx(&out_dir); setup_nyx(&out_dir);
create_nyx_workdir(&out_dir); create_nyx_workdir(&out_dir, &client_bin);
} }
#[track_caller] #[track_caller]
fn shell(cwd: impl AsRef<Path>, command_string: &str) { fn shell(cwd: impl AsRef<Path>, command_string: &str) {
println!(
"cargo:warning=Running ({}) {command_string}",
cwd.as_ref().display()
);
let cwd = cwd.as_ref(); let cwd = cwd.as_ref();
let mut parts = command_string.split(" "); let mut parts = command_string.split(" ");
let command_name = parts.next().unwrap(); let command_name = parts.next().unwrap();
@ -34,8 +39,14 @@ fn shell(cwd: impl AsRef<Path>, command_string: &str) {
} }
} }
fn build_client() { /// Builds the client and returns the path to its binary
shell("client", "cargo build --release"); fn build_client(out_dir: &str) -> String {
// Change the target dir to avoid a cargo target dir deadlock
shell(
"client",
&format!("cargo build --release --target-dir {out_dir}/client_target"),
);
format!("{out_dir}/client_target/release/client")
} }
/// Downloads and compiles qemu-nyx and packer and compiles them for the current architecture /// Downloads and compiles qemu-nyx and packer and compiles them for the current architecture
@ -61,8 +72,7 @@ fn setup_nyx(out_dir: &str) {
let qemu_compile_mode = if is_debug_build { let qemu_compile_mode = if is_debug_build {
"debug_static" "debug_static"
} else { } else {
// TODO: Consider using "lto" "lto"
"full_static"
}; };
shell( shell(
qemu_path, qemu_path,
@ -71,13 +81,12 @@ fn setup_nyx(out_dir: &str) {
} }
} }
fn create_nyx_workdir(out_dir: &str) { fn create_nyx_workdir(out_dir: &str, client_bin: &str) {
// Create the directory and move required binaries to it // Create the directory and move required binaries to it
let repository_root = env::var("CARGO_MANIFEST_DIR").unwrap();
shell( shell(
out_dir, out_dir,
&format!( &format!(
"python3 packer/packer/nyx_packer.py {repository_root}/target/release/client build afl processor_trace --fast_reload_mode --purge" "python3 packer/packer/nyx_packer.py {client_bin} build afl processor_trace --fast_reload_mode --purge"
), ),
); );

View File

@ -0,0 +1,11 @@
[package]
name = "pt-dump-decoder"
version = "0.1.0"
edition = "2024"
[lib]
[dependencies]
libipt = { version = "0.4.0", features = ["libipt_master"] }
memmap2 = "0.9.7"

View File

@ -0,0 +1,60 @@
use libipt::enc_dec_builder::EncoderDecoderBuilder;
use libipt::packet::{Packet, PacketDecoder};
use memmap2::Mmap;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::time::Duration;
#[derive(Debug)]
pub struct AnalyzeData {
pub packets: u64,
pub cycles: u64,
pub time: Duration,
pub time_outside_hypervisor: Duration,
}
pub fn analyze_dump(path: impl AsRef<Path>) -> Result<AnalyzeData, Box<dyn Error>> {
let trace_file = File::open(path)?;
let mmap = unsafe { Mmap::map(&trace_file)? };
let builder = EncoderDecoderBuilder::<PacketDecoder<()>>::new();
// I hope this is safe if the buffer is never written to
let builder = unsafe { builder.buffer_from_raw(mmap.as_ptr() as *mut _, mmap.len()) };
let mut decoder = builder.build()?;
// Required before it can be used
decoder.sync_forward()?;
let mut total = 0u64;
let mut cycles = 0u64;
let mut cycles_in_vmcs = 0u64;
let mut last_packet_vmcs = false;
for packet in decoder {
total += 1;
match packet {
Ok(Packet::Cyc(cyc)) => {
cycles += cyc.value();
if last_packet_vmcs {
cycles_in_vmcs += cyc.value();
last_packet_vmcs = false;
}
}
Ok(Packet::Vmcs(_)) => {
last_packet_vmcs = true;
}
Ok(_) => {}
Err(error) => println!("Got error: {error:?}"),
}
}
let cycles_outside_hypervisor = cycles - cycles_in_vmcs;
let total_seconds = cycles as f64 / 2_700_000_000.0;
let total_seconds_no_hypervisor = cycles_outside_hypervisor as f64 / 2_700_000_000.0;
Ok(AnalyzeData {
packets: total,
cycles,
time: Duration::from_secs_f64(total_seconds),
time_outside_hypervisor: Duration::from_secs_f64(total_seconds_no_hypervisor),
})
}

View File

@ -1,44 +1,43 @@
//! Translated from libnyx/test.c //! Translated from libnyx/test.c
use libnyx::ffi::nyx_print_aux_buffer; use libnyx::ffi::nyx_print_aux_buffer;
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole}; use libnyx::{NyxConfig, NyxProcess, NyxProcessRole, NyxReturnValue};
use std::error::Error; use std::error::Error;
use pt_dump_decoder::analyze_dump;
const WORKDIR_PATH: &str = "/tmp/wdir"; const WORKDIR_PATH: &str = "/tmp/wdir";
// The sharedir path gets set by the build script // The sharedir path gets set by the build script
const SHAREDIR_PATH: &str = env!("NYX_SHAREDIR"); const SHAREDIR_PATH: &str = env!("NYX_SHAREDIR");
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
std::fs::remove_dir_all(WORKDIR_PATH)?;
run_client()?;
let dump_path = format!("{WORKDIR_PATH}/pt_trace_dump_0");
let result = analyze_dump(dump_path)?;
println!("{result:?}");
Ok(())
}
fn run_client() -> Result<(), Box<dyn Error>> {
let mut nyx_config = NyxConfig::load(SHAREDIR_PATH)?; let mut nyx_config = NyxConfig::load(SHAREDIR_PATH)?;
nyx_config.set_workdir_path(WORKDIR_PATH.to_string()); nyx_config.set_workdir_path(WORKDIR_PATH.to_string());
nyx_config.set_input_buffer_size(0x2000); nyx_config.set_input_buffer_size(0x2000);
nyx_config.set_nyx_debug_log_path("qemu_nyx.log".to_string()); nyx_config.set_nyx_debug_log_path("qemu_nyx.log".to_string());
// let file = File::create("/tmp/nyx_test_output.log")?;
// let fd = file.as_raw_fd();
// test.c never closes the file, and closing it throws a warning...
// std::mem::forget(file);
// nyx_config.set_hprintf_fd(fd);
nyx_config.set_process_role(NyxProcessRole::StandAlone); nyx_config.set_process_role(NyxProcessRole::StandAlone);
nyx_config.print(); nyx_config.print();
let mut nyx_runner = NyxProcess::new(&mut nyx_config, 0)?; let mut nyx_runner = NyxProcess::new(&mut nyx_config, 0)?;
nyx_runner.set_input(b"INPUT", 5);
nyx_runner.option_set_reload_mode(true);
nyx_runner.option_set_trace_mode(true); nyx_runner.option_set_trace_mode(true);
nyx_runner.option_set_timeout(10, 0); nyx_runner.option_set_timeout(10, 0);
nyx_runner.option_apply(); nyx_runner.option_apply();
for _ in 0..1 {
let result = nyx_runner.exec(); let result = nyx_runner.exec();
println!("{result}"); assert!(matches!(result, NyxReturnValue::Normal), "Unexpected return value {result:?}");
nyx_print_aux_buffer(&mut nyx_runner as *mut _); nyx_print_aux_buffer(&mut nyx_runner as *mut _);
}
nyx_runner.shutdown(); nyx_runner.shutdown();
// std::fs::remove_dir_all(WORKDIR_PATH)?;
Ok(()) Ok(())
} }