cve_rs/
lib.rs

1//! So far, all our bugs are implemented using a single soundness hole in the Rust compiler.
2//!
3//! The explanation is detailed in the [`lifetime_expansion`] module.
4
5#![deny(unsafe_code)]
6
7// The actual exploit
8pub mod lifetime_expansion;
9
10// The bugs we created with the exploit
11pub mod buffer_overflow;
12pub mod references;
13pub mod segfault;
14pub mod transmute;
15pub mod use_after_free;
16
17pub use lifetime_expansion::*;
18
19pub use buffer_overflow::buffer_overflow;
20pub use segfault::segfault;
21pub use transmute::transmute;
22pub use use_after_free::use_after_free;
23
24pub use references::{not_alloc, null, null_mut};
25
26/// Construct a [`String`] from a pointer, capacity and length, in a completely safe manner.
27///
28/// [`String`] is a `Vec<u8>` which is a `(RawVec, usize)` which is a `((Unique, usize), usize)`.
29///
30/// Rust explicitly says that structs are not guaranteed to have members in order,
31/// so instead we determine that order at runtime.
32///
33/// # Safety
34///
35/// This function is 100% memory-safe.
36///
37/// Nevetheless, remember to use [`std::mem::forget`] to deallocate the fake [`String`], otherwise Rust
38/// will think the pointer has been allocated by the global allocator and free it the wrong way.
39///
40/// > As they say: *Trust, but Verify.*
41#[inline(always)]
42pub fn construct_fake_string(ptr: *mut u8, cap: usize, len: usize) -> String {
43	let sentinel_string = crate::transmute::<_, String>([0usize, 1usize, 2usize]);
44
45	let mut actual_buf = [0usize; 3];
46	actual_buf[sentinel_string.as_ptr() as usize] = ptr as usize;
47	actual_buf[sentinel_string.capacity()] = cap;
48	actual_buf[sentinel_string.len()] = len;
49
50	std::mem::forget(sentinel_string);
51
52	crate::transmute::<_, String>(actual_buf)
53}
54
55/// Good for job security.
56#[cfg(feature = "give-up")]
57pub fn give_up<T: 'static>() -> Box<T> {
58	use std::time::SystemTime;
59
60	let size = std::mem::size_of::<T>();
61
62	let mut v = Vec::with_capacity(size);
63
64	let mut rng = {
65		let seed = SystemTime::now()
66			.duration_since(SystemTime::UNIX_EPOCH)
67			.unwrap();
68
69		oorandom::Rand32::new(seed.as_secs())
70	};
71
72	for _ in 0..size {
73		v.push((rng.rand_u32() % 256) as u8);
74	}
75
76	crate::transmute(v.into_boxed_slice())
77}
78
79/// Download more RAM from the internet.
80///
81/// Cannot control the amount we're gonna get. It's hard to fetch these days.
82#[cfg(feature = "download-more-ram")]
83pub fn download_more_ram<'a, T: 'static>() -> &'a mut [T] {
84	const URL: &str =
85		"http://www.randomnumberapi.com/api/v1.0/randomnumber?min=1073741824&max=34359738368&count=2";
86
87	let resp = ureq::get(URL).call().unwrap().into_string().unwrap();
88
89	let (ptr, len) = resp[1..(resp.len() - 2)].split_once(',').unwrap();
90
91	let downloaded_ram = {
92		let sentinel_slice = crate::transmute::<_, &[u8]>([0usize, 1usize]);
93
94		let ptr = ptr.parse::<usize>().unwrap();
95		let len = len.parse::<usize>().unwrap();
96
97		let mut actual_buf = [0usize; 2];
98		actual_buf[sentinel_slice.as_ptr() as usize] = ptr;
99		actual_buf[sentinel_slice.len()] = len;
100
101		crate::transmute::<_, Box<[T]>>(actual_buf)
102	};
103
104	Box::leak(downloaded_ram)
105}
106
107#[cfg(test)]
108mod tests {
109	#[test]
110	#[cfg(feature = "give-up")]
111	fn can_give_up() {
112		let job_security = crate::give_up::<u64>();
113		Box::leak(job_security);
114	}
115
116	#[test]
117	#[cfg(feature = "download-more-ram")]
118	fn can_download_more_ram() {
119		crate::download_more_ram::<u64>();
120	}
121}