mirror of
https://github.com/PatchRequest/BusyWork
synced 2026-06-09 16:04:04 +00:00
Expand all task categories with 50+ new variations
Compute: 6→14 tasks (fibonacci, xor cipher, collatz, string ops, bubble sort, bitwise, pi approx, permutations) Memory: 4→10 tasks (heap fragmentation, ring buffer, binary search, scatter/gather, interleave) Filesystem: 4→12 tasks (Program Files, fonts, drivers, prefetch, logs, DLL stats, user profile) Registry: 4→10 tasks (env vars, network config, CPU info, fonts, startup programs, file associations) WinAPI: 4→16 tasks (system metrics, cursor, drives, volumes, disk space, FindFile, modules, VirtualQuery) Network: 3→7 tasks (24 DNS hosts, 11 HTTP endpoints, 7 NTP servers, HEAD, POST, TCP probes) Crypto: 2→7 tasks (SHA-512, SHA-1, MD5 via BCrypt, AES encrypt, RNG algorithms)
This commit is contained in:
@@ -40,6 +40,9 @@ cat-winapi = [
|
||||
"windows/Win32_System_DataExchange",
|
||||
"windows/Win32_Foundation",
|
||||
"windows/Win32_System_Threading",
|
||||
"windows/Win32_Storage_FileSystem",
|
||||
"windows/Win32_System_Memory",
|
||||
"windows/Win32_System_LibraryLoader",
|
||||
]
|
||||
cat-network = []
|
||||
cat-crypto = [
|
||||
|
||||
@@ -41,6 +41,46 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::COMPUTE,
|
||||
func: compress_decompress,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "fibonacci_sequence",
|
||||
category: Categories::COMPUTE,
|
||||
func: fibonacci_sequence,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "xor_cipher",
|
||||
category: Categories::COMPUTE,
|
||||
func: xor_cipher,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "collatz_sequence",
|
||||
category: Categories::COMPUTE,
|
||||
func: collatz_sequence,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "string_operations",
|
||||
category: Categories::COMPUTE,
|
||||
func: string_operations,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bubble_sort",
|
||||
category: Categories::COMPUTE,
|
||||
func: bubble_sort,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bitwise_operations",
|
||||
category: Categories::COMPUTE,
|
||||
func: bitwise_operations,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "pi_approximation",
|
||||
category: Categories::COMPUTE,
|
||||
func: pi_approximation,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "permutation_generate",
|
||||
category: Categories::COMPUTE,
|
||||
func: permutation_generate,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -145,3 +185,139 @@ fn compress_decompress(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
black_box(&decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
fn fibonacci_sequence(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let mut a: u128 = 0;
|
||||
let mut b: u128 = 1;
|
||||
for _ in 0..params.iterations {
|
||||
let next = a.wrapping_add(b);
|
||||
a = b;
|
||||
b = next;
|
||||
}
|
||||
black_box(b);
|
||||
}
|
||||
|
||||
fn xor_cipher(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let mut key = [0u8; 256];
|
||||
rng.fill_bytes(&mut key);
|
||||
let size = params.buffer_size.min(1_048_576);
|
||||
for _ in 0..params.call_depth {
|
||||
let mut data = vec![0u8; size];
|
||||
rng.fill_bytes(&mut data);
|
||||
for (i, byte) in data.iter_mut().enumerate() {
|
||||
*byte ^= key[i % 256];
|
||||
}
|
||||
black_box(&data);
|
||||
}
|
||||
}
|
||||
|
||||
fn collatz_sequence(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let iteration_limit = 10_000usize;
|
||||
for _ in 0..params.iterations {
|
||||
let mut n: u64 = rng.gen::<u64>().saturating_add(1);
|
||||
let mut steps = 0usize;
|
||||
while n != 1 && steps < iteration_limit {
|
||||
if n % 2 == 0 {
|
||||
n /= 2;
|
||||
} else {
|
||||
n = n.saturating_mul(3).saturating_add(1);
|
||||
}
|
||||
steps += 1;
|
||||
}
|
||||
black_box(steps);
|
||||
}
|
||||
}
|
||||
|
||||
fn string_operations(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let size = params.buffer_size.min(65536).max(1);
|
||||
for _ in 0..params.call_depth {
|
||||
let s: String = (0..size)
|
||||
.map(|_| {
|
||||
let c = rng.gen_range(32u8..127u8);
|
||||
c as char
|
||||
})
|
||||
.collect();
|
||||
|
||||
let reversed: String = s.chars().rev().collect();
|
||||
black_box(&reversed);
|
||||
|
||||
let upper = s.to_uppercase();
|
||||
black_box(&upper);
|
||||
|
||||
let lower = s.to_lowercase();
|
||||
black_box(&lower);
|
||||
|
||||
let count = s.chars().filter(|&c| c == 'a' || c == 'A').count();
|
||||
black_box(count);
|
||||
|
||||
let found = s.find("the");
|
||||
black_box(found);
|
||||
}
|
||||
}
|
||||
|
||||
fn bubble_sort(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let size = (params.buffer_size / 4).min(4096).max(1);
|
||||
for _ in 0..params.call_depth {
|
||||
let mut data: Vec<u32> = (0..size).map(|_| rng.gen()).collect();
|
||||
let n = data.len();
|
||||
for i in 0..n {
|
||||
for j in 0..n.saturating_sub(i + 1) {
|
||||
if data[j] > data[j + 1] {
|
||||
data.swap(j, j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
black_box(&data);
|
||||
}
|
||||
}
|
||||
|
||||
fn bitwise_operations(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let mut accum: u64 = rng.gen();
|
||||
for _ in 0..params.iterations {
|
||||
let val: u64 = rng.gen();
|
||||
let shift = (val & 0x3F) as u32; // 0..63
|
||||
accum ^= val.wrapping_shl(shift);
|
||||
accum ^= val.wrapping_shr(shift);
|
||||
accum = accum.rotate_left(shift);
|
||||
accum = accum.rotate_right(shift.wrapping_add(1) & 0x3F);
|
||||
accum ^= val.count_ones() as u64;
|
||||
accum ^= val.leading_zeros() as u64;
|
||||
accum ^= val.trailing_zeros() as u64;
|
||||
accum ^= val.swap_bytes();
|
||||
}
|
||||
black_box(accum);
|
||||
}
|
||||
|
||||
fn pi_approximation(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let mut sum: f64 = 0.0;
|
||||
for k in 0..params.iterations {
|
||||
let sign = if k % 2 == 0 { 1.0f64 } else { -1.0f64 };
|
||||
sum += sign / (2 * k + 1) as f64;
|
||||
}
|
||||
let pi = 4.0 * sum;
|
||||
black_box(pi);
|
||||
}
|
||||
|
||||
fn permutation_generate(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let n = params.call_depth.min(10).max(1);
|
||||
let mut arr: Vec<usize> = (0..n).collect();
|
||||
// Heap's algorithm (iterative)
|
||||
let mut c = vec![0usize; n];
|
||||
black_box(&arr);
|
||||
let mut i = 0;
|
||||
while i < n {
|
||||
if c[i] < i {
|
||||
if i % 2 == 0 {
|
||||
arr.swap(0, i);
|
||||
} else {
|
||||
arr.swap(c[i], i);
|
||||
}
|
||||
black_box(&arr);
|
||||
c[i] += 1;
|
||||
i = 0;
|
||||
} else {
|
||||
c[i] = 0;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,31 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_hash,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bcrypt_sha512",
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_sha512,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bcrypt_md5_hash",
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_md5_hash,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bcrypt_sha1_hash",
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_sha1_hash,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bcrypt_aes_encrypt",
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_aes_encrypt,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "bcrypt_rng_algorithms",
|
||||
category: Categories::CRYPTO,
|
||||
func: bcrypt_rng_algorithms,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -71,3 +96,205 @@ fn bcrypt_hash(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn bcrypt_sha512(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let data_size = params.buffer_size.min(65536);
|
||||
let mut data = vec![0u8; data_size];
|
||||
rng.fill_bytes(&mut data);
|
||||
|
||||
unsafe {
|
||||
let mut alg = BCRYPT_ALG_HANDLE::default();
|
||||
let status = BCryptOpenAlgorithmProvider(
|
||||
&mut alg,
|
||||
windows::core::w!("SHA512"),
|
||||
None,
|
||||
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS(0),
|
||||
);
|
||||
if status.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..params.iterations.min(100) {
|
||||
let mut hash_handle = BCRYPT_HASH_HANDLE::default();
|
||||
let status = BCryptCreateHash(alg, &mut hash_handle, None, None, 0);
|
||||
if status.0 != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = BCryptHashData(hash_handle, &data, 0);
|
||||
|
||||
let mut output = vec![0u8; 64]; // SHA-512 output
|
||||
let _ = BCryptFinishHash(hash_handle, &mut output, 0);
|
||||
|
||||
black_box(&output);
|
||||
let _ = BCryptDestroyHash(hash_handle);
|
||||
}
|
||||
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn bcrypt_md5_hash(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let data_size = params.buffer_size.min(65536);
|
||||
let mut data = vec![0u8; data_size];
|
||||
rng.fill_bytes(&mut data);
|
||||
|
||||
unsafe {
|
||||
let mut alg = BCRYPT_ALG_HANDLE::default();
|
||||
let status = BCryptOpenAlgorithmProvider(
|
||||
&mut alg,
|
||||
windows::core::w!("MD5"),
|
||||
None,
|
||||
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS(0),
|
||||
);
|
||||
if status.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..params.iterations.min(100) {
|
||||
let mut hash_handle = BCRYPT_HASH_HANDLE::default();
|
||||
let status = BCryptCreateHash(alg, &mut hash_handle, None, None, 0);
|
||||
if status.0 != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = BCryptHashData(hash_handle, &data, 0);
|
||||
|
||||
let mut output = vec![0u8; 16]; // MD5 output
|
||||
let _ = BCryptFinishHash(hash_handle, &mut output, 0);
|
||||
|
||||
black_box(&output);
|
||||
let _ = BCryptDestroyHash(hash_handle);
|
||||
}
|
||||
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn bcrypt_sha1_hash(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let data_size = params.buffer_size.min(65536);
|
||||
let mut data = vec![0u8; data_size];
|
||||
rng.fill_bytes(&mut data);
|
||||
|
||||
unsafe {
|
||||
let mut alg = BCRYPT_ALG_HANDLE::default();
|
||||
let status = BCryptOpenAlgorithmProvider(
|
||||
&mut alg,
|
||||
windows::core::w!("SHA1"),
|
||||
None,
|
||||
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS(0),
|
||||
);
|
||||
if status.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..params.iterations.min(100) {
|
||||
let mut hash_handle = BCRYPT_HASH_HANDLE::default();
|
||||
let status = BCryptCreateHash(alg, &mut hash_handle, None, None, 0);
|
||||
if status.0 != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = BCryptHashData(hash_handle, &data, 0);
|
||||
|
||||
let mut output = vec![0u8; 20]; // SHA-1 output
|
||||
let _ = BCryptFinishHash(hash_handle, &mut output, 0);
|
||||
|
||||
black_box(&output);
|
||||
let _ = BCryptDestroyHash(hash_handle);
|
||||
}
|
||||
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn bcrypt_aes_encrypt(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let plaintext_size = params.buffer_size.min(4096);
|
||||
let mut plaintext = vec![0u8; plaintext_size];
|
||||
rng.fill_bytes(&mut plaintext);
|
||||
|
||||
let mut key_bytes = [0u8; 32]; // AES-256 key
|
||||
rng.fill_bytes(&mut key_bytes);
|
||||
|
||||
unsafe {
|
||||
let mut alg = BCRYPT_ALG_HANDLE::default();
|
||||
let status = BCryptOpenAlgorithmProvider(
|
||||
&mut alg,
|
||||
windows::core::w!("AES"),
|
||||
None,
|
||||
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS(0),
|
||||
);
|
||||
if status.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..params.call_depth.min(50) {
|
||||
let mut key_handle = BCRYPT_KEY_HANDLE::default();
|
||||
let status = BCryptGenerateSymmetricKey(
|
||||
alg,
|
||||
&mut key_handle,
|
||||
None,
|
||||
&key_bytes,
|
||||
0,
|
||||
);
|
||||
if status.0 != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Output buffer: plaintext + 16 bytes for AES block padding
|
||||
let mut output = vec![0u8; plaintext_size + 16];
|
||||
let mut bytes_written: u32 = 0;
|
||||
|
||||
let _ = BCryptEncrypt(
|
||||
key_handle,
|
||||
Some(&plaintext),
|
||||
None,
|
||||
None,
|
||||
Some(&mut output),
|
||||
&mut bytes_written,
|
||||
BCRYPT_BLOCK_PADDING,
|
||||
);
|
||||
|
||||
black_box(&output);
|
||||
black_box(bytes_written);
|
||||
|
||||
let _ = BCryptDestroyKey(key_handle);
|
||||
}
|
||||
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn bcrypt_rng_algorithms(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let alg_ids = [
|
||||
windows::core::w!("RNG"),
|
||||
windows::core::w!("FIPS186DSARNG"),
|
||||
windows::core::w!("DUALECRNG"),
|
||||
];
|
||||
|
||||
let buf_size = params.buffer_size.min(4096);
|
||||
let mut buffer = vec![0u8; buf_size];
|
||||
|
||||
for alg_id in &alg_ids {
|
||||
unsafe {
|
||||
let mut alg = BCRYPT_ALG_HANDLE::default();
|
||||
let status = BCryptOpenAlgorithmProvider(
|
||||
&mut alg,
|
||||
*alg_id,
|
||||
None,
|
||||
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS(0),
|
||||
);
|
||||
if status.0 != 0 {
|
||||
// Algorithm may not be available on this system, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
for _ in 0..params.iterations.min(50) {
|
||||
let _ = BCryptGenRandom(alg, &mut buffer, BCRYPTGENRANDOM_FLAGS(0));
|
||||
black_box(&buffer);
|
||||
}
|
||||
|
||||
let _ = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,46 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::FILESYSTEM,
|
||||
func: read_small_files,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_program_files",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_program_files,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_fonts",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_fonts,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_drivers",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_drivers,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_prefetch",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_prefetch,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_logs",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_logs,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "stat_common_dlls",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: stat_common_dlls,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_system_files_varied",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: read_system_files_varied,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "enumerate_user_profile",
|
||||
category: Categories::FILESYSTEM,
|
||||
func: enumerate_user_profile,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -94,3 +134,182 @@ fn read_small_files(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enumerate_program_files(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let dirs = [r"C:\Program Files", r"C:\Program Files (x86)"];
|
||||
let mut count = 0usize;
|
||||
for dir_path in &dirs {
|
||||
if let Ok(dir) = std::fs::read_dir(dir_path) {
|
||||
for entry in dir {
|
||||
if count >= params.iterations {
|
||||
return Ok(());
|
||||
}
|
||||
let entry = entry?;
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
black_box(meta.is_dir());
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
fn enumerate_fonts(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let dir = std::fs::read_dir(r"C:\Windows\Fonts")?;
|
||||
for (i, entry) in dir.enumerate() {
|
||||
if i >= params.iterations {
|
||||
break;
|
||||
}
|
||||
let entry = entry?;
|
||||
black_box(entry.file_name());
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
fn enumerate_drivers(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let dir = std::fs::read_dir(r"C:\Windows\System32\drivers")?;
|
||||
for (i, entry) in dir.enumerate() {
|
||||
if i >= params.iterations {
|
||||
break;
|
||||
}
|
||||
let entry = entry?;
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
fn enumerate_prefetch(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let dir = std::fs::read_dir(r"C:\Windows\Prefetch")?;
|
||||
for (i, entry) in dir.enumerate() {
|
||||
if i >= params.iterations {
|
||||
break;
|
||||
}
|
||||
let entry = entry?;
|
||||
black_box(entry.file_name());
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
fn enumerate_logs(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let mut count = 0usize;
|
||||
let base = std::path::Path::new(r"C:\Windows\Logs");
|
||||
let dir = std::fs::read_dir(base)?;
|
||||
for entry in dir {
|
||||
if count >= params.iterations {
|
||||
break;
|
||||
}
|
||||
let entry = entry?;
|
||||
black_box(entry.file_name());
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
if meta.is_dir() {
|
||||
if let Ok(subdir) = std::fs::read_dir(entry.path()) {
|
||||
for sub_entry in subdir {
|
||||
if count >= params.iterations {
|
||||
break;
|
||||
}
|
||||
if let Ok(sub_entry) = sub_entry {
|
||||
black_box(sub_entry.file_name());
|
||||
if let Ok(sub_meta) = sub_entry.metadata() {
|
||||
black_box(sub_meta.len());
|
||||
}
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
fn stat_common_dlls(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let dlls = [
|
||||
r"C:\Windows\System32\kernel32.dll",
|
||||
r"C:\Windows\System32\ntdll.dll",
|
||||
r"C:\Windows\System32\user32.dll",
|
||||
r"C:\Windows\System32\gdi32.dll",
|
||||
r"C:\Windows\System32\advapi32.dll",
|
||||
r"C:\Windows\System32\shell32.dll",
|
||||
r"C:\Windows\System32\ole32.dll",
|
||||
r"C:\Windows\System32\oleaut32.dll",
|
||||
r"C:\Windows\System32\msvcrt.dll",
|
||||
r"C:\Windows\System32\ws2_32.dll",
|
||||
r"C:\Windows\System32\crypt32.dll",
|
||||
r"C:\Windows\System32\secur32.dll",
|
||||
r"C:\Windows\System32\winhttp.dll",
|
||||
r"C:\Windows\System32\wininet.dll",
|
||||
r"C:\Windows\System32\mswsock.dll",
|
||||
r"C:\Windows\System32\rpcrt4.dll",
|
||||
r"C:\Windows\System32\combase.dll",
|
||||
r"C:\Windows\System32\bcrypt.dll",
|
||||
r"C:\Windows\System32\ncrypt.dll",
|
||||
r"C:\Windows\System32\shlwapi.dll",
|
||||
];
|
||||
for _ in 0..params.iterations {
|
||||
if let Some(path) = dlls.choose(rng) {
|
||||
if let Ok(meta) = std::fs::metadata(path) {
|
||||
black_box(meta.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_system_files_varied(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let paths = [
|
||||
r"C:\Windows\win.ini",
|
||||
r"C:\Windows\system.ini",
|
||||
r"C:\Windows\System32\drivers\etc\hosts",
|
||||
r"C:\Windows\System32\drivers\etc\services",
|
||||
r"C:\Windows\System32\drivers\etc\protocol",
|
||||
];
|
||||
for _ in 0..params.iterations {
|
||||
if let Some(path) = paths.choose(rng) {
|
||||
if let Ok(data) = std::fs::read(path) {
|
||||
black_box(data.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enumerate_user_profile(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
let _ = (|| -> std::io::Result<()> {
|
||||
let profile = std::env::var("USERPROFILE").map_err(|_| {
|
||||
std::io::Error::new(std::io::ErrorKind::NotFound, "USERPROFILE not set")
|
||||
})?;
|
||||
let dir = std::fs::read_dir(profile)?;
|
||||
for (i, entry) in dir.enumerate() {
|
||||
if i >= params.iterations {
|
||||
break;
|
||||
}
|
||||
let entry = entry?;
|
||||
black_box(entry.file_name());
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
black_box(meta.len());
|
||||
black_box(meta.is_dir());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,36 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::MEMORY,
|
||||
func: pattern_fill_verify,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "heap_fragmentation",
|
||||
category: Categories::MEMORY,
|
||||
func: heap_fragmentation,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "ring_buffer_ops",
|
||||
category: Categories::MEMORY,
|
||||
func: ring_buffer_ops,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "binary_search_repeated",
|
||||
category: Categories::MEMORY,
|
||||
func: binary_search_repeated,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "reverse_buffer",
|
||||
category: Categories::MEMORY,
|
||||
func: reverse_buffer,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "interleave_buffers",
|
||||
category: Categories::MEMORY,
|
||||
func: interleave_buffers,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "scatter_gather",
|
||||
category: Categories::MEMORY,
|
||||
func: scatter_gather,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -71,3 +101,131 @@ fn pattern_fill_verify(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
black_box(valid);
|
||||
}
|
||||
}
|
||||
|
||||
fn heap_fragmentation(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let count = params.iterations.min(500);
|
||||
let mut buffers: Vec<Option<Vec<u8>>> = Vec::with_capacity(count);
|
||||
|
||||
// Allocate many small random-sized buffers
|
||||
for _ in 0..count {
|
||||
let size = rng.gen_range(16..=4096);
|
||||
let mut buf = vec![0u8; size];
|
||||
rng.fill_bytes(&mut buf);
|
||||
buffers.push(Some(buf));
|
||||
}
|
||||
|
||||
// Drop roughly 50% at random
|
||||
for slot in buffers.iter_mut() {
|
||||
if rng.gen_bool(0.5) {
|
||||
*slot = None;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate more to fill gaps
|
||||
let mut total_bytes = 0usize;
|
||||
for slot in buffers.iter_mut() {
|
||||
if slot.is_none() {
|
||||
let size = rng.gen_range(16..=4096);
|
||||
let mut buf = vec![0u8; size];
|
||||
rng.fill_bytes(&mut buf);
|
||||
total_bytes += size;
|
||||
*slot = Some(buf);
|
||||
} else {
|
||||
total_bytes += slot.as_ref().unwrap().len();
|
||||
}
|
||||
}
|
||||
|
||||
black_box(total_bytes);
|
||||
black_box(&buffers);
|
||||
}
|
||||
|
||||
fn ring_buffer_ops(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let size = params.buffer_size.min(1_048_576).max(1);
|
||||
let mut buffer = vec![0u8; size];
|
||||
let mut write_pos: usize = 0;
|
||||
let mut read_pos: usize = 0;
|
||||
|
||||
for _ in 0..params.iterations {
|
||||
// Write a random byte at write_pos
|
||||
buffer[write_pos] = rng.gen();
|
||||
write_pos = (write_pos + 1) % size;
|
||||
|
||||
// Read at read_pos
|
||||
let val = buffer[read_pos];
|
||||
black_box(val);
|
||||
read_pos = (read_pos + 1) % size;
|
||||
}
|
||||
|
||||
black_box(&buffer);
|
||||
}
|
||||
|
||||
fn binary_search_repeated(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let elem_count = (params.buffer_size / 8).max(1);
|
||||
let mut data: Vec<u64> = (0..elem_count).map(|_| rng.gen()).collect();
|
||||
data.sort_unstable();
|
||||
|
||||
let mut hits = 0usize;
|
||||
for _ in 0..params.iterations {
|
||||
let target: u64 = rng.gen();
|
||||
if data.binary_search(&target).is_ok() {
|
||||
hits += 1;
|
||||
}
|
||||
}
|
||||
|
||||
black_box(hits);
|
||||
}
|
||||
|
||||
fn reverse_buffer(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let size = params.buffer_size.min(1_048_576).max(1);
|
||||
let mut buf = vec![0u8; size];
|
||||
rng.fill_bytes(&mut buf);
|
||||
|
||||
for _ in 0..params.iterations {
|
||||
buf.reverse();
|
||||
}
|
||||
|
||||
black_box(&buf);
|
||||
}
|
||||
|
||||
fn interleave_buffers(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let half_size = (params.buffer_size / 2).max(1);
|
||||
for _ in 0..params.call_depth {
|
||||
let mut buf_a = vec![0u8; half_size];
|
||||
let mut buf_b = vec![0u8; half_size];
|
||||
rng.fill_bytes(&mut buf_a);
|
||||
rng.fill_bytes(&mut buf_b);
|
||||
|
||||
let mut interleaved = Vec::with_capacity(half_size * 2);
|
||||
for i in 0..half_size {
|
||||
interleaved.push(buf_a[i]);
|
||||
interleaved.push(buf_b[i]);
|
||||
}
|
||||
|
||||
black_box(&interleaved);
|
||||
}
|
||||
}
|
||||
|
||||
fn scatter_gather(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let size = params.buffer_size.min(1_048_576).max(1);
|
||||
let index_count = (size / 4).max(1);
|
||||
|
||||
let mut buffer = vec![0u8; size];
|
||||
rng.fill_bytes(&mut buffer);
|
||||
|
||||
for _ in 0..params.iterations.min(100) {
|
||||
// Generate random index list
|
||||
let indices: Vec<usize> = (0..index_count).map(|_| rng.gen_range(0..size)).collect();
|
||||
|
||||
// Gather: read at random indices into contiguous output
|
||||
let gathered: Vec<u8> = indices.iter().map(|&idx| buffer[idx]).collect();
|
||||
black_box(&gathered);
|
||||
|
||||
// Scatter: write from contiguous input to random indices
|
||||
let input: Vec<u8> = (0..index_count).map(|_| rng.gen()).collect();
|
||||
for (i, &idx) in indices.iter().enumerate() {
|
||||
buffer[idx] = input[i];
|
||||
}
|
||||
}
|
||||
|
||||
black_box(&buffer);
|
||||
}
|
||||
|
||||
+191
-4
@@ -2,6 +2,7 @@ use crate::categories::Categories;
|
||||
use crate::tasks::{TaskDescriptor, TaskParams};
|
||||
use rand::rngs::ThreadRng;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::RngCore;
|
||||
use std::hint::black_box;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{TcpStream, ToSocketAddrs, UdpSocket};
|
||||
@@ -42,6 +43,26 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::NETWORK,
|
||||
func: ntp_query,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "http_head_request",
|
||||
category: Categories::NETWORK,
|
||||
func: http_head_request,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "tcp_connect_probe",
|
||||
category: Categories::NETWORK,
|
||||
func: tcp_connect_probe,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "dns_varied_ports",
|
||||
category: Categories::NETWORK,
|
||||
func: dns_varied_ports,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "http_post_discard",
|
||||
category: Categories::NETWORK,
|
||||
func: http_post_discard,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -55,6 +76,22 @@ fn dns_lookups(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
"apple.com:80",
|
||||
"mozilla.org:80",
|
||||
"wikipedia.org:80",
|
||||
"reddit.com:80",
|
||||
"stackoverflow.com:80",
|
||||
"twitter.com:80",
|
||||
"linkedin.com:80",
|
||||
"facebook.com:80",
|
||||
"youtube.com:80",
|
||||
"netflix.com:80",
|
||||
"twitch.tv:80",
|
||||
"spotify.com:80",
|
||||
"dropbox.com:80",
|
||||
"zoom.us:80",
|
||||
"slack.com:80",
|
||||
"discord.com:80",
|
||||
"akamai.com:80",
|
||||
"fastly.com:80",
|
||||
"aws.amazon.com:80",
|
||||
];
|
||||
for _ in 0..params.iterations.min(50) {
|
||||
if let Some(host) = hosts.choose(rng) {
|
||||
@@ -72,8 +109,16 @@ fn http_get(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
("httpbin.org", 80, "/get"),
|
||||
("ip-api.com", 80, "/json"),
|
||||
("ifconfig.me", 80, "/ip"),
|
||||
("api.ipify.org", 80, "/"),
|
||||
("httpbin.org", 80, "/headers"),
|
||||
("httpbin.org", 80, "/user-agent"),
|
||||
("worldtimeapi.org", 80, "/api/ip"),
|
||||
("httpbin.org", 80, "/ip"),
|
||||
("icanhazip.com", 80, "/"),
|
||||
("checkip.amazonaws.com", 80, "/"),
|
||||
("api.myip.com", 80, "/"),
|
||||
];
|
||||
for _ in 0..params.call_depth.min(3) {
|
||||
for _ in 0..params.call_depth.min(5) {
|
||||
if let Some(&(host, port, path)) = targets.choose(rng) {
|
||||
let addr = format!("{}:{}", host, port);
|
||||
let stream = match TcpStream::connect(&*addr) {
|
||||
@@ -96,8 +141,21 @@ fn http_get(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
}
|
||||
}
|
||||
|
||||
fn ntp_query(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
for _ in 0..params.call_depth.min(3) {
|
||||
fn ntp_query(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let servers = [
|
||||
"pool.ntp.org:123",
|
||||
"time.google.com:123",
|
||||
"time.cloudflare.com:123",
|
||||
"time.windows.com:123",
|
||||
"time.apple.com:123",
|
||||
"time.nist.gov:123",
|
||||
"ntp.ubuntu.com:123",
|
||||
];
|
||||
for _ in 0..params.call_depth.min(5) {
|
||||
let server = match servers.choose(rng) {
|
||||
Some(s) => *s,
|
||||
None => continue,
|
||||
};
|
||||
let socket = match UdpSocket::bind("0.0.0.0:0") {
|
||||
Ok(s) => s,
|
||||
Err(_) => continue,
|
||||
@@ -105,7 +163,7 @@ fn ntp_query(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
set_socket_timeouts(&socket, 3000);
|
||||
let mut packet = [0u8; 48];
|
||||
packet[0] = 0x1B; // NTP v3, client mode
|
||||
if socket.send_to(&packet, "pool.ntp.org:123").is_err() {
|
||||
if socket.send_to(&packet, server).is_err() {
|
||||
continue;
|
||||
}
|
||||
let mut response = [0u8; 48];
|
||||
@@ -113,3 +171,132 @@ fn ntp_query(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
black_box(&response);
|
||||
}
|
||||
}
|
||||
|
||||
fn http_head_request(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let targets: &[(&str, u16, &str)] = &[
|
||||
("httpbin.org", 80, "/get"),
|
||||
("httpbin.org", 80, "/headers"),
|
||||
("httpbin.org", 80, "/ip"),
|
||||
("httpbin.org", 80, "/user-agent"),
|
||||
("ip-api.com", 80, "/json"),
|
||||
("ifconfig.me", 80, "/ip"),
|
||||
("worldtimeapi.org", 80, "/api/ip"),
|
||||
("checkip.amazonaws.com", 80, "/"),
|
||||
("icanhazip.com", 80, "/"),
|
||||
("api.ipify.org", 80, "/"),
|
||||
];
|
||||
for _ in 0..params.call_depth.min(5) {
|
||||
if let Some(&(host, port, path)) = targets.choose(rng) {
|
||||
let addr = format!("{}:{}", host, port);
|
||||
let stream = match TcpStream::connect(&*addr) {
|
||||
Ok(s) => s,
|
||||
Err(_) => continue,
|
||||
};
|
||||
set_socket_timeouts(&stream, 3000);
|
||||
let request = format!(
|
||||
"HEAD {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n",
|
||||
path, host
|
||||
);
|
||||
let mut stream = stream;
|
||||
if stream.write_all(request.as_bytes()).is_err() {
|
||||
continue;
|
||||
}
|
||||
let mut response = vec![0u8; 2048];
|
||||
let _ = stream.read(&mut response);
|
||||
black_box(&response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tcp_connect_probe(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let targets: &[(&str, u16)] = &[
|
||||
("google.com", 80),
|
||||
("google.com", 443),
|
||||
("cloudflare.com", 80),
|
||||
("cloudflare.com", 443),
|
||||
("github.com", 443),
|
||||
("microsoft.com", 80),
|
||||
("microsoft.com", 443),
|
||||
("amazon.com", 443),
|
||||
("1.1.1.1", 53),
|
||||
("8.8.8.8", 53),
|
||||
];
|
||||
for _ in 0..params.iterations.min(10) {
|
||||
if let Some(&(host, port)) = targets.choose(rng) {
|
||||
let addr = format!("{}:{}", host, port);
|
||||
// Just connect and immediately drop — TCP handshake only
|
||||
if let Ok(stream) = TcpStream::connect(&*addr) {
|
||||
set_socket_timeouts(&stream, 2000);
|
||||
black_box(&stream);
|
||||
// stream is dropped here, sending FIN
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dns_varied_ports(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let hosts = [
|
||||
"example.com:21",
|
||||
"example.com:22",
|
||||
"example.com:25",
|
||||
"example.com:53",
|
||||
"example.com:110",
|
||||
"example.com:143",
|
||||
"example.com:443",
|
||||
"example.com:993",
|
||||
"example.com:8080",
|
||||
"example.com:8443",
|
||||
"example.org:80",
|
||||
"example.org:443",
|
||||
"example.net:80",
|
||||
"example.net:25",
|
||||
"example.net:8080",
|
||||
];
|
||||
for _ in 0..params.iterations.min(40) {
|
||||
if let Some(host) = hosts.choose(rng) {
|
||||
let _ = host.to_socket_addrs().map(|addrs| {
|
||||
for addr in addrs {
|
||||
black_box(addr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn http_post_discard(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let targets: &[(&str, u16, &str, &str)] = &[
|
||||
("httpbin.org", 80, "/post", "POST"),
|
||||
("httpbin.org", 80, "/anything", "POST"),
|
||||
("httpbin.org", 80, "/put", "PUT"),
|
||||
("httpbin.org", 80, "/anything", "PUT"),
|
||||
("httpbin.org", 80, "/patch", "PATCH"),
|
||||
];
|
||||
|
||||
let body_size = params.buffer_size.min(1024);
|
||||
let mut body = vec![0u8; body_size];
|
||||
rng.fill_bytes(&mut body);
|
||||
// Encode body as hex string for a safe text payload
|
||||
let body_hex: String = body.iter().map(|b| format!("{:02x}", b)).collect();
|
||||
|
||||
for _ in 0..params.call_depth.min(5) {
|
||||
if let Some(&(host, port, path, method)) = targets.choose(rng) {
|
||||
let addr = format!("{}:{}", host, port);
|
||||
let stream = match TcpStream::connect(&*addr) {
|
||||
Ok(s) => s,
|
||||
Err(_) => continue,
|
||||
};
|
||||
set_socket_timeouts(&stream, 3000);
|
||||
let request = format!(
|
||||
"{} {} HTTP/1.1\r\nHost: {}\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
|
||||
method, path, host, body_hex.len(), body_hex
|
||||
);
|
||||
let mut stream = stream;
|
||||
if stream.write_all(request.as_bytes()).is_err() {
|
||||
continue;
|
||||
}
|
||||
let mut response = vec![0u8; 4096];
|
||||
let _ = stream.read(&mut response);
|
||||
black_box(&response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,36 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::REGISTRY,
|
||||
func: read_timezone_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_environment_vars",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_environment_vars,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_network_config",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_network_config,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_hardware_info",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_hardware_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_font_list",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_font_list,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_startup_programs",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_startup_programs,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "read_file_associations",
|
||||
category: Categories::REGISTRY,
|
||||
func: read_file_associations,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -81,6 +111,31 @@ unsafe fn read_string_value(hkey: HKEY, value_name: &[u16]) {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn enum_values(hkey: HKEY, max_values: usize) {
|
||||
let mut name_buf = [0u16; 256];
|
||||
let mut data_buf = [0u8; 512];
|
||||
for i in 0..max_values as u32 {
|
||||
let mut name_len = name_buf.len() as u32;
|
||||
let mut data_len = data_buf.len() as u32;
|
||||
let mut data_type = 0u32;
|
||||
let result = RegEnumValueW(
|
||||
hkey,
|
||||
i,
|
||||
windows::core::PWSTR(name_buf.as_mut_ptr()),
|
||||
&mut name_len,
|
||||
None,
|
||||
Some(&mut data_type),
|
||||
Some(data_buf.as_mut_ptr()),
|
||||
Some(&mut data_len),
|
||||
);
|
||||
if result.0 != 0 {
|
||||
break;
|
||||
}
|
||||
black_box(&name_buf[..name_len as usize]);
|
||||
black_box(&data_buf[..data_len as usize]);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_installed_software(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 60];
|
||||
@@ -190,6 +245,251 @@ fn read_timezone_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_environment_vars(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 70];
|
||||
let bytes = b"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
unsafe {
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
windows::core::PCWSTR(PATH.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let value_names: &[&[u16]] = &[
|
||||
&encode_wide_const::<10>(b"Path\0"),
|
||||
&encode_wide_const::<10>(b"TEMP\0"),
|
||||
&encode_wide_const::<10>(b"TMP\0"),
|
||||
&encode_wide_const::<10>(b"OS\0"),
|
||||
&encode_wide_const::<30>(b"PROCESSOR_ARCHITECTURE\0"),
|
||||
&encode_wide_const::<20>(b"NUMBER_OF_PROCESSORS\0"),
|
||||
&encode_wide_const::<20>(b"PATHEXT\0"),
|
||||
&encode_wide_const::<15>(b"ComSpec\0"),
|
||||
&encode_wide_const::<15>(b"windir\0"),
|
||||
];
|
||||
for _ in 0..params.call_depth {
|
||||
for name in value_names {
|
||||
read_string_value(hkey, name);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_network_config(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 60];
|
||||
let bytes = b"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
const INTERFACES_PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 75];
|
||||
let bytes = b"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
unsafe {
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
windows::core::PCWSTR(PATH.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 == 0 {
|
||||
let value_names: &[&[u16]] = &[
|
||||
&encode_wide_const::<15>(b"Hostname\0"),
|
||||
&encode_wide_const::<15>(b"Domain\0"),
|
||||
&encode_wide_const::<15>(b"SearchList\0"),
|
||||
&encode_wide_const::<20>(b"NV Hostname\0"),
|
||||
&encode_wide_const::<20>(b"ICSDomain\0"),
|
||||
];
|
||||
for _ in 0..params.call_depth {
|
||||
for name in value_names {
|
||||
read_string_value(hkey, name);
|
||||
}
|
||||
}
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
enum_subkeys(HKEY_LOCAL_MACHINE, INTERFACES_PATH, params.iterations);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_hardware_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 60];
|
||||
let bytes = b"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
unsafe {
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
windows::core::PCWSTR(PATH.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let value_names: &[&[u16]] = &[
|
||||
&encode_wide_const::<25>(b"ProcessorNameString\0"),
|
||||
&encode_wide_const::<10>(b"~MHz\0"),
|
||||
&encode_wide_const::<15>(b"Identifier\0"),
|
||||
&encode_wide_const::<20>(b"VendorIdentifier\0"),
|
||||
&encode_wide_const::<20>(b"FeatureSet\0"),
|
||||
&encode_wide_const::<15>(b"Update Status\0"),
|
||||
];
|
||||
for _ in 0..params.call_depth {
|
||||
for name in value_names {
|
||||
read_string_value(hkey, name);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_font_list(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH: &[u16] = &{
|
||||
let mut arr = [0u16; 60];
|
||||
let bytes = b"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
unsafe {
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
windows::core::PCWSTR(PATH.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
enum_values(hkey, params.iterations);
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_startup_programs(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
const PATH_HKLM: &[u16] = &{
|
||||
let mut arr = [0u16; 50];
|
||||
let bytes = b"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
const PATH_HKCU: &[u16] = &{
|
||||
let mut arr = [0u16; 50];
|
||||
let bytes = b"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\0";
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
arr[i] = bytes[i] as u16;
|
||||
i += 1;
|
||||
}
|
||||
arr
|
||||
};
|
||||
unsafe {
|
||||
// Read HKLM\...\Run
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
windows::core::PCWSTR(PATH_HKLM.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 == 0 {
|
||||
enum_values(hkey, params.iterations);
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
// Read HKCU\...\Run
|
||||
let mut hkey = HKEY::default();
|
||||
let result = RegOpenKeyExW(
|
||||
HKEY_CURRENT_USER,
|
||||
windows::core::PCWSTR(PATH_HKCU.as_ptr()),
|
||||
0,
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
);
|
||||
if result.0 == 0 {
|
||||
enum_values(hkey, params.iterations);
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_file_associations(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
let mut name_buf = [0u16; 256];
|
||||
for i in 0..params.iterations as u32 {
|
||||
let mut name_len = name_buf.len() as u32;
|
||||
let result = RegEnumKeyExW(
|
||||
HKEY_CLASSES_ROOT,
|
||||
i,
|
||||
windows::core::PWSTR(name_buf.as_mut_ptr()),
|
||||
&mut name_len,
|
||||
None,
|
||||
windows::core::PWSTR::null(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
if result.0 != 0 {
|
||||
break;
|
||||
}
|
||||
// Only process entries starting with '.'
|
||||
if name_len > 0 && name_buf[0] == b'.' as u16 {
|
||||
black_box(&name_buf[..name_len as usize]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fn encode_wide_const<const N: usize>(bytes: &[u8]) -> [u16; N] {
|
||||
let mut arr = [0u16; N];
|
||||
let mut i = 0;
|
||||
|
||||
+352
-2
@@ -1,11 +1,18 @@
|
||||
use crate::categories::Categories;
|
||||
use crate::tasks::{TaskDescriptor, TaskParams};
|
||||
use rand::rngs::ThreadRng;
|
||||
use rand::Rng;
|
||||
use std::hint::black_box;
|
||||
use windows::core::w;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::Win32::Foundation::*;
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::*;
|
||||
use windows::Win32::System::SystemInformation::*;
|
||||
use windows::Win32::Storage::FileSystem::*;
|
||||
use windows::Win32::System::DataExchange::*;
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::*;
|
||||
use windows::Win32::System::LibraryLoader::*;
|
||||
use windows::Win32::System::Memory::*;
|
||||
use windows::Win32::System::SystemInformation::*;
|
||||
use windows::Win32::System::Threading::*;
|
||||
use windows::Win32::UI::WindowsAndMessaging::*;
|
||||
|
||||
pub fn register() -> Vec<TaskDescriptor> {
|
||||
@@ -30,9 +37,71 @@ pub fn register() -> Vec<TaskDescriptor> {
|
||||
category: Categories::WINAPI,
|
||||
func: read_clipboard,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_system_metrics",
|
||||
category: Categories::WINAPI,
|
||||
func: get_system_metrics,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_foreground_window_info",
|
||||
category: Categories::WINAPI,
|
||||
func: get_foreground_window_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_cursor_position",
|
||||
category: Categories::WINAPI,
|
||||
func: get_cursor_position,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_desktop_window_info",
|
||||
category: Categories::WINAPI,
|
||||
func: get_desktop_window_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_logical_drives_info",
|
||||
category: Categories::WINAPI,
|
||||
func: get_logical_drives_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_volume_info",
|
||||
category: Categories::WINAPI,
|
||||
func: get_volume_info,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_disk_free_space",
|
||||
category: Categories::WINAPI,
|
||||
func: get_disk_free_space,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "find_files_pattern",
|
||||
category: Categories::WINAPI,
|
||||
func: find_files_pattern,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_module_handles",
|
||||
category: Categories::WINAPI,
|
||||
func: get_module_handles,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "virtual_query_memory",
|
||||
category: Categories::WINAPI,
|
||||
func: virtual_query_memory,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_system_directories",
|
||||
category: Categories::WINAPI,
|
||||
func: get_system_directories,
|
||||
},
|
||||
TaskDescriptor {
|
||||
name: "get_process_thread_ids",
|
||||
category: Categories::WINAPI,
|
||||
func: get_process_thread_ids,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
// ── Existing tasks ──────────────────────────────────────────────────────────
|
||||
|
||||
unsafe extern "system" fn enum_window_callback(hwnd: HWND, lparam: LPARAM) -> BOOL {
|
||||
let windows = &mut *(lparam.0 as *mut Vec<HWND>);
|
||||
windows.push(hwnd);
|
||||
@@ -107,3 +176,284 @@ fn read_clipboard(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── New tasks ───────────────────────────────────────────────────────────────
|
||||
|
||||
fn get_system_metrics(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
const METRIC_INDICES: [i32; 10] = [
|
||||
0, // SM_CXSCREEN
|
||||
1, // SM_CYSCREEN
|
||||
2, // SM_CXVSCROLL
|
||||
3, // SM_CYHSCROLL
|
||||
4, // SM_CYCAPTION
|
||||
43, // SM_CMOUSEBUTTONS
|
||||
80, // SM_CMONITORS
|
||||
59, // SM_CXMAXTRACK
|
||||
60, // SM_CYMAXTRACK
|
||||
67, // SM_CLEANBOOT
|
||||
];
|
||||
|
||||
unsafe {
|
||||
for _ in 0..params.iterations {
|
||||
let idx = rng.gen_range(0..METRIC_INDICES.len());
|
||||
let metric = METRIC_INDICES[idx];
|
||||
let value = GetSystemMetrics(SYSTEM_METRICS_INDEX(metric));
|
||||
black_box(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_foreground_window_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.call_depth {
|
||||
let hwnd = GetForegroundWindow();
|
||||
if hwnd.0 == std::ptr::null_mut() {
|
||||
continue;
|
||||
}
|
||||
let mut text = [0u16; 256];
|
||||
GetWindowTextW(hwnd, &mut text);
|
||||
black_box(&text);
|
||||
|
||||
let mut rect = RECT::default();
|
||||
let _ = GetWindowRect(hwnd, &mut rect);
|
||||
black_box(rect.left);
|
||||
black_box(rect.top);
|
||||
black_box(rect.right);
|
||||
black_box(rect.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cursor_position(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.iterations {
|
||||
let mut point = POINT::default();
|
||||
let _ = GetCursorPos(&mut point);
|
||||
black_box(point.x);
|
||||
black_box(point.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_desktop_window_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.call_depth {
|
||||
let hwnd = GetDesktopWindow();
|
||||
|
||||
let mut rect = RECT::default();
|
||||
let _ = GetWindowRect(hwnd, &mut rect);
|
||||
black_box(rect.left);
|
||||
black_box(rect.top);
|
||||
black_box(rect.right);
|
||||
black_box(rect.bottom);
|
||||
|
||||
let mut client_rect = RECT::default();
|
||||
let _ = GetClientRect(hwnd, &mut client_rect);
|
||||
black_box(client_rect.right);
|
||||
black_box(client_rect.bottom);
|
||||
|
||||
let mut text = [0u16; 256];
|
||||
GetWindowTextW(hwnd, &mut text);
|
||||
black_box(&text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_logical_drives_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
let mask = GetLogicalDrives();
|
||||
if mask == 0 {
|
||||
return;
|
||||
}
|
||||
black_box(mask);
|
||||
|
||||
for bit in 0..26u32 {
|
||||
if mask & (1 << bit) == 0 {
|
||||
continue;
|
||||
}
|
||||
let letter = (b'A' + bit as u8) as u16;
|
||||
let path: [u16; 4] = [letter, ':' as u16, '\\' as u16, 0];
|
||||
let drive_type = GetDriveTypeW(PCWSTR(path.as_ptr()));
|
||||
black_box(drive_type);
|
||||
}
|
||||
|
||||
// Repeat the iteration to burn more cycles based on params
|
||||
for _ in 1..params.call_depth {
|
||||
let m = GetLogicalDrives();
|
||||
black_box(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_volume_info(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.call_depth {
|
||||
let mut volume_name = [0u16; 260];
|
||||
let mut serial_number: u32 = 0;
|
||||
let mut max_component_length: u32 = 0;
|
||||
let mut fs_flags: u32 = 0;
|
||||
let mut fs_name = [0u16; 260];
|
||||
|
||||
let ok = GetVolumeInformationW(
|
||||
w!("C:\\"),
|
||||
Some(&mut volume_name),
|
||||
Some(&mut serial_number),
|
||||
Some(&mut max_component_length),
|
||||
Some(&mut fs_flags),
|
||||
Some(&mut fs_name),
|
||||
);
|
||||
if ok.is_ok() {
|
||||
black_box(&volume_name);
|
||||
black_box(serial_number);
|
||||
black_box(max_component_length);
|
||||
black_box(fs_flags);
|
||||
black_box(&fs_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_disk_free_space(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.call_depth {
|
||||
let mut free_bytes_available: u64 = 0;
|
||||
let mut total_bytes: u64 = 0;
|
||||
let mut total_free_bytes: u64 = 0;
|
||||
|
||||
let ok = GetDiskFreeSpaceExW(
|
||||
w!("C:\\"),
|
||||
Some(&mut free_bytes_available as *mut u64),
|
||||
Some(&mut total_bytes as *mut u64),
|
||||
Some(&mut total_free_bytes as *mut u64),
|
||||
);
|
||||
if ok.is_ok() {
|
||||
black_box(free_bytes_available);
|
||||
black_box(total_bytes);
|
||||
black_box(total_free_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_files_pattern(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
let mut find_data = WIN32_FIND_DATAW::default();
|
||||
let handle = FindFirstFileW(w!("C:\\Windows\\System32\\*.dll"), &mut find_data);
|
||||
let handle = match handle {
|
||||
Ok(h) => h,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
black_box(&find_data.cFileName);
|
||||
black_box(find_data.nFileSizeHigh);
|
||||
black_box(find_data.nFileSizeLow);
|
||||
|
||||
for _ in 1..params.iterations {
|
||||
if FindNextFileW(handle, &mut find_data).is_err() {
|
||||
break;
|
||||
}
|
||||
black_box(&find_data.cFileName);
|
||||
black_box(find_data.nFileSizeHigh);
|
||||
black_box(find_data.nFileSizeLow);
|
||||
}
|
||||
|
||||
let _ = FindClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_module_handles(params: &TaskParams, rng: &mut ThreadRng) {
|
||||
let dll_names: &[PCWSTR] = &[
|
||||
w!("kernel32.dll"),
|
||||
w!("ntdll.dll"),
|
||||
w!("user32.dll"),
|
||||
w!("advapi32.dll"),
|
||||
w!("ws2_32.dll"),
|
||||
w!("shell32.dll"),
|
||||
w!("ole32.dll"),
|
||||
w!("crypt32.dll"),
|
||||
w!("bcrypt.dll"),
|
||||
w!("msvcrt.dll"),
|
||||
w!("gdi32.dll"),
|
||||
w!("combase.dll"),
|
||||
];
|
||||
|
||||
unsafe {
|
||||
for _ in 0..params.iterations {
|
||||
let idx = rng.gen_range(0..dll_names.len());
|
||||
let result = GetModuleHandleW(dll_names[idx]);
|
||||
match result {
|
||||
Ok(h) => {
|
||||
black_box(h);
|
||||
}
|
||||
Err(_) => {
|
||||
black_box(0u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn virtual_query_memory(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
let mut addr: usize = 0;
|
||||
let info_size = std::mem::size_of::<MEMORY_BASIC_INFORMATION>();
|
||||
|
||||
for _ in 0..params.iterations {
|
||||
let mut info = MEMORY_BASIC_INFORMATION::default();
|
||||
let result = VirtualQuery(
|
||||
Some(addr as *const std::ffi::c_void),
|
||||
&mut info,
|
||||
info_size,
|
||||
);
|
||||
if result == 0 {
|
||||
break;
|
||||
}
|
||||
black_box(info.BaseAddress);
|
||||
black_box(info.RegionSize);
|
||||
black_box(info.State);
|
||||
black_box(info.Type);
|
||||
|
||||
// Advance to the next region
|
||||
let region_size = if info.RegionSize == 0 {
|
||||
// Avoid infinite loop on zero-size region
|
||||
4096
|
||||
} else {
|
||||
info.RegionSize
|
||||
};
|
||||
addr = match addr.checked_add(region_size) {
|
||||
Some(a) => a,
|
||||
None => break,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_system_directories(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.call_depth {
|
||||
let mut sys_dir = [0u16; 260];
|
||||
let len = GetSystemDirectoryW(Some(&mut sys_dir));
|
||||
if len > 0 {
|
||||
black_box(&sys_dir[..len as usize]);
|
||||
}
|
||||
|
||||
let mut win_dir = [0u16; 260];
|
||||
let len = GetWindowsDirectoryW(Some(&mut win_dir));
|
||||
if len > 0 {
|
||||
black_box(&win_dir[..len as usize]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_process_thread_ids(params: &TaskParams, _rng: &mut ThreadRng) {
|
||||
unsafe {
|
||||
for _ in 0..params.iterations {
|
||||
let pid = GetCurrentProcessId();
|
||||
black_box(pid);
|
||||
|
||||
let tid = GetCurrentThreadId();
|
||||
black_box(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user