mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Add refrerence symbolic strings
This commit is contained in:
@@ -1,7 +1,57 @@
|
|||||||
use aes::cipher::{BlockDecryptMut, KeyIvInit, block_padding::Pkcs7};
|
use crate::{base62::Base62, hash};
|
||||||
|
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
||||||
|
use cbc::cipher::block_padding::Pkcs7;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::{Base62, hash};
|
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 {
|
||||||
|
let plaintext = plaintext.as_bytes();
|
||||||
|
|
||||||
|
// Hash the env key to get a 32-byte (256-bit) AES key
|
||||||
|
let key = hash(key_str.as_bytes());
|
||||||
|
|
||||||
|
// Generate a pseudo-random salt byte based on the plaintext
|
||||||
|
// I hope this does not break the encryption.
|
||||||
|
let mut salt = 0;
|
||||||
|
|
||||||
|
for byte in plaintext {
|
||||||
|
salt ^= byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut key_salted = key.clone();
|
||||||
|
|
||||||
|
// Salt the key by XORing the salt byte with all the key bytes.
|
||||||
|
// This ensures that the "hash" generated from the plaintext will
|
||||||
|
// make the encrypted result extremely different.
|
||||||
|
for i in 0..32 {
|
||||||
|
key_salted[i] ^= salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mut ct = cbc::Encryptor::<aes::Aes256>::new(&key_salted.into(), &iv.into())
|
||||||
|
.encrypt_padded_mut::<Pkcs7>(&mut buf, pt_len)
|
||||||
|
.unwrap()
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
// Add the salt byte to the key byte,
|
||||||
|
ct.insert(0, salt);
|
||||||
|
|
||||||
|
// Encode result in base62
|
||||||
|
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]) -> Result<String, String> {
|
pub fn decrypt_aes(input: &str, key_str: &str, iv: [u8; 16]) -> Result<String, String> {
|
||||||
// Hash the env key to get a 32-byte (256-bit) AES key
|
// Hash the env key to get a 32-byte (256-bit) AES key
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
use crate::{base62::Base62, hash};
|
|
||||||
use aes::cipher::{BlockEncryptMut, KeyIvInit};
|
|
||||||
use cbc::cipher::block_padding::Pkcs7;
|
|
||||||
|
|
||||||
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 {
|
|
||||||
let plaintext = plaintext.as_bytes();
|
|
||||||
|
|
||||||
// Hash the env key to get a 32-byte (256-bit) AES key
|
|
||||||
let key = hash(key_str.as_bytes());
|
|
||||||
|
|
||||||
// Generate a psudo-random salt byte based on the plaintext
|
|
||||||
// I hope this does not break the encryption.
|
|
||||||
let mut salt = 0;
|
|
||||||
|
|
||||||
for byte in plaintext {
|
|
||||||
salt ^= byte;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut key_salted = key.clone();
|
|
||||||
|
|
||||||
// Salt the key by XORing the salt byte with all the key bytes.
|
|
||||||
// This ensures that the "hash" generated from the plaintext will
|
|
||||||
// make the encrypted result extremely different.
|
|
||||||
for i in 0..32 {
|
|
||||||
key_salted[i] ^= salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 mut ct = cbc::Encryptor::<aes::Aes256>::new(&key_salted.into(), &iv.into())
|
|
||||||
.encrypt_padded_mut::<Pkcs7>(&mut buf, pt_len)
|
|
||||||
.unwrap()
|
|
||||||
.to_vec();
|
|
||||||
|
|
||||||
// Add the salt byte to the key byte,
|
|
||||||
ct.insert(0, salt);
|
|
||||||
|
|
||||||
// Encode result in base62
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
@@ -18,19 +18,20 @@ const ENCODING_RATIO: f64 = 8.0 / 5.954196310386875; // 8.0 / log2(62.0)
|
|||||||
impl Base62 {
|
impl Base62 {
|
||||||
pub fn new(key: &[u8], nonce: usize) -> Self {
|
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
|
// Hash key again, for the chance that this random function can be used to derive the key
|
||||||
|
// My solution to not being good at cryptography lol
|
||||||
let key = hash(key);
|
let key = hash(key);
|
||||||
|
|
||||||
let mut charset: [char; 62] = [0 as char; 62];
|
let mut charset: [char; 62] = [0 as char; 62];
|
||||||
|
|
||||||
// Create a vector of indices from 0 to 61
|
// Create a vector of indices from 0 to 61
|
||||||
let mut current_indicies = (0..62).map(|i| i as usize).collect::<Vec<usize>>();
|
let mut current_indices = (0..62).map(|i| i as usize).collect::<Vec<usize>>();
|
||||||
|
|
||||||
// Loop through each byte in the key until all chars are filled
|
// Loop through each byte in the key until all chars are filled
|
||||||
for i in 0..62 as usize {
|
for i in 0..62 as usize {
|
||||||
let rand = STATIC_BYTE_MAP[(key[i as usize % key.len()] as usize + nonce) % 255];
|
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 index_index = rand as usize % current_indices.len();
|
||||||
let put_index = current_indicies.remove(index_index);
|
let put_index = current_indices.remove(index_index);
|
||||||
|
|
||||||
charset[put_index] = BASE62_CHARS[i];
|
charset[put_index] = BASE62_CHARS[i];
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -1,11 +1,8 @@
|
|||||||
mod aes_decrypt;
|
mod aes;
|
||||||
mod aes_encrypt;
|
|
||||||
#[allow(dead_code)]
|
|
||||||
mod base62;
|
mod base62;
|
||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
pub use aes_decrypt::{decrypt_aes, decrypt_aes_lines};
|
pub use aes::{decrypt_aes, decrypt_aes_lines, encrypt_aes, encrypt_aes_lines};
|
||||||
pub use aes_encrypt::{encrypt_aes, encrypt_aes_lines};
|
|
||||||
pub use base62::Base62;
|
pub use base62::Base62;
|
||||||
|
|
||||||
pub const STATIC_IV: [u8; 16] = [
|
pub const STATIC_IV: [u8; 16] = [
|
||||||
@@ -35,3 +32,19 @@ pub fn hash(input: &[u8]) -> [u8; 32] {
|
|||||||
hasher.update(input);
|
hasher.update(input);
|
||||||
hasher.finalize().into()
|
hasher.finalize().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn encode_usize(value: usize) -> Vec<u8> {
|
||||||
|
if value == 0 {
|
||||||
|
return vec![0];
|
||||||
|
}
|
||||||
|
let bytes = value.to_be_bytes();
|
||||||
|
let leading_zeros = bytes.iter().take_while(|&&b| b == 0).count();
|
||||||
|
bytes[leading_zeros..].to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_usize(bytes: &[u8]) -> usize {
|
||||||
|
let mut buf = [0u8; size_of::<usize>()];
|
||||||
|
let offset = buf.len() - bytes.len();
|
||||||
|
buf[offset..].copy_from_slice(bytes);
|
||||||
|
usize::from_be_bytes(buf)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
# -Z build-std-features= \
|
# -Z build-std-features= \
|
||||||
# --profile minimize -p unshell-payload -- $@
|
# --profile minimize -p unshell-payload -- $@
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
OBFUSCATION_KEY=kjwerkwerkjbwejehrwhje \
|
||||||
cargo build --profile minimize -p ush-payload $@
|
cargo build --profile minimize -p ush-payload $@
|
||||||
|
|
||||||
export BINARY=./target/minimize/ush-payload
|
export BINARY=./target/minimize/ush-payload
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ authors.workspace = true
|
|||||||
include.workspace = true
|
include.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["obfuscate_none"]
|
default = []
|
||||||
obfuscate_none = []
|
|
||||||
obfuscate_aes = []
|
obfuscate_aes = []
|
||||||
obfuscate_ref = []
|
obfuscate_ref = []
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ const ENV_KEY_NAME: &str = "OBFUSCATION_KEY";
|
|||||||
const BACKUP_ENV_KEY: &str = "OBFUSCATION_KEY_DO_NOT_USE";
|
const BACKUP_ENV_KEY: &str = "OBFUSCATION_KEY_DO_NOT_USE";
|
||||||
|
|
||||||
pub fn get_encryption_key() -> String {
|
pub fn get_encryption_key() -> String {
|
||||||
std::env::var(ENV_KEY_NAME).unwrap_or({
|
if let Ok(key) = std::env::var(ENV_KEY_NAME) {
|
||||||
|
key
|
||||||
|
} else {
|
||||||
println!("Using default encryption key!");
|
println!("Using default encryption key!");
|
||||||
BACKUP_ENV_KEY.to_owned()
|
BACKUP_ENV_KEY.to_owned()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ pub fn xor(input: TokenStream) -> TokenStream {
|
|||||||
return TokenStream::from(quote! { String::new() });
|
return TokenStream::from(quote! { String::new() });
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Obfuscated Branch Logic ---
|
|
||||||
// This code runs at compile-time
|
|
||||||
|
|
||||||
let str_bytes = original_str.as_bytes();
|
let str_bytes = original_str.as_bytes();
|
||||||
let len = str_bytes.len();
|
let len = str_bytes.len();
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ macro_rules! delete {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "obfuscate_none")]
|
#[cfg(all(not(feature = "obfuscate_aes"), not(feature = "obfuscate_ref")))]
|
||||||
pub mod proc_impl {
|
pub mod proc_impl {
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syn::{LitStr, parse_macro_input};
|
use syn::{LitStr, parse_macro_input};
|
||||||
@@ -61,6 +61,6 @@ pub mod proc_impl {
|
|||||||
unwrap_string!(xor);
|
unwrap_string!(xor);
|
||||||
delete!(junk_asm);
|
delete!(junk_asm);
|
||||||
|
|
||||||
unwrap_string!(sym);
|
passtrough!(sym, crate::symbolic_ref::sym_ref);
|
||||||
unwrap_string!(sym_fn);
|
unwrap_string!(sym_fn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,48 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use base62::{Base62, hash};
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{LitStr, parse_macro_input};
|
||||||
|
|
||||||
|
use crate::env::get_encryption_key;
|
||||||
|
|
||||||
|
static mut SYM_COUNTER: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
pub fn get_symbol_number() -> usize {
|
||||||
|
unsafe { SYM_COUNTER.len() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
pub fn get_symbol(text: String) -> usize {
|
||||||
|
unsafe {
|
||||||
|
if let Some(n) = SYM_COUNTER.iter().position(|r| r == &text) {
|
||||||
|
n
|
||||||
|
} else {
|
||||||
|
SYM_COUNTER.push(text);
|
||||||
|
|
||||||
|
SYM_COUNTER.len() - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sym_ref(input: TokenStream) -> TokenStream {
|
||||||
|
// Parse the input as a string literal
|
||||||
|
let lit_str = parse_macro_input!(input as LitStr);
|
||||||
|
let original_name = lit_str.value();
|
||||||
|
|
||||||
|
let n = get_symbol(original_name);
|
||||||
|
|
||||||
|
let data = base62::encode_usize(n);
|
||||||
|
let key = hash(&get_encryption_key().as_bytes());
|
||||||
|
|
||||||
|
let encoded = format!("_{}_", Base62::encode_full(&data, &key));
|
||||||
|
|
||||||
|
println!("Aliased '{}' as '{encoded}'", lit_str.value());
|
||||||
|
|
||||||
|
// Expand to a static string literal
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
#encoded
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ edition = "2024"
|
|||||||
default = ["log"]
|
default = ["log"]
|
||||||
log = ["unshell/log"]
|
log = ["unshell/log"]
|
||||||
log_debug = ["unshell/log_debug"]
|
log_debug = ["unshell/log_debug"]
|
||||||
obfuscate = ["unshell/obfuscate_aes"]
|
obfuscate = ["unshell/obfuscate_ref"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
unshell.path = "../"
|
unshell.path = "../"
|
||||||
|
|||||||
+21
-23
@@ -1,46 +1,44 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
extern crate unshell;
|
extern crate unshell;
|
||||||
|
|
||||||
use unshell::{
|
use unshell::{info, obfuscate::sym, tree::Tree};
|
||||||
Value, info,
|
|
||||||
obfuscate::{junk_asm, sym},
|
|
||||||
tree::{Tree, TreeElement, symbols},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut manager = Tree::new();
|
let mut manager = Tree::new();
|
||||||
manager.init_logger();
|
manager.init_logger();
|
||||||
|
|
||||||
|
println!("{}", sym!("TEST"));
|
||||||
|
|
||||||
info!("Test thing!");
|
info!("Test thing!");
|
||||||
info!("Test thing!");
|
info!("Test thing!");
|
||||||
|
|
||||||
loop {
|
// loop {
|
||||||
if test123(&mut manager) {
|
// if test123(&mut manager) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// println!("Test");
|
// println!("Test");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test123(manager: &mut Tree) -> bool {
|
// fn test123(manager: &mut Tree) -> bool {
|
||||||
let result = manager.send_message(
|
// let result = manager.send_message(
|
||||||
Value::String(sym!("Logger").to_string()),
|
// Value::String(sym!("Logger").to_string()),
|
||||||
Value::String(symbols::CMD_GET.to_string()),
|
// Value::String(symbols::CMD_GET.to_string()),
|
||||||
);
|
// );
|
||||||
|
|
||||||
junk_asm!(20.);
|
// junk_asm!(20.);
|
||||||
|
|
||||||
let is_null = result.is_null();
|
// let is_null = result.is_null();
|
||||||
|
|
||||||
// if let Ok(result) = serde_json::from_value::<Record>(result) {
|
// // if let Ok(result) = serde_json::from_value::<Record>(result) {
|
||||||
// log(&result);
|
// // log(&result);
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
is_null
|
// is_null
|
||||||
|
|
||||||
// println!("Logger: {}", result);
|
// // println!("Logger: {}", result);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// use std::{any::Any, collections::HashMap, fs::File, io::Read};
|
// use std::{any::Any, collections::HashMap, fs::File, io::Read};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user