Skip to content

Instantly share code, notes, and snippets.

@th0rex
Created December 7, 2019 10:08
Show Gist options
  • Save th0rex/3e1e70514123acec8c7f524e46eccb94 to your computer and use it in GitHub Desktop.
Save th0rex/3e1e70514123acec8c7f524e46eccb94 to your computer and use it in GitHub Desktop.
zydis rs bench
[package]
name = "zydis-rs-bench"
version = "0.1.0"
authors = ["th0rex "]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
goblin = "*"
serde_json = "*"
xed-sys = { path = "/tmp/xed-sys" }
zydis = { git = "https://github.com/zyantific/zydis-rs/", features = ["minimal"] }
use std::error::Error;
use std::fs::{self, File};
use std::io::Read;
use std::mem;
use std::time::Instant;
use goblin::pe::PE;
use xed_sys::xed_interface::{
xed_decoded_inst_set_mode, xed_decoded_inst_t, xed_decoded_inst_zero, xed_ild_decode,
xed_tables_init, XED_ADDRESS_WIDTH_64b, XED_ERROR_NONE, XED_MACHINE_MODE_LONG_64,
XED_MAX_INSTRUCTION_BYTES,
};
use zydis::{
ffi::{ZydisDecoderDecodeBuffer, ZydisDecoderEnableMode, ZydisDecoderInit},
AddressWidth, Decoder, DecoderMode, MachineMode,
};
fn zydis(text: &[u8], offs: &[usize]) -> Result> {
let mut decoder = Decoder::new(MachineMode::LONG_64, AddressWidth::_64)?;
decoder.enable_mode(DecoderMode::MINIMAL, true)?;
let mut success = 0;
for _ in 0..100 {
for off in offs {
if let Ok(r) = decoder.decode(&text[*off..]) {
if r.is_some() {
success += 1;
}
}
}
}
Ok(success)
}
fn zydis_raw(text: &[u8], offs: &[usize]) -> Result> {
unsafe {
let mut decoder = mem::MaybeUninit::uninit();
ZydisDecoderInit(
decoder.as_mut_ptr(),
MachineMode::LONG_64,
AddressWidth::_64,
);
ZydisDecoderEnableMode(decoder.as_mut_ptr(), DecoderMode::MINIMAL, true as _);
let mut insn = mem::MaybeUninit::uninit();
let mut success = 0;
for _ in 0..100 {
for off in offs {
if ZydisDecoderDecodeBuffer(
decoder.as_mut_ptr(),
text[*off..].as_ptr() as *const std::os::raw::c_void,
16,
insn.as_mut_ptr(),
) == zydis::Status::Success
{
success += 1;
}
}
}
Ok(success)
}
}
fn xed(text: &[u8], offs: &[usize]) -> Result> {
unsafe {
let (mmode, stack_addr_width) = (XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b);
xed_tables_init();
let mut xedd = mem::MaybeUninit::::uninit();
let mut success = 0;
for _ in 0..100 {
for off in offs {
xed_decoded_inst_zero(xedd.as_mut_ptr());
xed_decoded_inst_set_mode(xedd.as_mut_ptr(), mmode, stack_addr_width);
let r = xed_ild_decode(
xedd.as_mut_ptr(),
text[*off..].as_ptr(),
XED_MAX_INSTRUCTION_BYTES,
);
if r == XED_ERROR_NONE {
success += 1;
}
}
}
Ok(success)
}
}
fn main() -> Result<(), Box> {
println!("reading .text...");
let mut obj = vec![];
let mut h = File::open("ntoskrnl.exe")?;
h.read_to_end(&mut obj)?;
let p = PE::parse(&obj)?;
let section = p
.sections
.iter()
.find(|s| s.name().unwrap() == ".text")
.unwrap();
let text = &obj[section.pointer_to_raw_data as usize
..section.pointer_to_raw_data as usize + section.size_of_raw_data as usize];
println!("read {} bytes of .text", text.len());
// Python>import json
// Python>offs = list(map(lambda a: a - ida_segment.get_segm_by_name('.text').start_ea, filter(lambda a: ida_segment.get_segm_name(ida_segment.getseg(a)) == '.text', Heads())))
// Python>with open('offs.json', 'wb') as h:
// Python> json.dump(offs, h)
println!("reading offsets...");
let j = fs::read_to_string("offs.json")?;
let offs: Vec = serde_json::from_str(&j)?;
for off in &offs {
if *off > text.len() {
panic!(
"offset {:x} out of bounds of {:x} byte section",
off,
text.len()
);
}
}
println!("read {} offsets", offs.len());
let mut zysuccess = 0;
let mut zyrawsuccess = 0;
let mut xedsuccess = 0;
let mut zytotal = 0;
let mut zyrawtotal = 0;
let mut xedtotal = 0;
let total = 3;
for _ in 0..total {
let zystart = Instant::now();
zysuccess = zydis(text, &offs)?;
zytotal += zystart.elapsed().as_millis();
}
for _ in 0..total {
let zystart = Instant::now();
zyrawsuccess = zydis_raw(text, &offs)?;
zyrawtotal += zystart.elapsed().as_millis();
}
for _ in 0..total {
let xedstart = Instant::now();
xedsuccess = xed(text, &offs)?;
xedtotal += xedstart.elapsed().as_millis();
}
println!(
"zydis decoded {} instructions in {}ms",
zysuccess,
zytotal / total,
);
println!(
"zydis raw decoded {} instructions in {}ms",
zyrawsuccess,
zyrawtotal / total,
);
println!(
"xed decoded {} instructions in {}ms",
xedsuccess,
xedtotal / total
);
Ok(())
}
nothing:
zydis decoded 100045400 instructions in 17958ms
zydis raw decoded 100045500 instructions in 12213ms
xed decoded 100046000 instructions in 7146ms
minimal:
zydis decoded 100045400 instructions in 16514ms
zydis raw decoded 100045500 instructions in 11106ms
xed decoded 100046000 instructions in 7100ms
lto:
zydis decoded 100045400 instructions in 12320ms
zydis raw decoded 100045500 instructions in 12351ms
xed decoded 100046000 instructions in 7202ms
minimal lto:
zydis decoded 100045400 instructions in 11335ms
zydis raw decoded 100045500 instructions in 11351ms
xed decoded 100046000 instructions in 7007ms
===
AFTER PATCHES TO ZYDIS-RS
===
nothing:
zydis decoded 100045400 instructions in 12182ms
zydis raw decoded 100045500 instructions in 12076ms
xed decoded 100046000 instructions in 7222ms
minimal:
zydis decoded 100045400 instructions in 11391ms
zydis raw decoded 100045500 instructions in 11266ms
xed decoded 100046000 instructions in 7066ms
minimal lto:
zydis decoded 100045400 instructions in 11642ms
zydis raw decoded 100045500 instructions in 11586ms
xed decoded 100046000 instructions in 7897ms
@yrp604
Copy link

yrp604 commented Dec 7, 2019

After patches:

nothing:
zydis decoded 100045400 instructions in 11805ms
zydis raw decoded 100045500 instructions in 13518ms
xed decoded 100046000 instructions in 8089ms

minimal:
zydis decoded 100045400 instructions in 7493ms
zydis raw decoded 100045500 instructions in 7351ms
xed decoded 100046000 instructions in 5285ms

minimal lto:
zydis decoded 100045400 instructions in 7615ms
zydis raw decoded 100045500 instructions in 7411ms
xed decoded 100046000 instructions in 5444ms

I don't really see why adding minimal slows down xed, and makes me think I fucked something up?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment