-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexflag.rs
96 lines (85 loc) · 2.98 KB
/
exflag.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! =====================================================
//! exflag2 (brute force), rs edition
//! by Arc'blroth
//! =====================================================
use rayon::prelude::{ParallelBridge, ParallelIterator};
/// Exfiltrates a flag, character by character, given a brute-force oracle and a charset.
fn extract_flag2<Checker>(checker: Checker, prefix: &[u8], charset: &[u8]) -> String
where
Checker: Fn(&[u8]) -> bool + Send + Sync + 'static,
{
struct FlagGenerator<'f> {
charset: &'f [u8],
prefix: &'f [u8],
flag_len: usize,
flag: Vec<usize>,
try_flag: Vec<u8>,
ready_for_next_len: bool,
}
impl<'f> FlagGenerator<'f> {
pub fn new(charset: &'f [u8], prefix: &'f [u8]) -> Self {
let flag_len = 1;
let flag = vec![0usize; flag_len];
let mut try_flag = vec![0u8; prefix.len() + flag_len];
try_flag[0..prefix.len()].copy_from_slice(prefix);
Self {
charset,
prefix,
flag_len,
flag,
try_flag,
ready_for_next_len: false,
}
}
}
impl<'f> Iterator for FlagGenerator<'f> {
type Item = Vec<u8>;
fn next(&mut self) -> Option<Self::Item> {
if self.ready_for_next_len {
self.flag_len += 1;
for c in &mut self.flag {
*c = 0;
}
self.flag.push(0);
for c in &mut self.try_flag[self.prefix.len()..] {
*c = 0;
}
self.try_flag.push(0);
self.ready_for_next_len = false;
}
self.flag
.iter()
.map(|x| self.charset[*x])
.enumerate()
.for_each(|(i, x)| self.try_flag[self.prefix.len() + i] = x);
let out = Some(self.try_flag.clone());
let mut update_index = self.flag.len() - 1;
loop {
if self.flag[update_index] < self.charset.len() - 1 {
self.flag[update_index] += 1;
break;
} else if update_index > 0 {
self.flag[update_index] = 0;
update_index -= 1;
} else {
self.ready_for_next_len = true;
break;
}
}
out
}
}
FlagGenerator::new(charset, prefix)
.par_bridge()
.try_for_each(|try_flag| {
let try_flag_as_str = std::str::from_utf8(&try_flag).unwrap();
println!("\x1b[90mTrying \"{}\"\x1b[0m", try_flag_as_str);
if checker(&try_flag) {
println!("\x1b[33mFound \"{}\"!\x1b[0m", try_flag_as_str);
Err(String::from(try_flag_as_str.clone()))
} else {
Ok(())
}
})
.unwrap_err()
}