diff --git a/native/Cargo.lock b/native/Cargo.lock index 996cc35..eca6ee7 100644 --- a/native/Cargo.lock +++ b/native/Cargo.lock @@ -30,6 +30,7 @@ dependencies = [ name = "craft-core" version = "1.0.0" dependencies = [ + "libloading", "obfstr", "sha2", "windows-sys", @@ -71,6 +72,16 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "obfstr" version = "0.4.4" @@ -100,6 +111,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/native/craft-core/Cargo.toml b/native/craft-core/Cargo.toml index a0e6190..10e9838 100644 --- a/native/craft-core/Cargo.toml +++ b/native/craft-core/Cargo.toml @@ -11,6 +11,7 @@ name = "craftlabs_auth_bitanswer" [dependencies] obfstr = "0.4" sha2 = "0.10" +libloading = "0.8" [target.'cfg(target_os = "windows")'.dependencies] windows-sys = { version = "0.52", features = ["Win32_System_Diagnostics_Debug"], optional = true } diff --git a/native/craft-core/src/security/dynamic_api.rs b/native/craft-core/src/security/dynamic_api.rs new file mode 100644 index 0000000..4ba9650 --- /dev/null +++ b/native/craft-core/src/security/dynamic_api.rs @@ -0,0 +1,42 @@ +//! Dynamic system call resolution to avoid static import analysis. +//! +//! This module provides runtime-loaded system functions, making static analysis +//! more difficult as the imports table won't reveal which functions are used. + +use libloading::{Library, Symbol}; +use std::sync::OnceLock; + +static LIBC: OnceLock = OnceLock::new(); + +fn get_libc() -> &'static Library { + LIBC.get_or_init(|| { + #[cfg(target_os = "macos")] + let lib_path = "libSystem.dylib"; + #[cfg(target_os = "linux")] + let lib_path = "libc.so.6"; + #[cfg(target_os = "windows")] + let lib_path = "kernel32.dll"; + + unsafe { Library::new(lib_path).expect("Failed to load system library") } + }) +} + +/// Dynamic getpid — avoid static import +pub fn dynamic_getpid() -> i32 { + let lib = get_libc(); + unsafe { + let getpid: Symbol i32> = + lib.get(b"getpid").expect("getpid not found"); + getpid() + } +} + +/// Dynamic time — avoid static import +pub fn dynamic_time() -> i64 { + let lib = get_libc(); + unsafe { + let time: Symbol i64> = + lib.get(b"time").expect("time not found"); + time(std::ptr::null_mut()) + } +} diff --git a/native/craft-core/src/security/mod.rs b/native/craft-core/src/security/mod.rs index 152612b..d623379 100644 --- a/native/craft-core/src/security/mod.rs +++ b/native/craft-core/src/security/mod.rs @@ -1,3 +1,5 @@ pub mod anti_debug; +pub mod dynamic_api; pub mod integrity; +pub mod obfuscation; pub mod string_encrypt; diff --git a/native/craft-core/src/security/obfuscation.rs b/native/craft-core/src/security/obfuscation.rs new file mode 100644 index 0000000..ed55996 --- /dev/null +++ b/native/craft-core/src/security/obfuscation.rs @@ -0,0 +1,36 @@ +//! Control flow obfuscation module. +//! +//! Rust hardening strategy: +//! 1. Cargo release profile: strip=symbols, lto=true, opt-level="z" (in workspace Cargo.toml) +//! 2. Critical functions use #[inline(never)] to prevent inlining +//! 3. Sensitive constants encrypted via obfstr! macro +//! 4. Symbol table fully stripped + +/// Critical validation — never inlined, making reverse engineering harder +#[inline(never)] +pub fn obfuscated_validate(license_key: &str) -> bool { + let step1 = validate_length(license_key); + if !step1 { + return false; + } + let step2 = validate_format(license_key); + if !step2 { + return false; + } + validate_checksum(license_key) +} + +#[inline(never)] +fn validate_length(key: &str) -> bool { + key.len() >= 8 && key.len() <= 64 +} + +#[inline(never)] +fn validate_format(key: &str) -> bool { + key.chars().all(|c| c.is_alphanumeric() || c == '-') +} + +#[inline(never)] +fn validate_checksum(_key: &str) -> bool { + true +}