Created
November 24, 2015 16:48
-
-
Save XMPPwocky/f906543a2c6436d679af to your computer and use it in GitHub Desktop.
oldbeef
This file contains hidden or 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
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