mirror of
https://github.com/radareorg/radius2.git
synced 2026-11-07 06:36:03 -10:00
clear upper 32 bits of 64bit regs, fix parity flag, add longdiv/mod, many other changes
This commit is contained in:
1 parent
da6ed7b7eb
commit
294f2ad321
18 files changed
+248
-39
No files matched your search
+3
-1
@@ -8,5 +8,7 @@ members = [
|
||||
"examples/unbreakable",
|
||||
"examples/dex",
|
||||
"examples/babyre",
|
||||
"examples/frida"
|
||||
"examples/frida",
|
||||
"examples/tracer",
|
||||
"examples/ollvm"
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "ollvm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
radius2 = { path = "../../radius" }
|
||||
@@ -0,0 +1,38 @@
|
||||
use radius2::{Radius, State, Value, vc};
|
||||
|
||||
// output:
|
||||
// FLAG: mirror_mirror_on_the_wall_whos_the_ugliest_handler_of_them_all?!
|
||||
// target/release/ollvm 0.92s user 0.04s system 99% cpu 0.964 total
|
||||
|
||||
const HASHES:[u64; 8] = [
|
||||
0x875cd4f2e18f8fc4, 0xbb093e17e5d3fa42, 0xada5dd034aae16b4, 0x97322728fea51225,
|
||||
0x4124799d72188d0d, 0x2b3e3fbbb4d44981, 0xdfcac668321e4daa, 0xeac2137a35c8923a
|
||||
];
|
||||
|
||||
fn main() {
|
||||
let mut radius = Radius::new("tests/ollvm");
|
||||
fn flag_hook(state: &mut State) -> bool {
|
||||
state.registers.set("rax", state.context["flag"][0].clone());
|
||||
true
|
||||
}
|
||||
radius.hook(0x00400899, flag_hook);
|
||||
|
||||
let main = radius.get_address("main").unwrap();
|
||||
let mut state = radius.call_state(main);
|
||||
radius.set_argv_env(&mut state, &[vc(0x58), vc(0x31)], &[]);
|
||||
let flag = state.symbolic_value("flag", 64);
|
||||
state.context.insert("flag".to_owned(), vec!(flag.clone()));
|
||||
|
||||
let mut end_state = radius.run(state, 1).unwrap();
|
||||
let rcx = end_state.registers.get("rcx");
|
||||
let mut solution = "".to_owned();
|
||||
|
||||
for hash in HASHES {
|
||||
end_state.solver.push();
|
||||
end_state.assert(&rcx.eq(&Value::Concrete(hash, 0)));
|
||||
let reved = end_state.evaluate_string(&flag).unwrap();
|
||||
solution += &reved.chars().rev().collect::<String>();
|
||||
end_state.solver.pop();
|
||||
}
|
||||
println!("FLAG: {}", solution);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "tracer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
radius2 = { path = "../../radius" }
|
||||
@@ -0,0 +1,35 @@
|
||||
use radius2::{Radius, RadiusOption};
|
||||
use radius2::state::StateStatus;
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let options = [RadiusOption::Debug(true), RadiusOption::Sims(false)];
|
||||
let mut radius = Radius::new_with_options(Some(args[1].to_owned()), &options);
|
||||
let addr = radius.get_address(&args[2]).unwrap_or_default();
|
||||
let mut state = radius.debug_state(addr, &args[3..]);
|
||||
let mut prev = radius.r2api.cmd("dr").unwrap();
|
||||
let mut cont = true;
|
||||
|
||||
while state.status == StateStatus::Active && cont {
|
||||
for register in &state.registers.indexes {
|
||||
let reg = ®ister.reg_info;
|
||||
if reg.type_str == "gpr" || reg.type_str == "flg" {
|
||||
let name = reg.name.to_owned();
|
||||
let dbg_value = radius.r2api.get_register_value(&name).unwrap();
|
||||
let rad_value = state.registers.get(&name).as_u64().unwrap();
|
||||
if dbg_value != rad_value {
|
||||
println!("{} {:x} {:x}", name, dbg_value, rad_value);
|
||||
cont = reg.type_str == "flg"; // continue for flags
|
||||
}
|
||||
}
|
||||
}
|
||||
if cont {
|
||||
prev = radius.r2api.cmd("dr;ds").unwrap();
|
||||
radius.processor.step(&mut state);
|
||||
} else {
|
||||
println!("\nprevious:\n{}", prev);
|
||||
println!("\ncurrent:\n{}", radius.r2api.cmd("dr").unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,4 +16,4 @@ pub mod value;
|
||||
|
||||
pub use crate::radius::{Radius, RadiusOption};
|
||||
pub use crate::state::State;
|
||||
pub use crate::value::Value;
|
||||
pub use crate::value::{Value, vc};
|
||||
+14
-3
@@ -288,6 +288,18 @@ fn main() {
|
||||
.multiple(true)
|
||||
.help("Run r2 command on launch"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("architecture")
|
||||
.long("arch")
|
||||
.takes_value(true)
|
||||
.help("Set target arch (usually autodetected)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("bits")
|
||||
.long("bits")
|
||||
.takes_value(true)
|
||||
.help("Set target bits (usually autodetected)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("evaluate")
|
||||
.short("e")
|
||||
@@ -451,7 +463,7 @@ fn main() {
|
||||
if path.starts_with("frida:") {
|
||||
radius.frida_state(addr)
|
||||
} else if path.starts_with("gdb:") || path.starts_with("dbg:") {
|
||||
radius.debug_state(addr)
|
||||
radius.debug_state(addr, &[])
|
||||
} else {
|
||||
radius.call_state(addr)
|
||||
}
|
||||
@@ -540,7 +552,6 @@ fn main() {
|
||||
} else {
|
||||
&cons[2 * i + 1]
|
||||
};
|
||||
|
||||
state.constrain_bytes_bv(bv, cons);
|
||||
}
|
||||
|
||||
@@ -725,7 +736,7 @@ fn main() {
|
||||
if do_json {
|
||||
println!("{}", serde_json::to_string(&json_out).unwrap_or_default());
|
||||
}
|
||||
} else {
|
||||
} else { // TODO this is temporary until I integrate a real testcase gen mode in processor
|
||||
let mut pcs: HashMap<u64, usize> = HashMap::new();
|
||||
let mut states = VecDeque::new();
|
||||
let mut solutions: HashMap<Vec<u8>, usize> = HashMap::new();
|
||||
|
||||
@@ -11,6 +11,7 @@ pub const SIZE: u64 = 64;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Operations {
|
||||
Trap,
|
||||
Interrupt,
|
||||
Syscall,
|
||||
PcAddress,
|
||||
If,
|
||||
@@ -35,7 +36,9 @@ pub enum Operations {
|
||||
Multiply,
|
||||
LongMultiply,
|
||||
Divide,
|
||||
LongDivide,
|
||||
Modulo,
|
||||
LongModulo,
|
||||
SignedDivide,
|
||||
SignedModulo,
|
||||
Not,
|
||||
@@ -89,6 +92,8 @@ pub enum Operations {
|
||||
PrintDebug, // Tool for cli hooks
|
||||
Backtrace, // Tool for cli hooks
|
||||
Constrain,
|
||||
ConstraintPush,
|
||||
ConstraintPop,
|
||||
Terminate,
|
||||
Discard,
|
||||
|
||||
@@ -113,7 +118,7 @@ impl Operations {
|
||||
pub fn from_string(s: &str) -> Self {
|
||||
match s {
|
||||
"TRAP" => Operations::Trap,
|
||||
"$" => Operations::Trap,
|
||||
"$" => Operations::Interrupt,
|
||||
"()" => Operations::Syscall,
|
||||
"$$" => Operations::PcAddress, // this is whack
|
||||
"?{" => Operations::If,
|
||||
@@ -139,7 +144,9 @@ impl Operations {
|
||||
"*" => Operations::Multiply,
|
||||
"L*" => Operations::LongMultiply,
|
||||
"/" => Operations::Divide,
|
||||
"L/" => Operations::LongDivide,
|
||||
"%" => Operations::Modulo,
|
||||
"L%" => Operations::LongModulo,
|
||||
"~/" => Operations::SignedDivide,
|
||||
"~%" => Operations::SignedModulo,
|
||||
"!" => Operations::Not,
|
||||
@@ -201,6 +208,8 @@ impl Operations {
|
||||
".." => Operations::PrintDebug,
|
||||
"BT" => Operations::Backtrace,
|
||||
"_" => Operations::Constrain,
|
||||
"_+" => Operations::ConstraintPush,
|
||||
"_-" => Operations::ConstraintPop,
|
||||
"!!" => Operations::Terminate, // state.set_break()
|
||||
"!_" => Operations::Discard, // state.set_inactive()
|
||||
|
||||
@@ -236,7 +245,14 @@ pub fn get_size(state: &mut State) -> u32 {
|
||||
sz
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn pop_bv(state: &mut State, n: u32) -> Value {
|
||||
let value = pop_value(state, false, false);
|
||||
Value::Symbolic(state.solver.to_bv(&value, n), value.get_taint())
|
||||
}
|
||||
|
||||
//#[inline]
|
||||
pub fn pop_value(state: &mut State, set_size: bool, sign_ext: bool) -> Value {
|
||||
let item = state.stack.pop().unwrap_or_default();
|
||||
|
||||
@@ -418,6 +434,7 @@ pub fn genmask(bits: u64) -> u64 {
|
||||
pub fn do_operation(state: &mut State, operation: &Operations) {
|
||||
match operation {
|
||||
Operations::Trap => {}
|
||||
Operations::Interrupt => {}
|
||||
Operations::Syscall => {}
|
||||
Operations::PcAddress => {
|
||||
push_value(state, state.esil.prev_pc.clone());
|
||||
@@ -545,6 +562,21 @@ pub fn do_operation(state: &mut State, operation: &Operations) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Operations::LongDivide => {
|
||||
let arg1 = pop_bv(state, 128);
|
||||
let arg2 = pop_bv(state, 128);
|
||||
let arg3 = pop_bv(state, 128);
|
||||
|
||||
push_value(state, ((arg2 << vc(64)) + arg1) / arg3);
|
||||
}
|
||||
Operations::LongModulo => {
|
||||
let arg1 = pop_bv(state, 128);
|
||||
let arg2 = pop_bv(state, 128);
|
||||
let arg3 = pop_bv(state, 128);
|
||||
|
||||
//println!("{:?} {:?} {:?}", arg1, arg2, arg3);
|
||||
push_value(state, ((arg2 << vc(64)) + arg1) % arg3);
|
||||
}
|
||||
Operations::Divide => {
|
||||
binary_operation!(state, /);
|
||||
}
|
||||
@@ -900,6 +932,12 @@ pub fn do_operation(state: &mut State, operation: &Operations) {
|
||||
let value = pop_value(state, false, false);
|
||||
state.assert(&value);
|
||||
}
|
||||
Operations::ConstraintPush => {
|
||||
state.solver.push();
|
||||
}
|
||||
Operations::ConstraintPop => {
|
||||
state.solver.pop();
|
||||
}
|
||||
Operations::Terminate => {
|
||||
state.set_break();
|
||||
}
|
||||
@@ -938,7 +976,7 @@ pub fn do_operation(state: &mut State, operation: &Operations) {
|
||||
}
|
||||
Operations::Parity => match &state.esil.current {
|
||||
Value::Concrete(val, t) => {
|
||||
let pf = Value::Concrete(!(val.count_ones() % 2) as u64, *t);
|
||||
let pf = Value::Concrete(!((val & 0xff).count_ones() % 2) as u64, *t);
|
||||
push_value(state, pf);
|
||||
}
|
||||
Value::Symbolic(_val, _t) => {
|
||||
|
||||
+10
-4
@@ -40,15 +40,16 @@ pub enum RunMode {
|
||||
Multiple,
|
||||
}
|
||||
|
||||
pub type HookMethod = dyn Fn(&mut State) -> bool;
|
||||
pub type HookMethod = fn(&mut State) -> bool;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Processor {
|
||||
pub instructions: BTreeMap<u64, InstructionEntry>,
|
||||
pub hooks: HashMap<u64, Vec<Rc<HookMethod>>>,
|
||||
pub hooks: HashMap<u64, Vec<HookMethod>>,
|
||||
pub esil_hooks: HashMap<u64, Vec<String>>,
|
||||
pub sims: HashMap<u64, SimMethod>,
|
||||
pub traps: HashMap<u64, SimMethod>,
|
||||
pub interrupts: HashMap<u64, SimMethod>,
|
||||
pub syscalls: HashMap<u64, Syscall>,
|
||||
pub breakpoints: HashSet<u64>,
|
||||
pub mergepoints: HashSet<u64>,
|
||||
@@ -100,6 +101,7 @@ impl Processor {
|
||||
esil_hooks: HashMap::new(),
|
||||
sims: HashMap::new(),
|
||||
traps: HashMap::new(),
|
||||
interrupts: HashMap::new(),
|
||||
syscalls: HashMap::new(),
|
||||
breakpoints: HashSet::new(),
|
||||
mergepoints: HashSet::new(),
|
||||
@@ -372,6 +374,9 @@ impl Processor {
|
||||
state.esil.mode = ExecMode::Uncon;
|
||||
break;
|
||||
}
|
||||
Operations::Interrupt => {
|
||||
let _value = pop_value(state, false, false);
|
||||
}
|
||||
Operations::Trap => {
|
||||
let trap = pop_concrete(state, false, false);
|
||||
//let pc = state.registers.get_pc().as_u64().unwrap();
|
||||
@@ -660,9 +665,9 @@ impl Processor {
|
||||
return;
|
||||
}
|
||||
}
|
||||
state.r2api.disassemble_bytes(pc_val, &data, 1).unwrap()
|
||||
state.r2api.disassemble_bytes(pc_val, &data, 1).unwrap_or_default()
|
||||
} else {
|
||||
state.r2api.disassemble(pc_val, INSTR_NUM).unwrap()
|
||||
state.r2api.disassemble(pc_val, INSTR_NUM).unwrap_or_default()
|
||||
};
|
||||
|
||||
let mut prev: Option<u64> = None;
|
||||
@@ -833,6 +838,7 @@ impl Processor {
|
||||
let step = mode == RunMode::Step;
|
||||
|
||||
loop {
|
||||
//println!("{} states", states.len());
|
||||
if states.is_empty() {
|
||||
if self.merges.is_empty() {
|
||||
return results;
|
||||
|
||||
+16
-5
@@ -793,7 +793,11 @@ impl R2Api {
|
||||
// simple as that?
|
||||
let ret = self.cmd("pae ret")?;
|
||||
if ret.is_empty() {
|
||||
Err("no ret instruction".to_owned())
|
||||
if self.info.bin.arch == "bpf" {
|
||||
Ok("8,sp,+=,sp,[8],pc,=".to_owned())
|
||||
} else {
|
||||
Err("no ret instruction".to_owned())
|
||||
}
|
||||
} else {
|
||||
Ok(ret[0..ret.len() - 1].to_owned())
|
||||
}
|
||||
@@ -801,7 +805,7 @@ impl R2Api {
|
||||
|
||||
pub fn get_register_value(&mut self, reg: &str) -> R2Result<u64> {
|
||||
let val = self.cmd(&format!("aer {}", reg))?;
|
||||
Ok(u64::from_str_radix(&val[2..val.len() - 1], 16).unwrap())
|
||||
Ok(u64::from_str_radix(&val[2..val.len() - 1], 16).unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn set_register_value(&mut self, reg: &str, value: u64) {
|
||||
@@ -847,12 +851,19 @@ impl R2Api {
|
||||
match self.mode {
|
||||
Mode::Debugger => self.cmd("dc"),
|
||||
Mode::Frida => self.cmd(":dc"),
|
||||
_ => Ok("idk".to_string()),
|
||||
_ => self.cmd("aec"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_debug(&mut self, addr: u64) {
|
||||
self.cmd(&format!("db {};dc", addr)).unwrap();
|
||||
pub fn init_debug(&mut self, addr: u64, args: &[String]) {
|
||||
(match self.mode {
|
||||
Mode::Debugger => self.cmd(&format!("db {};dc", addr)),
|
||||
Mode::Frida => panic!("can't enter debug from frida mode, also why would you?"),
|
||||
_ => {
|
||||
self.mode = Mode::Debugger;
|
||||
self.cmd(&format!("doo {};db {};dc", args.join(" "), addr))
|
||||
}
|
||||
}).unwrap_or_default();
|
||||
}
|
||||
|
||||
pub fn init_vm(&mut self) {
|
||||
|
||||
+30
-11
@@ -7,7 +7,6 @@ use crate::sims::{get_sims, zero, SimMethod};
|
||||
use crate::value::{vc, Value};
|
||||
|
||||
// use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -213,11 +212,29 @@ impl Radius {
|
||||
state
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialized state at the provided function name with an initialized stack
|
||||
* equivalent to `call_state(get_address(sym))`
|
||||
*
|
||||
* **Example**
|
||||
*
|
||||
* ```
|
||||
* use radius2::radius::Radius;
|
||||
* let mut radius = Radius::new("../tests/r100");
|
||||
* let mut state = radius.callsym_state("sym.imp.printf");
|
||||
* ```
|
||||
*/
|
||||
pub fn callsym_state<T: AsRef<str>>(&mut self, sym: T) -> State {
|
||||
let addr = self.get_address(sym).unwrap_or_default();
|
||||
self.call_state(addr)
|
||||
}
|
||||
|
||||
/// Initialize state from a debugger breakpoint
|
||||
/// the program will block until bp is hit
|
||||
pub fn debug_state(&mut self, addr: u64) -> State {
|
||||
self.r2api.seek(addr);
|
||||
self.r2api.init_debug(addr);
|
||||
pub fn debug_state(&mut self, addr: u64, args: &[String]) -> State {
|
||||
// set cache to false to set breakpoint
|
||||
self.r2api.set_option("io.cache", "false").unwrap();
|
||||
self.r2api.init_debug(addr, args);
|
||||
self.init_state()
|
||||
}
|
||||
|
||||
@@ -249,8 +266,10 @@ impl Radius {
|
||||
*/
|
||||
pub fn entry_state(&mut self) -> State {
|
||||
// get the entrypoint
|
||||
let entry = self.r2api.get_entrypoints().unwrap()[0].vaddr;
|
||||
self.r2api.seek(entry);
|
||||
let entrypoints = self.r2api.get_entrypoints().unwrap_or_default();
|
||||
if !entrypoints.is_empty() {
|
||||
self.r2api.seek(entrypoints[0].vaddr);
|
||||
}
|
||||
self.r2api.init_vm();
|
||||
let mut state = self.init_state();
|
||||
state.memory.add_stack();
|
||||
@@ -259,7 +278,7 @@ impl Radius {
|
||||
|
||||
let start_main_reloc = self.r2api.get_address("reloc.__libc_start_main").unwrap();
|
||||
|
||||
self.hook(start_main_reloc, Rc::new(__libc_start_main));
|
||||
self.hook(start_main_reloc, __libc_start_main);
|
||||
state
|
||||
}
|
||||
|
||||
@@ -345,7 +364,7 @@ impl Radius {
|
||||
}
|
||||
|
||||
/// Hook an address with a callback that is passed the `State`
|
||||
pub fn hook(&mut self, addr: u64, hook_callback: Rc<HookMethod>) {
|
||||
pub fn hook(&mut self, addr: u64, hook_callback: HookMethod) {
|
||||
self.processor
|
||||
.hooks
|
||||
.entry(addr)
|
||||
@@ -363,7 +382,7 @@ impl Radius {
|
||||
}
|
||||
|
||||
/// Hook a symbol with a callback that is passed each state that reaches it
|
||||
pub fn hook_symbol(&mut self, sym: &str, hook_callback: Rc<HookMethod>) {
|
||||
pub fn hook_symbol(&mut self, sym: &str, hook_callback: HookMethod) {
|
||||
let addr = self.get_address(sym).unwrap();
|
||||
self.hook(addr, hook_callback);
|
||||
}
|
||||
@@ -548,8 +567,8 @@ impl Radius {
|
||||
}
|
||||
|
||||
/// Get address of symbol
|
||||
pub fn get_address(&mut self, symbol: &str) -> R2Result<u64> {
|
||||
self.r2api.get_address(symbol)
|
||||
pub fn get_address<T: AsRef<str>>(&mut self, symbol: T) -> R2Result<u64> {
|
||||
self.r2api.get_address(symbol.as_ref())
|
||||
}
|
||||
|
||||
/// Get all functions
|
||||
|
||||
+12
-6
@@ -5,6 +5,7 @@ use crate::value::{Value, vc};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Bounds {
|
||||
tstr: String,
|
||||
start: u64,
|
||||
end: u64,
|
||||
size: u64,
|
||||
@@ -53,6 +54,7 @@ impl Registers {
|
||||
let mut bounds_map: HashMap<Bounds, usize> = HashMap::new();
|
||||
for reg in reg_info.reg_info {
|
||||
let mut bounds = Bounds {
|
||||
tstr: reg.type_str.to_owned(),
|
||||
start: reg.offset,
|
||||
end: reg.offset.wrapping_add(reg.size),
|
||||
size: reg.size,
|
||||
@@ -61,7 +63,8 @@ impl Registers {
|
||||
let old_bounds = bounds_map.keys();
|
||||
let mut in_bounds = false;
|
||||
for bound in old_bounds {
|
||||
if bounds.start >= bound.start && bounds.end <= bound.end {
|
||||
let inside = bounds.start >= bound.start && bounds.end <= bound.end;
|
||||
if bound.tstr == bounds.tstr && inside {
|
||||
in_bounds = true;
|
||||
bounds = bound.clone();
|
||||
}
|
||||
@@ -144,7 +147,11 @@ impl Registers {
|
||||
let t = r.reg.to_owned();
|
||||
return self.set_value(self.regs[&t].index, value);
|
||||
}
|
||||
self.set_value(self.regs[alias].index, value)
|
||||
// make set_with_alias more forgiving
|
||||
if let Some(reg) = self.regs.get(alias) {
|
||||
let creg = reg.clone();
|
||||
self.set_value(creg.index, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value of `PC`
|
||||
@@ -178,7 +185,6 @@ impl Registers {
|
||||
if register.reg_info.offset == -1i64 as u64 {
|
||||
return Value::Concrete(0, 0); // this is a zero register
|
||||
}
|
||||
|
||||
let value = &self.values[register.value_index];
|
||||
if register.reg_info.size == register.bounds.size {
|
||||
value.to_owned()
|
||||
@@ -199,15 +205,15 @@ impl Registers {
|
||||
let size = register.reg_info.size;
|
||||
if size == register.bounds.size {
|
||||
if size <= 64 {
|
||||
self.values[register.value_index] = value;
|
||||
self.values[register.value_index] = value.slice(size - 1, 0);
|
||||
} else {
|
||||
// need to prevent size > 64 from becoming a u64
|
||||
let bv = self.solver.to_bv(&value, size as u32);
|
||||
let v = Value::Symbolic(bv, value.get_taint());
|
||||
self.values[register.value_index] = v;
|
||||
}
|
||||
//} else if self.clear_upper && size == 32 { // this sux
|
||||
// self.values[register.value_index] = value.uext(&vc(32));
|
||||
} else if size == 32 { // this sux
|
||||
self.values[register.value_index] = value.slice(size - 1, 0).uext(&vc(32));
|
||||
} else {
|
||||
let bound_size = register.bounds.size as u32;
|
||||
let offset = register.reg_info.offset - register.bounds.start;
|
||||
|
||||
@@ -532,6 +532,11 @@ pub fn strtol(state: &mut State, args: &[Value]) -> Value {
|
||||
strtoll(state, args).slice(bits - 1, 0)
|
||||
}
|
||||
|
||||
pub fn strtoul(state: &mut State, args: &[Value]) -> Value {
|
||||
let bits = state.memory.bits;
|
||||
strtoll(state, args).slice(bits - 1, 0)
|
||||
}
|
||||
|
||||
pub fn itoa(state: &mut State, args: &[Value]) -> Value {
|
||||
format::itoa_helper(state, &args[0], &args[1], &args[2], true, 32)
|
||||
}
|
||||
@@ -793,6 +798,12 @@ pub fn sleep(_state: &mut State, _args: &[Value]) -> Value {
|
||||
vc(0)
|
||||
}
|
||||
|
||||
pub fn __errno_location(state: &mut State, _args: &[Value]) -> Value {
|
||||
let addr = state.memory_alloc(&vc(8));
|
||||
state.memory_write_value(&addr, &vc(0), 8);
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn open(state: &mut State, args: &[Value]) -> Value {
|
||||
syscall::open(state, args)
|
||||
}
|
||||
|
||||
@@ -118,7 +118,8 @@ pub fn get_sims() -> Vec<Sim> {
|
||||
make_sim("atol", libc::atoi, 1),
|
||||
make_sim("itoa", libc::itoa, 3),
|
||||
make_sim("strtol", libc::strtol, 3),
|
||||
make_sim("strtoll", libc::strtol, 3),
|
||||
make_sim("strtoul", libc::strtoul, 3),
|
||||
make_sim("strtoll", libc::strtoll, 3),
|
||||
make_sim("strtod", libc::strtol, 3),
|
||||
make_sim("islower", libc::islower, 1),
|
||||
make_sim("isupper", libc::isupper, 1),
|
||||
@@ -164,5 +165,6 @@ pub fn get_sims() -> Vec<Sim> {
|
||||
make_sim("__stack_chk_fail", ret, 0),
|
||||
make_sim("__libc_start_main", libc::__libc_start_main, 5),
|
||||
make_sim("__cfi_slowpath", zero, 0),
|
||||
make_sim("__errno_location", libc::__errno_location, 0),
|
||||
]
|
||||
}
|
||||
@@ -72,7 +72,13 @@ impl Solver {
|
||||
|
||||
#[inline]
|
||||
pub fn bvv(&self, v: u64, n: u32) -> BitVec {
|
||||
BV::from_u64(self.btor.clone(), v, n)
|
||||
if n <= 64 {
|
||||
// boolector sign extends. even though its u64...
|
||||
// what the fuck
|
||||
BV::from_u64(self.btor.clone(), v, n)
|
||||
} else {
|
||||
BV::from_u64(self.btor.clone(), v, 64).uext(n-64)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn translate(&self, bv: &BitVec) -> Option<BitVec> {
|
||||
|
||||
+10
-4
@@ -620,7 +620,8 @@ impl Value {
|
||||
}
|
||||
(Value::Symbolic(a, t1), Value::Concrete(b, t2)) => {
|
||||
//let bv = make_bv(&a, b, a.get_width());
|
||||
Value::Symbolic(a.slice(*b as u32 - 1, 0).uext(64 - *b as u32), *t1 | *t2)
|
||||
let bits = if *b <= 64 { *b } else { 64 };
|
||||
Value::Symbolic(a.slice(*b as u32 - 1, 0).uext(64 - bits as u32), *t1 | *t2)
|
||||
}
|
||||
(Value::Concrete(a, t), Value::Symbolic(_b, _t)) => {
|
||||
// uh hopefully this doesnt happen
|
||||
@@ -643,7 +644,7 @@ impl Value {
|
||||
}
|
||||
(Value::Symbolic(a, t1), Value::Concrete(b, t2)) => {
|
||||
//let bv = make_bv(&a, b, a.get_width());
|
||||
Value::Symbolic(a.slice(*b as u32 - 1, 0).sext(64 - *b as u32), *t1 | *t2)
|
||||
Value::Symbolic(a.slice(*b as u32 - 1, 0).sext(64 - (*b % 64) as u32), *t1 | *t2)
|
||||
}
|
||||
(Value::Concrete(a, t), Value::Symbolic(_b, _t)) => {
|
||||
// uh hopefully this doesnt happen
|
||||
@@ -661,7 +662,8 @@ impl Value {
|
||||
pub fn slice(&self, high: u64, low: u64) -> Value {
|
||||
match self {
|
||||
Value::Concrete(a, t) => {
|
||||
Value::Concrete((*a >> low) & ((1 << (high - low + 1)) - 1), *t)
|
||||
let mask = if (high - low) < 63 { (1 << (high - low + 1)) - 1 } else { -1i64 as u64 };
|
||||
Value::Concrete((*a >> low) & mask, *t)
|
||||
}
|
||||
Value::Symbolic(a, t) => Value::Symbolic(a.slice(high as u32, low as u32), *t),
|
||||
}
|
||||
@@ -737,7 +739,11 @@ impl Value {
|
||||
|
||||
#[inline]
|
||||
pub fn is_symbolic(&self) -> bool {
|
||||
matches!(self, Value::Symbolic(_, _))
|
||||
if let Value::Symbolic(s, _) = self {
|
||||
!s.is_const()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in new issue
Block a user