-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #221 from Freax13/aslr
add ASLR
- Loading branch information
Showing
9 changed files
with
263 additions
and
36 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; | ||
use raw_cpuid::CpuId; | ||
use x86_64::instructions::{port::Port, random::RdRand}; | ||
|
||
/// Gather entropy from various sources to seed a RNG. | ||
pub fn build_rng() -> ChaCha20Rng { | ||
const ENTROPY_SOURCES: [fn() -> [u8; 32]; 3] = [rd_rand_entropy, tsc_entropy, pit_entropy]; | ||
|
||
// Collect entropy from different sources and xor them all together. | ||
let mut seed = [0; 32]; | ||
for entropy_source in ENTROPY_SOURCES { | ||
let entropy = entropy_source(); | ||
|
||
for (seed, entropy) in seed.iter_mut().zip(entropy) { | ||
*seed ^= entropy; | ||
} | ||
} | ||
|
||
// Construct the RNG. | ||
ChaCha20Rng::from_seed(seed) | ||
} | ||
|
||
/// Gather entropy by requesting random numbers with `RDRAND` instruction if it's available. | ||
/// | ||
/// This function provides excellent entropy (unless you don't trust the CPU vendors). | ||
fn rd_rand_entropy() -> [u8; 32] { | ||
let mut entropy = [0; 32]; | ||
|
||
// Check if the CPU supports `RDRAND`. | ||
if let Some(rd_rand) = RdRand::new() { | ||
for i in 0..4 { | ||
if let Some(value) = get_random_64(rd_rand) { | ||
entropy[i * 8..(i + 1) * 8].copy_from_slice(&value.to_ne_bytes()); | ||
} | ||
} | ||
} | ||
|
||
entropy | ||
} | ||
|
||
/// Try to fetch a 64 bit random value with a retry count limit of 10. | ||
/// | ||
/// This function is a port of the C implementation provided in Intel's Software Developer's Manual, Volume 1, 7.3.17.1. | ||
fn get_random_64(rd_rand: RdRand) -> Option<u64> { | ||
const RETRY_LIMIT: u32 = 10; | ||
for _ in 0..RETRY_LIMIT { | ||
if let Some(value) = rd_rand.get_u64() { | ||
return Some(value); | ||
} | ||
} | ||
None | ||
} | ||
|
||
/// Gather entropy by reading the current time with the `RDTSC` instruction if it's available. | ||
/// | ||
/// This function doesn't provide particulary good entropy, but it's better than nothing. | ||
fn tsc_entropy() -> [u8; 32] { | ||
let mut entropy = [0; 32]; | ||
|
||
// Check if the CPU supports `RDTSC`. | ||
let cpu_id = CpuId::new(); | ||
if let Some(feature_info) = cpu_id.get_feature_info() { | ||
if !feature_info.has_tsc() { | ||
for i in 0..4 { | ||
let value = unsafe { | ||
// SAFETY: We checked that the cpu supports `RDTSC` and we run in ring 0. | ||
core::arch::x86_64::_rdtsc() | ||
}; | ||
entropy[i * 8..(i + 1) * 8].copy_from_slice(&value.to_ne_bytes()); | ||
} | ||
} | ||
} | ||
|
||
entropy | ||
} | ||
|
||
/// Gather entropy by reading the current count of PIT channel 1-3. | ||
/// | ||
/// This function doesn't provide particulary good entropy, but it's always available. | ||
fn pit_entropy() -> [u8; 32] { | ||
let mut entropy = [0; 32]; | ||
|
||
for (i, entropy_byte) in entropy.iter_mut().enumerate() { | ||
// Cycle through channels 1-3. | ||
let channel = i % 3; | ||
|
||
let mut port = Port::<u8>::new(0x40 + channel as u16); | ||
let value = unsafe { | ||
// SAFETY: It's safe to read from ports 0x40-0x42. | ||
port.read() | ||
}; | ||
|
||
*entropy_byte = value; | ||
} | ||
|
||
entropy | ||
} |
This file contains 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
This file contains 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
Oops, something went wrong.