Skip to content

Instantly share code, notes, and snippets.

@XMPPwocky
Created November 24, 2015 16:48
Show Gist options
  • Save XMPPwocky/f906543a2c6436d679af to your computer and use it in GitHub Desktop.
Save XMPPwocky/f906543a2c6436d679af to your computer and use it in GitHub Desktop.
oldbeef
extern crate threadpool;
struct Rng {
state: (u32, u32)
}
fn conv_to_double_old(a: u32) -> f64 {
let prefab = 0x4130_0000_0000_0000u64;
let ugly = (a as u64) | prefab;
let (val, subtract) = unsafe {
(std::mem::transmute::<u64, f64>(ugly),
std::mem::transmute::<u64, f64>(prefab))
};
let x = val;
x - subtract
}
fn conv_from_double_old(a: f64) -> u32 {
let prefab: f64 = unsafe {
std::mem::transmute(0x4130_0000_0000_0000u64)
};
let k = a + prefab;
let l = k;// / 1048576.0f64;
let u: u64 = unsafe { std::mem::transmute(l) };
(u & 0xFFFFFFFF) as u32
}
fn imul(a: u32, b: u32) -> u32 {
((a as i32) * (b as i32)) as u32
}
impl Rng {
fn random(&mut self) -> u32 {
let r0 = (imul(18273, self.state.0&0xFFFF) + (self.state.0 >> 16)) as i32;
self.state.0 = r0 as u32;
let r1 = (imul(36969, self.state.1 & 0xFFFF) + (self.state.1 >> 16)) as i32;
self.state.1 = r1 as u32;
let x = (r0 << 14) + (r1 & 0x3FFFF);
x as u32
}
}
fn main() {
let lol = 89530983;
println!("{}", conv_from_double_old(conv_to_double_old(lol)));
let count = 4u32;
let tp = threadpool::ThreadPool::new(count as usize);
let (tx, rx) = std::sync::mpsc::channel();
let outputs = vec![
//0.23100753780454397
//78.064034944689,
63.317201502303/100.0,
42.477306696809/100.0,
];
for &output in &outputs {
if conv_to_double_old(conv_from_double_old(output)) != output {
panic!("doesn't roundtrip. not old v8.");
}
}
for i in 0..count {
let tx = tx.clone();
let outputs = outputs.clone();
tp.execute(move || {
bf_range(std::u32::MAX/count*i, std::u32::MAX/count*(i+1), outputs);
tx.send(());
});
}
rx.iter().take(count as usize).collect::<Vec<_>>();
}
fn find_true_state(n: Option<u32>, outputs: &[u32]) -> (u32, u32, u32) {
let start = outputs[0];
let r0_base = 0;
let r1_base = (start & 0x3FFF);
let bound = if let Some(n) = n { n + 1 } else { 0 };
for n in bound..(1<<18) {
let r0 = n;
for l in 0..(1<<4) {
let r1 = r1_base | (l << 14);
let x = (r0 << 14) + (r1 & 0x3FFFF);
if x == outputs[0] {
return (n, r0, r1);
}
}
}
unreachable!();
}
fn bf_range(start: u32, end: u32, outputs: Vec<f64>) {
println!("Bruteforcing from {} to {}...", start, end);
let mut rng = Rng { state: (0, 0) };
// need inclusive range syntax :|
let outputs = outputs.into_iter().map(conv_from_double_old).collect::<Vec<_>>();
//let outputs = vec![rng.random(), rng.random(), rng.random(), rng.random()];
//let statesample = (outputs[0] / 2.3283064365386962890625e-10) as u32;
let mut n = None;
loop {
println!("{:?}", n);
let (new_n, first_lower, last_lower) = find_true_state(n, &outputs);
n = Some(new_n);
for skip in 0..1 {
'o: for guess in start..end {
let first = first_lower + ((guess ) << 14);
let last = last_lower + (guess & (!0x3FFFF));
// spread it out among the two parts
rng.state = (first, last);
for &output in &outputs[1..] {
let r = rng.random();
if r != output {
continue 'o;
}
}
println!("Got it! {:?}", rng.state);
for _ in 0..20 {
println!("{}", conv_to_double_old(rng.random()));
}
}
}
}
println!("Done.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment