Created
December 7, 2019 10:08
-
-
Save th0rex/3e1e70514123acec8c7f524e46eccb94 to your computer and use it in GitHub Desktop.
zydis rs bench
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
After patches:
I don't really see why adding minimal slows down xed, and makes me think I fucked something up?