extern crate libsmt;
use libsmt::backends::smtlib2::*;
use libsmt::backends::backend::*;
use libsmt::backends::z3;
use libsmt::theories::{array_ex, bitvec, core};
use libsmt::logics::qf_abv::QF_ABV;
use libsmt::logics::qf_abv;
macro_rules! bv_const {
($solver: ident, $i: expr, $n: expr) => { $solver.new_const(bitvec::OpCodes::Const($i, $n)) }
}
fn main() {
let mut z3: z3::Z3 = Default::default();
let mut solver = SMTLib2::new(Some(QF_ABV));
let rdi = solver.new_var(Some("rdi"), qf_abv::bv_sort(64));
let rsi = solver.new_var(Some("rsi"), qf_abv::bv_sort(64));
let mem = {
let bit_vec_arr = qf_abv::array_sort(qf_abv::bv_sort(64),
qf_abv::bv_sort(64));
solver.new_var(Some("mem"), bit_vec_arr)
};
let rbp = bv_const!(solver, 0x9000, 64);
let const_a = bv_const!(solver, 0xA, 64);
let const_4 = bv_const!(solver, 0x4, 64);
let const_badcafe = bv_const!(solver, 0xbadcafe, 64);
let const_mem_0 = {
let arr_const = qf_abv::array_const(qf_abv::bv_sort(64),
qf_abv::bv_sort(64),
bitvec::OpCodes::Const(0, 64));
solver.new_const(arr_const)
};
solver.assert(core::OpCodes::Cmp, &[mem, const_mem_0]);
let ret_addr = solver.assert(bitvec::OpCodes::BvAdd, &[rbp, const_4]);
let buf = solver.assert(bitvec::OpCodes::BvSub, &[rbp, const_a]);
let rax = solver.assert(bitvec::OpCodes::BvAdd, &[buf, rdi]);
let new_mem = solver.assert(array_ex::OpCodes::Store, &[mem, rax, rsi]);
let sel = solver.assert(array_ex::OpCodes::Select, &[new_mem, ret_addr]);
solver.assert(core::OpCodes::Cmp, &[sel, const_badcafe]);
if let Ok(result) = solver.solve(&mut z3) {
println!("Out-Of-Bounds Write detected!");
println!("rdi: 0x{:x}; rsi: 0x{:x};", result[&rdi], result[&rsi]);
} else {
println!("This program is not vulnerable to Out-Of-Bounds Write.");
}
}