Skip to content

Commit 1bb2d0e

Browse files
committed
Ablation study variant b
1 parent f6c61d1 commit 1bb2d0e

File tree

12 files changed

+50
-172
lines changed

12 files changed

+50
-172
lines changed

src/bin/crackers/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ fn new(path: PathBuf) -> anyhow::Result<()> {
5656
let config = CrackersConfig {
5757
meta: Default::default(),
5858
specification: SpecificationConfig {
59-
path: "spec.o".to_string(),
6059
max_instructions: 1,
6160
},
6261
library: Default::default(),
@@ -122,7 +121,7 @@ fn synthesize(config: PathBuf) -> anyhow::Result<()> {
122121
.init();
123122
let params = p.resolve()?;
124123

125-
match params.build_single(&z3) {
124+
match params.build_combined(&z3) {
126125
Ok(mut p) => match p.decide() {
127126
Ok(res) => match res {
128127
DecisionResult::AssignmentFound(a) => {

src/config/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ impl CrackersConfig {
3838
b.pointer_invariants(c.get_pointer_constraints().collect());
3939
}
4040
b.gadget_library(library)
41-
.seed(self.meta.seed)
42-
.instructions(self.specification.get_spec(&self.sleigh)?);
41+
.seed(self.meta.seed).slots(self.specification.max_instructions);
4342
b.selection_strategy(self.synthesis.strategy);
4443
b.candidates_per_slot(self.synthesis.max_candidates_per_slot);
4544
b.parallel(self.synthesis.parallel).seed(self.meta.seed);

src/config/specification.rs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,10 @@
1-
use std::fs;
2-
3-
use jingle::sleigh::context::loaded::LoadedSleighContext;
4-
use jingle::sleigh::Instruction;
5-
use object::{File, Object, ObjectSymbol};
61
use serde::{Deserialize, Serialize};
72

8-
use crate::config::error::CrackersConfigError;
9-
use crate::config::error::CrackersConfigError::{SpecMissingStartSymbol, SpecMissingTextSection};
10-
use crate::config::object::load_sleigh_spec;
11-
use crate::config::sleigh::SleighConfig;
12-
133
#[derive(Clone, Debug, Deserialize, Serialize)]
144
pub struct SpecificationConfig {
15-
pub path: String,
165
pub max_instructions: usize,
176
}
187

198
impl SpecificationConfig {
20-
pub fn load_sleigh<'a>(
21-
&self,
22-
sleigh_config: &'a SleighConfig,
23-
) -> Result<LoadedSleighContext<'a>, CrackersConfigError> {
24-
load_sleigh_spec(&self.path, sleigh_config)
25-
}
269

27-
pub fn get_spec(
28-
&self,
29-
sleigh_config: &SleighConfig,
30-
) -> Result<Vec<Instruction>, CrackersConfigError> {
31-
let data = fs::read(&self.path)?;
32-
let gimli_file = File::parse(&*data)?;
33-
let sym = gimli_file
34-
.symbol_by_name("_start")
35-
.ok_or(SpecMissingStartSymbol)?;
36-
let _section = gimli_file
37-
.section_by_name(".text")
38-
.ok_or(SpecMissingTextSection)?;
39-
let sleigh = self.load_sleigh(sleigh_config)?;
40-
let instrs: Vec<Instruction> = sleigh
41-
.read_until_branch(sym.address(), self.max_instructions)
42-
.collect();
43-
Ok(instrs)
44-
}
4510
}

src/gadget/another_iterator.rs

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
use std::sync::Arc;
2+
13
use jingle::modeling::{ModeledInstruction, ModelingContext};
24
use jingle::sleigh::{Instruction, OpCode};
35
use jingle::JingleContext;
46
use tracing::trace;
5-
use z3::ast::Ast;
7+
use z3::ast::{Ast, Bool};
68
use z3::Solver;
79

810
use crate::gadget::signature::GadgetSignature;
911
use crate::gadget::Gadget;
12+
use crate::synthesis::builder::StateConstraintGenerator;
1013

1114
pub struct TraceCandidateIterator<'ctx, 'a, T>
1215
where
@@ -15,20 +18,27 @@ where
1518
jingle: JingleContext<'ctx>,
1619
_solver: Solver<'ctx>,
1720
gadgets: T,
18-
trace: Vec<ModeledInstruction<'ctx>>,
21+
step_length: usize,
22+
postconditions: Vec<Arc<StateConstraintGenerator>>,
1923
}
2024

2125
impl<'ctx, 'a, T> TraceCandidateIterator<'ctx, 'a, T>
2226
where
2327
T: Iterator<Item = &'a Gadget>,
2428
{
25-
pub(crate) fn new(jingle: &JingleContext<'ctx>, gadgets: T, trace: Vec<ModeledInstruction<'ctx>>) -> Self {
29+
pub(crate) fn new(
30+
jingle: &JingleContext<'ctx>,
31+
gadgets: T,
32+
step_length: usize,
33+
postconditions: Vec<Arc<StateConstraintGenerator>>,
34+
) -> Self {
2635
let _solver = Solver::new(jingle.z3);
2736
Self {
2837
jingle: jingle.clone(),
2938
_solver,
3039
gadgets,
31-
trace,
40+
step_length,
41+
postconditions,
3242
}
3343
}
3444
}
@@ -39,41 +49,27 @@ where
3949
type Item = Vec<Option<&'a Gadget>>;
4050

4151
fn next(&mut self) -> Option<Self::Item> {
42-
let mut next_entry = vec![None; self.trace.len()];
4352
loop {
4453
let gadget = self.gadgets.next()?;
45-
let gadget_signature = GadgetSignature::from(gadget);
4654
trace!("Evaluating gadget at {:x}", gadget.address());
47-
let is_candidate: Vec<bool> = self
48-
.trace
49-
.iter()
50-
.map(|i| {
51-
trace!("Checking {} signature vs gadget {}", i.instr.disassembly, gadget);
52-
53-
gadget_signature.covers(&GadgetSignature::from_instr(&i.instr, i))
54-
&& has_compatible_control_flow(&i.instr, gadget)
55-
})
56-
.collect();
57-
if is_candidate.iter().any(|b| *b) {
58-
let model = gadget.model(&self.jingle);
59-
if let Ok(model) = &model {
60-
is_candidate.iter().enumerate().for_each(|(i, c)| {
61-
if *c {
62-
let expr = model
63-
.upholds_postcondition(&self.trace[i])
64-
.unwrap()
65-
.simplify();
66-
if !expr.is_const() || expr.as_bool().unwrap() {
67-
next_entry[i] = Some(gadget)
55+
let model = gadget.model(&self.jingle);
56+
if let Ok(model) = &model {
57+
for predicate in &self.postconditions {
58+
let f = predicate(&self.jingle, model.get_final_state(), 0);
59+
let i = predicate(&self.jingle, model.get_original_state(), 0);
60+
if let Ok(f) = f{
61+
if let Ok(i) = i {
62+
let f = f.simplify();
63+
//
64+
if f.is_const() && f.as_bool().unwrap() || !f.is_const(){
65+
let i = i.simplify();
66+
if !f._eq(&i).simplify().is_const(){
67+
return Some(vec![Some(gadget); self.step_length]);
68+
}
6869
}
6970
}
70-
})
71-
}else{
72-
trace!("Could not model gadget: \n{}", gadget)
71+
}
7372
}
74-
return Some(next_entry);
75-
} else {
76-
continue;
7773
}
7874
}
7975
}

src/gadget/library/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
use std::collections::HashMap;
2-
31
use jingle::modeling::ModeledInstruction;
42
use jingle::sleigh::context::loaded::LoadedSleighContext;
53
use jingle::sleigh::{Instruction, RegisterManager, SpaceInfo, SpaceManager, VarNode};
64
use jingle::{JingleContext, JingleError};
75
use rand::rngs::StdRng;
86
use rand::seq::SliceRandom;
97
use rand::SeedableRng;
8+
use std::collections::HashMap;
9+
use std::sync::Arc;
1010
use tracing::{event, Level};
1111

1212
use crate::gadget::another_iterator::TraceCandidateIterator;
1313
use crate::gadget::library::builder::GadgetLibraryParams;
1414
use crate::gadget::Gadget;
15+
use crate::synthesis::builder::StateConstraintGenerator;
1516

1617
pub mod builder;
1718
pub mod image;
@@ -33,12 +34,13 @@ impl GadgetLibrary {
3334
pub fn get_random_candidates_for_trace<'ctx, 'a: 'ctx>(
3435
&'a self,
3536
jingle: &JingleContext<'ctx>,
36-
trace: &[ModeledInstruction<'ctx>],
37+
trace_length: usize,
38+
postconditions: &[Arc<StateConstraintGenerator>],
3739
seed: i64,
3840
) -> impl Iterator<Item = Vec<Option<&'a Gadget>>> + 'ctx {
3941
let mut rng = StdRng::seed_from_u64(seed as u64);
4042
let r = self.gadgets.choose_multiple(&mut rng, self.gadgets.len());
41-
TraceCandidateIterator::new(jingle, r, trace.to_vec())
43+
TraceCandidateIterator::new(jingle, r, trace_length, postconditions.to_vec())
4244
}
4345
pub(super) fn build_from_image(
4446
sleigh: LoadedSleighContext,

src/synthesis/builder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::sync::Arc;
22

33
use derive_builder::Builder;
44
use jingle::modeling::{ModeledBlock, State};
5-
use jingle::sleigh::Instruction;
65
use jingle::JingleContext;
76
use serde::{Deserialize, Serialize};
87
use z3::ast::Bool;
@@ -44,7 +43,7 @@ pub struct SynthesisParams {
4443
pub gadget_library: Arc<GadgetLibrary>,
4544
pub candidates_per_slot: usize,
4645
pub parallel: usize,
47-
pub instructions: Vec<Instruction>,
46+
pub slots: usize,
4847
#[builder(default)]
4948
pub preconditions: Vec<Arc<StateConstraintGenerator>>,
5049
#[builder(default)]

src/synthesis/combined.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,14 @@ pub struct CombinedAssignmentSynthesis<'a> {
1515

1616
impl<'a> CombinedAssignmentSynthesis<'a> {
1717
pub fn decide(&mut self) -> Result<DecisionResult<'a, ModeledBlock<'a>>, CrackersError> {
18-
let mut ordering: Vec<Vec<Instruction>> = self
19-
.base_config
20-
.instructions
21-
.partitions()
22-
.map(|part| {
23-
part.into_iter()
24-
.map(|instrs| Instruction::try_from(instrs).unwrap())
25-
.collect::<Vec<Instruction>>()
26-
})
27-
.collect();
28-
// let mut blacklist = HashSet::new();
29-
// todo: gross hack to avoid rewriting the partitioning algorithm to be breadth-first
30-
ordering.sort_by(|a, b| a.len().partial_cmp(&b.len()).unwrap());
31-
let iter = ordering.into_iter();
3218
let mut last: Option<DecisionResult<'a, ModeledBlock<'a>>> = None;
33-
for instructions in iter {
19+
for i in 1..=self.base_config.slots{
3420
// todo: filter for instruction combinations that have already been ruled out?
3521
// if instructions.iter().any(|i| blacklist.contains(i)) {
3622
// continue;
3723
// }
3824
let mut new_config = self.base_config.clone();
39-
new_config.instructions = instructions;
25+
new_config.slots = i;
4026
let synth = AssignmentSynthesis::new(self.z3, &new_config);
4127
if let Ok(mut synth) = synth {
4228
// this one constructed, let's try it

src/synthesis/mod.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,20 @@ pub struct AssignmentSynthesis<'ctx> {
5959
preconditions: Vec<Arc<StateConstraintGenerator>>,
6060
postconditions: Vec<Arc<StateConstraintGenerator>>,
6161
candidates_per_slot: usize,
62-
instructions: Vec<Instruction>,
62+
slots: usize,
6363
parallel: usize,
6464
}
6565

6666
impl<'ctx> AssignmentSynthesis<'ctx> {
6767
pub fn new(z3: &'ctx Context, builder: &SynthesisParams) -> Result<Self, CrackersError> {
68-
let instrs = &builder.instructions;
69-
if instrs.is_empty() {
70-
return Err(EmptySpecification);
71-
}
7268
let jingle = JingleContext::new(z3, builder.gadget_library.as_ref());
73-
let modeled_instrs: Vec<ModeledInstruction<'ctx>> = instrs
74-
.iter()
75-
.map(|i| {
76-
ModeledInstruction::new(i.clone(), &jingle).unwrap()
77-
})
78-
.collect();
7969

8070
let candidates = CandidateBuilder::default()
8171
.with_random_sample_size(builder.candidates_per_slot)
8272
.build(builder.gadget_library.get_random_candidates_for_trace(
8373
&jingle,
84-
modeled_instrs.as_slice(),
74+
builder.slots,
75+
builder.postconditions.as_slice(),
8576
builder.seed,
8677
))?;
8778
let outer_problem = match builder.selection_strategy {
@@ -92,9 +83,6 @@ impl<'ctx> AssignmentSynthesis<'ctx> {
9283
OptimizeProb(OptimizationProblem::initialize(z3, &candidates.candidates))
9384
}
9485
};
95-
for x in &builder.instructions {
96-
println!("{}", x.disassembly)
97-
}
9886
Ok(AssignmentSynthesis {
9987
z3,
10088
outer_problem,
@@ -104,7 +92,7 @@ impl<'ctx> AssignmentSynthesis<'ctx> {
10492
preconditions: builder.preconditions.clone(),
10593
postconditions: builder.postconditions.clone(),
10694
candidates_per_slot: builder.candidates_per_slot,
107-
instructions: builder.instructions.clone(),
95+
slots: builder.slots,
10896
parallel: builder.parallel,
10997
})
11098
}
@@ -117,8 +105,7 @@ impl<'ctx> AssignmentSynthesis<'ctx> {
117105
.with_pointer_invariants(&self.pointer_invariants)
118106
.with_preconditions(&self.preconditions)
119107
.with_postconditions(&self.postconditions)
120-
.with_max_candidates(self.candidates_per_slot)
121-
.with_templates(self.instructions.clone().into_iter());
108+
.with_max_candidates(self.candidates_per_slot);
122109
let (resp_sender, resp_receiver) = std::sync::mpsc::channel();
123110
std::thread::scope(|s| {
124111
for idx in 0..self.parallel {

0 commit comments

Comments
 (0)