From 2b5074153b08123952be088e7bf40b4173c8158e Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Mon, 10 Nov 2025 22:18:21 -0700 Subject: [PATCH] Add base62 encoding --- unshell-breakout-module/Cargo.lock | 11 +- unshell-breakout-module/build.sh | 4 +- unshell-cli/Cargo.lock | 87 ++++++-- unshell-cli/Cargo.toml | 4 +- unshell-cli/src/main.rs | 83 +++++++- unshell-crypt/Cargo.lock | 256 ++++++++++++++++++++++++ unshell-crypt/Cargo.toml | 14 ++ unshell-crypt/src/aes.rs | 71 +++++++ unshell-crypt/src/base62.rs | 225 +++++++++++++++++++++ unshell-crypt/src/lib.rs | 35 ++++ unshell-lib/Cargo.lock | 83 ++++++-- unshell-lib/Cargo.toml | 13 +- unshell-lib/src/crypt/mod.rs | 1 + unshell-lib/src/lib.rs | 27 ++- unshell-lib/src/logger/pretty_logger.rs | 4 +- unshell-obfuscate/Cargo.lock | 56 +++++- unshell-obfuscate/Cargo.toml | 10 +- unshell-obfuscate/src/encrypt.rs | 59 ------ unshell-obfuscate/src/lib.rs | 28 ++- unshell-payload/Cargo.lock | 41 ++-- unshell-payload/Cargo.toml | 3 +- 21 files changed, 981 insertions(+), 134 deletions(-) create mode 100644 unshell-crypt/Cargo.lock create mode 100644 unshell-crypt/Cargo.toml create mode 100644 unshell-crypt/src/aes.rs create mode 100644 unshell-crypt/src/base62.rs create mode 100644 unshell-crypt/src/lib.rs create mode 100644 unshell-lib/src/crypt/mod.rs delete mode 100644 unshell-obfuscate/src/encrypt.rs diff --git a/unshell-breakout-module/Cargo.lock b/unshell-breakout-module/Cargo.lock index a8887e6..24a106f 100644 --- a/unshell-breakout-module/Cargo.lock +++ b/unshell-breakout-module/Cargo.lock @@ -403,17 +403,24 @@ dependencies = [ [[package]] name = "unshell-lib" -version = "0.1.0" +version = "0.0.0" dependencies = [ + "aes", "bincode", + "block-padding 0.4.1", + "cbc", "chrono", + "getrandom", + "hex", + "hex-literal", "libloading", + "sha2", "unshell-obfuscate", ] [[package]] name = "unshell-obfuscate" -version = "0.1.0" +version = "0.0.0" dependencies = [ "aes", "block-padding 0.4.1", diff --git a/unshell-breakout-module/build.sh b/unshell-breakout-module/build.sh index 77f28ba..c4eb922 100755 --- a/unshell-breakout-module/build.sh +++ b/unshell-breakout-module/build.sh @@ -1,4 +1,6 @@ -RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none" cargo +nightly build \ +OBFUSCATION_KEY=abc123abc \ +RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none" \ +cargo +nightly build \ -Z build-std=std,panic_abort \ -Z build-std-features="optimize_for_size" \ --profile release $@ diff --git a/unshell-cli/Cargo.lock b/unshell-cli/Cargo.lock index f5062ff..9819a77 100644 --- a/unshell-cli/Cargo.lock +++ b/unshell-cli/Cargo.lock @@ -13,6 +13,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -279,6 +288,12 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + [[package]] name = "num-traits" version = "0.2.19" @@ -318,6 +333,35 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rustversion" version = "1.0.22" @@ -372,9 +416,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.109" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -397,21 +441,13 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" name = "unshell-cli" version = "0.1.0" dependencies = [ + "unshell-crypt", "unshell-lib", -] - -[[package]] -name = "unshell-lib" -version = "0.1.0" -dependencies = [ - "bincode", - "chrono", - "libloading", "unshell-obfuscate", ] [[package]] -name = "unshell-obfuscate" +name = "unshell-crypt" version = "0.1.0" dependencies = [ "aes", @@ -420,10 +456,35 @@ dependencies = [ "getrandom", "hex", "hex-literal", + "regex", + "sha2", +] + +[[package]] +name = "unshell-lib" +version = "0.0.0" +dependencies = [ + "aes", + "bincode", + "block-padding 0.4.1", + "cbc", + "chrono", + "getrandom", + "hex", + "hex-literal", + "libloading", + "sha2", + "unshell-obfuscate", +] + +[[package]] +name = "unshell-obfuscate" +version = "0.0.0" +dependencies = [ "proc-macro2", "quote", - "sha2", "syn", + "unshell-crypt", ] [[package]] diff --git a/unshell-cli/Cargo.toml b/unshell-cli/Cargo.toml index 14b48e1..68c97ea 100644 --- a/unshell-cli/Cargo.toml +++ b/unshell-cli/Cargo.toml @@ -4,4 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -unshell-lib = {path = "../unshell-lib"}#, default-features = false, features = ["server-component"]} +unshell-lib = {path = "../unshell-lib"} +unshell-obfuscate = {path = "../unshell-obfuscate"} +unshell-crypt = {path = "../unshell-crypt"} diff --git a/unshell-cli/src/main.rs b/unshell-cli/src/main.rs index 41b710f..5c47fda 100644 --- a/unshell-cli/src/main.rs +++ b/unshell-cli/src/main.rs @@ -1,14 +1,82 @@ use std::io::{Write, stdin, stdout}; +use unshell_crypt::{ + aes::{decrypt_aes, decrypt_aes_lines, encrypt_aes, encrypt_aes_lines}, + base62::Base62, + fill, hash, +}; use unshell_lib::Announcement; -// use unshell_test_module::ListenerRuntime; +use unshell_obfuscate::format_obs; -// fn print_continue_prompt(str: &str) { -// printl -// } +fn main() -> Result<(), Box> { + // let aaa = unshell_lib::crypt::aes::decrypt_aes( + // "611dcb046fcb11c3a0cf6d27ac7c8452e0120c2675d067a0dd857d9cd3d9df21140f1e2a715083a48180907eb90b87a6", //_1c82a871dda0f4372eb8e0dbba34c8de", + // "abc123abc", + // )?; + + let key = "abc123abc"; + + println!( + "{}", + encrypt_aes_lines("Verylongstringthat1", &key, unshell_crypt::STATIC_IV) + ); + println!( + "{}", + encrypt_aes_lines("Verylongstringthat12", &key, unshell_crypt::STATIC_IV) + ); + println!( + "{}", + encrypt_aes_lines("Verylongstringthat123", &key, unshell_crypt::STATIC_IV) + ); + println!( + "{}", + encrypt_aes_lines("Verylongstringthat1234", &key, unshell_crypt::STATIC_IV) + ); + println!( + "{}", + encrypt_aes_lines("Verylongstringthat12345", &key, unshell_crypt::STATIC_IV) + ); + + // let e = Base62::encode_full(data, &key); + // let e = "_Nl8MlCFOyM4egPSXfo0wE4tfA0vOfBSZCx1TpKzjhI2qfahTrwh4JE1pJpcBttQqz_"; + + // let mut buf = [0u8; 256]; + // _L1IuRLMW8tZN68RerKcbltQl675Yeq930NbcxsEfYYf_ + // _L1IuRLMW8tZN68RerKcblyGtqOCLeLuBu3ormgklt3J_ + // _L1IuRLMW8tZN68RerKcblKi37HPcZRonvwFUS5SZc0C_ + // _L1IuRLMW8tZN68RerKcblya0Yw6TrFQxruqpemtv3K2_ + + // fill(&mut buf); + + // for byte in buf.iter() { + // print!("{}, ", byte); + // } + + // src/main.rs:13 + // _SqF7lDRCyatsM4hnUTNAOq_ + // + // _Nl8MlCFOyM4egPSXfo0wE4tfA0vOfBSZCx1TpKzjhI2qfahTrwh4JE1pJpcBttQqz_ + // unshell-lib-0.0.0/src/module/manager.rs:52 + + // println!("Key: {}", String::from_utf8_lossy(&key)); + + // let encoded = Base62::decode_full(&e, &key).unwrap(); + // let plaintext = decrypt_aes_lines(&data, &key, unshell_crypt::STATIC_IV); + + // let base = Base62::new(&hash("TEST_KEY".as_bytes()), 0); + + // let encoded = base.encode("123 1234 12342 1235e2".as_bytes()); + + // println!("Base62: {}", plaintext); + + // let base = Base62::new(&hash("TEST_KEY".as_bytes()), 0); + + // let decoded = base.decode(&encoded).unwrap(); + // println!("Decoded: {}", String::from_utf8(decoded).unwrap()); + + // Ok(()) -fn main() { let mut serverruntime = unshell_lib::server::ListenerRuntime::new(); loop { @@ -16,6 +84,9 @@ fn main() { stdout().flush().expect("Failed to flush stdout"); let mut input = String::new(); stdin().read_line(&mut input).expect("Failed to read line"); + + // println!("{}", input); + let args = input.trim().split(" ").collect::>(); match args[0] { @@ -35,6 +106,6 @@ fn main() { } } - // println!("{:?}", args); + println!("{:?}", args); } } diff --git a/unshell-crypt/Cargo.lock b/unshell-crypt/Cargo.lock new file mode 100644 index 0000000..ea3e2d3 --- /dev/null +++ b/unshell-crypt/Cargo.lock @@ -0,0 +1,256 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d28ed5f5f65056148fd25e1a596b5b6d9e772270abf9a9085d7cbfbf26c563" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" + +[[package]] +name = "hybrid-array" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +dependencies = [ + "typenum", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding 0.3.3", + "generic-array", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unshell-crypt" +version = "0.1.0" +dependencies = [ + "aes", + "block-padding 0.4.1", + "cbc", + "getrandom", + "hex", + "hex-literal", + "regex", + "sha2", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" diff --git a/unshell-crypt/Cargo.toml b/unshell-crypt/Cargo.toml new file mode 100644 index 0000000..0f0d989 --- /dev/null +++ b/unshell-crypt/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "unshell-crypt" +version = "0.1.0" +edition = "2024" + +[dependencies] +aes = "0.8.4" +block-padding = "0.4.1" +cbc = "0.1.2" +getrandom = "0.3.4" +hex = "0.4.3" +hex-literal = "1.1.0" +regex = "1.12.2" +sha2 = "0.10.9" diff --git a/unshell-crypt/src/aes.rs b/unshell-crypt/src/aes.rs new file mode 100644 index 0000000..0a1002c --- /dev/null +++ b/unshell-crypt/src/aes.rs @@ -0,0 +1,71 @@ +use crate::{base62::Base62, hash}; +use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit}; +use cbc::cipher::block_padding::Pkcs7; +use regex::Regex; + +fn pkcs7_padded_length(input_len: usize) -> usize { + let block_size = 16; + ((input_len / block_size) + 1) * block_size +} + +pub fn encrypt_aes(plaintext: &str, key_str: &str, iv: [u8; 16]) -> String { + // Hash the env key to get a 32-byte (256-bit) AES key + let key = hash(key_str.as_bytes()); + + let plaintext = plaintext.as_bytes(); + + let buf_len = pkcs7_padded_length(plaintext.len()); + + let mut buf = vec![0u8; buf_len]; + let pt_len = plaintext.len(); + buf[..pt_len].copy_from_slice(&plaintext); + let ct = cbc::Encryptor::::new(&key.into(), &iv.into()) + .encrypt_padded_mut::(&mut buf, pt_len) + .unwrap(); + + Base62::encode_full(ct, &key) +} + +pub fn encrypt_aes_lines(plaintext: &str, key_str: &str, iv: [u8; 16]) -> String { + format!("_{}_", encrypt_aes(plaintext, key_str, iv)) +} + +pub fn decrypt_aes(input: &str, key_str: &str, iv: [u8; 16]) -> String { + // Hash the env key to get a 32-byte (256-bit) AES key + let key = hash(key_str.as_bytes()); + + let cipher_bytes = Base62::decode_full(input, &key).unwrap(); + + // Create buffer for result + let buf_len = cipher_bytes.len(); + let mut buf: Vec = vec![0; buf_len]; + buf[..cipher_bytes.len()].copy_from_slice(&cipher_bytes); + + if let Ok(pt) = cbc::Decryptor::::new(&key.into(), &iv.into()) + .decrypt_padded_mut::(&mut buf) + { + String::from_utf8_lossy(pt).to_string() + } else { + "".to_string() + } +} + +pub fn decrypt_aes_lines(input: &str, key_str: &str, iv: [u8; 16]) -> String { + let mut decrypted_result = input.to_string(); + let mut total_offset = 0; + + for aes_block in Regex::new(r"_([0-9a-zA-Z]*?)_").unwrap().find_iter(&input) { + let range = aes_block.range(); + let aes_block = aes_block.as_str()[1..(aes_block.len() - 1)].to_string(); + let decrypted_block = decrypt_aes(&aes_block, key_str, iv); + + let range = (range.start + total_offset as usize)..(range.end + total_offset as usize); + + // Offset range by the difference between the decrypted block length and the original range length + total_offset += decrypted_block.len().clone() - (range.end - range.start); + + decrypted_result.replace_range(range, &decrypted_block); + } + + decrypted_result +} diff --git a/unshell-crypt/src/base62.rs b/unshell-crypt/src/base62.rs new file mode 100644 index 0000000..fdacaf0 --- /dev/null +++ b/unshell-crypt/src/base62.rs @@ -0,0 +1,225 @@ +use crate::{STATIC_BYTE_MAP, hash}; + +// Randomly mapped Base62 characters +pub struct Base62 { + charset: [char; 62], +} + +pub const BASE62_CHARS: [char; 62] = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', +]; + +// Const for ratio +const ENCODING_RATIO: f64 = 8.0 / 5.954196310386875; // 8.0 / log2(62.0) + +impl Base62 { + pub fn new(key: &[u8], nonce: usize) -> Self { + // Hash key again, for the chance that this random function can be used to derive the key + let key = hash(key); + + let mut charset: [char; 62] = [0 as char; 62]; + + // Create a vector of indices from 0 to 61 + let mut current_indicies = (0..62).map(|i| i as usize).collect::>(); + + // Loop through each byte in the key until all chars are filled + for i in 0..62 as usize { + let rand = STATIC_BYTE_MAP[(key[i as usize % key.len()] as usize + nonce) % 255]; + + let index_index = rand as usize % current_indicies.len(); + let put_index = current_indicies.remove(index_index); + + charset[put_index] = BASE62_CHARS[i]; + } + + return Self { charset }; + } + + // Convert character to base-62 value using custom charset + fn char_to_value(&self, ch: char) -> Result { + self.charset + .iter() + .position(|&c| c == ch) + .map(|pos| pos as u8) + .ok_or_else(|| format!("Invalid character for this charset: '{}'", ch)) + } + + /// Encodes a byte slice into a base-62 string using a custom character set + /// Supports arbitrary length input by using big integer arithmetic + pub fn encode(&self, data: &[u8]) -> String { + if data.is_empty() { + return String::new(); + } + + // Count leading zeros + let leading_zeros = data.iter().take_while(|&&b| b == 0).count(); + + // Skip leading zeros for conversion + let data = &data[leading_zeros..]; + + if data.is_empty() { + return self.charset[0].to_string().repeat(leading_zeros); + } + + let mut result = Vec::new(); + let mut num = data.to_vec(); + + // Convert to base-62 using division + while !is_zero(&num) { + let remainder = div_mod_62(&mut num); + result.push(self.charset[remainder]); + } + + // Add leading zeros + for _ in 0..leading_zeros { + result.push(self.charset[0]); + } + + // Reverse since we built it backwards + result.reverse(); + result.into_iter().collect() + } + + /// Decodes a base-62 string back into bytes using a custom character set + /// Supports arbitrary length output + pub fn decode(&self, encoded: &str) -> Result, String> { + if encoded.is_empty() { + return Ok(Vec::new()); + } + + // Count leading zeros (first character in charset) + let zero_char = self.charset[0]; + let leading_zeros = encoded.chars().take_while(|&c| c == zero_char).count(); + + // Skip leading zeros for conversion + let encoded = &encoded[leading_zeros..]; + + if encoded.is_empty() { + return Ok(vec![0; leading_zeros]); + } + + // Convert base-62 string to bytes using multiplication + let mut num = vec![0u8]; + + for ch in encoded.chars() { + let value = self.char_to_value(ch)?; + mul_add(&mut num, 62, value); + } + + // Add leading zero bytes + let mut result = vec![0u8; leading_zeros]; + result.append(&mut num); + + Ok(result) + } + + pub fn encode_full(data: &[u8], key: &[u8]) -> String { + // Predict the length of the encoded data + let length = predict_base62_len(data); + + let base = Base62::new(&key, length % 255); + let encoded = base.encode(data); + + if encoded.len() != length { + let len = encoded.len(); + let base = Base62::new(&key, len % 255); + let encoded = base.encode(data); + + println!("Fallback"); + + assert_eq!(encoded.len(), len); + + encoded + } else { + encoded + } + } + pub fn decode_full(data: &str, key: &[u8]) -> Result, String> { + let base = Base62::new(&key, data.len() % 255); + base.decode(data) + } + + // pub fn encode_full +} + +// Helper: Check if big integer (as bytes) is zero +fn is_zero(num: &[u8]) -> bool { + num.iter().all(|&b| b == 0) +} + +// Helper: Divide big integer by 62 and return remainder +// Modifies num in place to be the quotient +fn div_mod_62(num: &mut Vec) -> usize { + let mut remainder = 0u16; + let mut all_zero = true; + + for byte in num.iter_mut() { + let current = (remainder << 8) | (*byte as u16); + *byte = (current / 62) as u8; + remainder = current % 62; + if *byte != 0 { + all_zero = false; + } + } + + // Remove leading zeros from quotient + if all_zero { + num.clear(); + num.push(0); + } else { + let first_nonzero = num.iter().position(|&b| b != 0).unwrap_or(0); + if first_nonzero > 0 { + num.drain(0..first_nonzero); + } + } + + remainder as usize +} + +// Helper: Multiply big integer by 62 and add a value +// Modifies num in place +fn mul_add(num: &mut Vec, multiplier: u16, add: u8) { + let mut carry = add as u16; + + for byte in num.iter_mut().rev() { + let product = (*byte as u16) * multiplier + carry; + *byte = (product & 0xFF) as u8; + carry = product >> 8; + } + + // Add remaining carry bytes + while carry > 0 { + num.insert(0, (carry & 0xFF) as u8); + carry >>= 8; + } +} + +/// Predicts the byte length of the decoded output given a base-62 encoded string +/// This calculates the length without performing the full decoding +pub fn predict_base62_len(input_bytes: &[u8]) -> usize { + if input_bytes.is_empty() { + return 0; + } + + // 1. Count leading zero bytes. + let num_leading_zeros = input_bytes.iter().take_while(|&&b| b == 0).count(); + + // 2. Calculate length of the rest of the bytes. + let num_rest_bytes = input_bytes.len() - num_leading_zeros; + + if num_rest_bytes == 0 { + // If all bytes were zeros, the length is just the number of zeros. + num_leading_zeros + } else { + // 3. Calculate the mathematical upper bound for the non-zero part. + // This is ceil(num_rest_bytes * 8_bits / log2(62)) + // which is ceil(num_rest_bytes * log_62(256)) + let rest_len = (num_rest_bytes as f64 * ENCODING_RATIO).ceil(); + + // 4. Total length is zeros + rest_len + num_leading_zeros + rest_len as usize + } +} diff --git a/unshell-crypt/src/lib.rs b/unshell-crypt/src/lib.rs new file mode 100644 index 0000000..0031b6b --- /dev/null +++ b/unshell-crypt/src/lib.rs @@ -0,0 +1,35 @@ +pub mod aes; +pub mod base62; + +pub const ENV_KEY_NAME: &str = "OBFUSCATION_KEY"; +pub const BACKUP_ENV_KEY: &str = "OBFUSCATION_KEY_DO_NOT_USE"; + +pub const STATIC_IV: [u8; 16] = [ + 0x6d, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x69, 0x76, 0x5f, 0x30, 0x31, 0x32, +]; + +pub const STATIC_BYTE_MAP: [u8; 256] = [ + 58, 177, 23, 16, 227, 134, 93, 239, 201, 3, 74, 162, 228, 195, 126, 157, 136, 57, 98, 86, 175, + 111, 71, 39, 205, 49, 139, 116, 143, 182, 250, 222, 59, 36, 18, 79, 37, 84, 190, 42, 7, 142, + 167, 168, 105, 54, 218, 230, 203, 83, 52, 129, 144, 184, 41, 73, 29, 72, 128, 75, 160, 149, 20, + 32, 207, 155, 131, 125, 199, 220, 56, 76, 94, 78, 247, 214, 165, 33, 19, 241, 69, 206, 172, + 113, 225, 90, 150, 242, 107, 232, 8, 77, 100, 187, 240, 104, 31, 180, 53, 253, 63, 192, 252, + 30, 140, 158, 1, 210, 24, 44, 243, 145, 197, 80, 202, 65, 196, 45, 51, 11, 55, 236, 186, 22, + 224, 118, 200, 204, 153, 114, 117, 229, 47, 159, 96, 219, 234, 183, 13, 70, 81, 137, 46, 211, + 254, 255, 127, 138, 246, 87, 61, 89, 189, 66, 208, 221, 85, 251, 188, 43, 248, 102, 146, 170, + 132, 213, 178, 103, 62, 92, 27, 6, 38, 122, 185, 181, 215, 12, 179, 4, 169, 226, 209, 0, 112, + 154, 120, 17, 101, 64, 194, 193, 212, 198, 121, 135, 99, 115, 244, 14, 133, 26, 156, 10, 5, + 238, 163, 164, 25, 88, 95, 152, 40, 108, 216, 21, 109, 2, 123, 233, 237, 235, 119, 60, 82, 191, + 68, 151, 161, 124, 48, 35, 249, 171, 50, 141, 166, 34, 15, 176, 97, 148, 147, 91, 9, 28, 223, + 67, 130, 217, 231, 106, 245, 110, 173, 174, +]; + +use sha2::{Digest, Sha256}; + +pub fn hash(input: &[u8]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(input); + hasher.finalize().into() +} + +pub use getrandom::fill; diff --git a/unshell-lib/Cargo.lock b/unshell-lib/Cargo.lock index 64a0002..320f3cd 100644 --- a/unshell-lib/Cargo.lock +++ b/unshell-lib/Cargo.lock @@ -13,6 +13,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -279,6 +288,12 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + [[package]] name = "num-traits" version = "0.2.19" @@ -318,6 +333,35 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rustversion" version = "1.0.22" @@ -394,17 +438,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unshell-lib" -version = "0.1.0" -dependencies = [ - "bincode", - "chrono", - "libloading", - "unshell-obfuscate", -] - -[[package]] -name = "unshell-obfuscate" +name = "unshell-crypt" version = "0.1.0" dependencies = [ "aes", @@ -413,10 +447,35 @@ dependencies = [ "getrandom", "hex", "hex-literal", + "regex", + "sha2", +] + +[[package]] +name = "unshell-lib" +version = "0.0.0" +dependencies = [ + "aes", + "bincode", + "block-padding 0.4.1", + "cbc", + "chrono", + "getrandom", + "hex", + "hex-literal", + "libloading", + "sha2", + "unshell-obfuscate", +] + +[[package]] +name = "unshell-obfuscate" +version = "0.0.0" +dependencies = [ "proc-macro2", "quote", - "sha2", "syn", + "unshell-crypt", ] [[package]] diff --git a/unshell-lib/Cargo.toml b/unshell-lib/Cargo.toml index adcfb5f..1369402 100644 --- a/unshell-lib/Cargo.toml +++ b/unshell-lib/Cargo.toml @@ -1,10 +1,21 @@ [package] name = "unshell-lib" -version = "0.1.0" edition = "2024" [dependencies] +# Base dependencies libloading = {version = "0.8.9"} bincode = "2.0.1" unshell-obfuscate = {path = "../unshell-obfuscate"} chrono = "0.4.42" + +# Crypt dependencies +aes = "0.8.4" +block-padding = "0.4.1" +cbc = "0.1.2" +getrandom = "0.3.4" +hex = "0.4.3" +hex-literal = "1.1.0" +sha2 = "0.10.9" + +# diff --git a/unshell-lib/src/crypt/mod.rs b/unshell-lib/src/crypt/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/unshell-lib/src/crypt/mod.rs @@ -0,0 +1 @@ + diff --git a/unshell-lib/src/lib.rs b/unshell-lib/src/lib.rs index e033ec6..cb7dab1 100644 --- a/unshell-lib/src/lib.rs +++ b/unshell-lib/src/lib.rs @@ -1,12 +1,16 @@ #![no_main] pub mod client; +pub mod crypt; pub mod logger; pub mod module; pub mod server; mod announcement; -use std::sync::{Arc, Mutex}; +use std::{ + fmt, + sync::{Arc, Mutex}, +}; pub use announcement::Announcement; @@ -18,9 +22,30 @@ pub enum ModuleError { LibLoadingError(libloading::Error), // LogError(log::SetLoggerError), LinkError(String), + CryptError(String), Error(String), } +impl std::error::Error for ModuleError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + + fn description(&self) -> &str { + "description() is deprecated; use Display" + } + + fn cause(&self) -> Option<&dyn std::error::Error> { + Some(self) + } +} + +impl fmt::Display for ModuleError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(format!("{:?}", self).as_str()) + } +} + /// Trait for defining modules that have a runtime. pub trait ModuleRuntime: Send { /// Returns true if the module is running. diff --git a/unshell-lib/src/logger/pretty_logger.rs b/unshell-lib/src/logger/pretty_logger.rs index 05cf7e6..f543201 100644 --- a/unshell-lib/src/logger/pretty_logger.rs +++ b/unshell-lib/src/logger/pretty_logger.rs @@ -18,10 +18,10 @@ static GREY: &str = "\x1b[90m"; impl Logger for PrettyLogger { fn log(&self, message: Record) { let log_level = match message.log_level { - LogLevel::Debug => format!("{DEBUG_COLOR}DEBUG"), + LogLevel::Debug => format!("{DEBUG_COLOR}DBUG"), LogLevel::Info => format!("{INFO_COLOR}INFO"), LogLevel::Warn => format!("{WARN_COLOR}WARN"), - LogLevel::Error => format!("{ERROR_COLOR}ERROR"), + LogLevel::Error => format!("{ERROR_COLOR}ERR!"), }; let date: DateTime = message.time.into(); diff --git a/unshell-obfuscate/Cargo.lock b/unshell-obfuscate/Cargo.lock index 177d78b..15c3124 100644 --- a/unshell-obfuscate/Cargo.lock +++ b/unshell-obfuscate/Cargo.lock @@ -13,6 +13,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -153,6 +162,12 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + [[package]] name = "proc-macro2" version = "1.0.103" @@ -177,6 +192,35 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "sha2" version = "0.10.9" @@ -212,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unshell-obfuscate" +name = "unshell-crypt" version = "0.1.0" dependencies = [ "aes", @@ -221,10 +265,18 @@ dependencies = [ "getrandom", "hex", "hex-literal", + "regex", + "sha2", +] + +[[package]] +name = "unshell-obfuscate" +version = "0.0.0" +dependencies = [ "proc-macro2", "quote", - "sha2", "syn", + "unshell-crypt", ] [[package]] diff --git a/unshell-obfuscate/Cargo.toml b/unshell-obfuscate/Cargo.toml index 0d1a516..687f532 100644 --- a/unshell-obfuscate/Cargo.toml +++ b/unshell-obfuscate/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "unshell-obfuscate" -version = "0.1.0" edition = "2024" [lib] @@ -11,13 +10,8 @@ proc-macro = true obfuscate = [] [dependencies] -aes = "0.8.4" -block-padding = "0.4.1" -cbc = "0.1.2" -getrandom = "0.3.4" -hex = "0.4.3" -hex-literal = "1.1.0" quote = "1.0.42" -sha2 = "0.10.9" syn = {version = "2.0.109", features = ["full"]} proc-macro2 = "1.0.103" + +unshell-crypt = {path = "../unshell-crypt"} diff --git a/unshell-obfuscate/src/encrypt.rs b/unshell-obfuscate/src/encrypt.rs deleted file mode 100644 index cf7483e..0000000 --- a/unshell-obfuscate/src/encrypt.rs +++ /dev/null @@ -1,59 +0,0 @@ -// --- Add these imports to the top of src/lib.rs --- -use aes::{ - Aes256, - cipher::{BlockEncryptMut, KeyIvInit}, -}; -use cbc::Encryptor; -use cbc::cipher::block_padding::Pkcs7; -use hex; -use sha2::{Digest, Sha256}; - -use crate::{BACKUP_ENV_KEY, ENV_KEY_NAME}; - -// type Aes256CbcEncryptor = ; - -// A static, hardcoded IV. This is fine for obfuscation, -// as we're not protecting against replay attacks, just static analysis. -// This is the hex for "my_static_iv_012". -const STATIC_IV: [u8; 16] = [ - 0x6d, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x69, 0x76, 0x5f, 0x30, 0x31, 0x32, -]; - -fn pkcs7_padded_length(input_len: usize) -> usize { - let block_size = 16; - ((input_len / block_size) + 1) * block_size -} - -pub fn get_obfuscated_symbol_name(input: &str) -> String { - // 1. Get the key from the environment - // let key_str = - // std::env::var(ENV_KEY_NAME).expect(&format!("'{}' env var not set", ENV_KEY_NAME)); - - let key_str = std::env::var(ENV_KEY_NAME).unwrap_or(BACKUP_ENV_KEY.to_owned()); - - // 2. Hash the env key to get a 32-byte (256-bit) AES key - let mut hasher = Sha256::new(); - hasher.update(key_str.as_bytes()); - let key: [u8; 32] = hasher.finalize().into(); - - // 3. Encrypt the input string - let cipher = Encryptor::::new(&key.into(), &STATIC_IV.into()); - let mut plaintext = input.to_string(); - let plaintext = unsafe { plaintext.as_bytes_mut() }; - - let buf_len = pkcs7_padded_length(plaintext.len()); - let mut buf: Vec = vec![0; buf_len]; - - buf[..plaintext.len()].copy_from_slice(plaintext); - let ciphertext = cipher - .encrypt_padded_mut::(&mut buf, plaintext.len()) - .expect("Could not encrypt"); - - // 4. Hex-encode the result - let hex_encoded = hex::encode(ciphertext); - - hex_encoded - - // 5. Prepend a prefix - // format!("obf_{}", hex_encoded) -} diff --git a/unshell-obfuscate/src/lib.rs b/unshell-obfuscate/src/lib.rs index 2d92088..6a66ba4 100644 --- a/unshell-obfuscate/src/lib.rs +++ b/unshell-obfuscate/src/lib.rs @@ -3,10 +3,7 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{Expr, ItemFn, LitStr, parse_macro_input}; - -#[cfg(feature = "obfuscate")] -mod encrypt; +use syn::{ItemFn, parse_macro_input}; mod format_helper; use format_helper::*; @@ -14,11 +11,12 @@ use format_helper::*; // Put all encrypt-related dependencies in a module, so they are easier to use with the feature flag #[cfg(feature = "obfuscate")] mod obs_deps { - pub use crate::encrypt::get_obfuscated_symbol_name; pub use syn::LitStr; - - pub const ENV_KEY_NAME: &str = "OBFUSCATION_KEY"; - pub const BACKUP_ENV_KEY: &str = "OBFUSCATION_KEY_DO_NOT_USE"; + pub use unshell_crypt::BACKUP_ENV_KEY; + pub use unshell_crypt::ENV_KEY_NAME; + pub use unshell_crypt::STATIC_IV; + pub use unshell_crypt::aes::encrypt_aes_lines; + pub use unshell_crypt::fill; } #[cfg(feature = "obfuscate")] use obs_deps::*; @@ -49,13 +47,18 @@ pub fn symbol(input: TokenStream) -> TokenStream { #[cfg(feature = "obfuscate")] pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream { // Parse the input function + + use unshell_crypt::aes::encrypt_aes; let func = parse_macro_input!(item as ItemFn); // Get the original function name let fn_name = func.sig.ident.to_string(); + // get the encryption key + let key_str = std::env::var(ENV_KEY_NAME).unwrap_or(BACKUP_ENV_KEY.to_owned()); + // Generate the new, obfuscated name - let obfuscated_name = get_obfuscated_symbol_name(&fn_name); + let obfuscated_name = encrypt_aes_lines(&fn_name, &key_str, STATIC_IV); // Create a new string literal for the name let new_name_lit = LitStr::new(&obfuscated_name, func.sig.ident.span()); @@ -77,8 +80,11 @@ pub fn symbol(input: TokenStream) -> TokenStream { let lit_str = parse_macro_input!(input as LitStr); let original_name = lit_str.value(); + // get the encryption key + let key_str = std::env::var(ENV_KEY_NAME).unwrap_or(BACKUP_ENV_KEY.to_owned()); + // Generate the exact same obfuscated name - let obfuscated_name = get_obfuscated_symbol_name(&original_name); + let obfuscated_name = encrypt_aes_lines(&original_name, &key_str, STATIC_IV); // Expand to a static string literal TokenStream::from(quote! { @@ -106,7 +112,7 @@ pub fn obs(input: TokenStream) -> TokenStream { // 1. Generate a unique, random key for this string let mut key = vec![0u8; len]; - getrandom::fill(&mut key).expect("Failed to get random bytes for XOR key"); + fill(&mut key).expect("Failed to get random bytes for XOR key"); // 2. XOR the string with the key let mut obfuscated = Vec::with_capacity(len); diff --git a/unshell-payload/Cargo.lock b/unshell-payload/Cargo.lock index 6b4e035..13963e9 100644 --- a/unshell-payload/Cargo.lock +++ b/unshell-payload/Cargo.lock @@ -568,17 +568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unshell-lib" -version = "0.1.0" -dependencies = [ - "bincode", - "chrono", - "libloading", - "unshell-obfuscate", -] - -[[package]] -name = "unshell-obfuscate" +name = "unshell-crypt" version = "0.1.0" dependencies = [ "aes", @@ -587,15 +577,40 @@ dependencies = [ "getrandom", "hex", "hex-literal", + "regex", + "sha2", +] + +[[package]] +name = "unshell-lib" +version = "0.0.0" +dependencies = [ + "aes", + "bincode", + "block-padding 0.4.1", + "cbc", + "chrono", + "getrandom", + "hex", + "hex-literal", + "libloading", + "sha2", + "unshell-obfuscate", +] + +[[package]] +name = "unshell-obfuscate" +version = "0.0.0" +dependencies = [ "proc-macro2", "quote", - "sha2", "syn", + "unshell-crypt", ] [[package]] name = "unshell-payload" -version = "0.1.0" +version = "0.0.0" dependencies = [ "env_logger", "libloading", diff --git a/unshell-payload/Cargo.toml b/unshell-payload/Cargo.toml index 9ff3124..3fdaaf6 100644 --- a/unshell-payload/Cargo.toml +++ b/unshell-payload/Cargo.toml @@ -2,7 +2,6 @@ cargo-features = ["trim-paths"] [package] name = "unshell-payload" -version = "0.1.0" edition = "2024" [features] @@ -12,7 +11,7 @@ obfuscate = ["unshell-obfuscate/obfuscate"] env_logger = "0.11.8" libloading = "0.8.9" proc-macro2 = "1.0.103" -# unshell-logger = {path = "../unshell-logger"} + unshell-lib = {path = "../unshell-lib"} unshell-obfuscate = {path = "../unshell-obfuscate"}