Skip to content

Instantly share code, notes, and snippets.

@molenzwiebel
Created December 2, 2023 15:33
Show Gist options
  • Save molenzwiebel/284318d9e963672b239f9fca901be89a to your computer and use it in GitHub Desktop.
Save molenzwiebel/284318d9e963672b239f9fca901be89a to your computer and use it in GitHub Desktop.
/// Character substitutions for obfuscation purposes.
const SUBST_TABLE: &[(char, [&'static str; 4])] = &[
('Q', ["QP", "QD", "QW", "Q4"]),
('-', ["QL", "QB", "QO", "Q5"]),
('_', ["QC", "QN", "QT", "Q9"]),
('X', ["XU", "XN", "XH", "X3"]),
('!', ["XW", "XS", "XZ", "X0"]),
];
/// Character substitutions for deobfuscation purposes.
const SUBST_TABLE_REV: &[(&'static str, char, usize)] = &[
// Q
("QP", 'Q', 0),
("QD", 'Q', 1),
("QW", 'Q', 2),
("Q4", 'Q', 3),
// -
("QL", '-', 0),
("QB", '-', 1),
("QO", '-', 2),
("Q5", '-', 3),
// _
("QC", '_', 0),
("QN", '_', 1),
("QT", '_', 2),
("Q9", '_', 3),
// X
("XU", 'X', 0),
("XN", 'X', 1),
("XH", 'X', 2),
("X3", 'X', 3),
// !
("XW", '!', 0),
("XS", '!', 1),
("XZ", '!', 2),
("X0", '!', 3),
];
/// Escape the given string by replacing all characters in SUBST_TABLE.
pub fn escape_string(input: &str) -> String {
let input = input.to_uppercase();
let mut out = String::new();
for c in input.chars() {
let subst = SUBST_TABLE.iter().find(|(c2, _)| *c2 == c);
if let Some((_, subst)) = subst {
out.push_str(subst[out.len() % subst.len()]);
} else {
out.push(c);
}
}
out
}
/// Unescape the given string by checking whether every pair of characters
/// is in SUBST_TABLE_REV.
pub fn unescape_string(input: &str) -> String {
let input = input.to_uppercase();
let mut out = String::new();
let mut i = 0;
while i < input.len() {
let subst = SUBST_TABLE_REV
.iter()
.find(|(c2, _, _)| input[i..].starts_with(c2));
match subst {
Some(&(str, c, pos)) if i % 4 == pos => {
out.push(c);
i += str.len();
}
_ => {
out.push(input.chars().nth(i).unwrap());
i += 1;
}
}
}
out
}
/// Obfuscate the given string.
pub fn obfuscate_string(orig_input: &str) -> String {
let mut input = escape_string(orig_input);
let unpadded_length = orig_input.len();
// if the input is less than 20 characters, pad with ......
if unpadded_length < 20 {
// escape leaves . intact but replaces ! with relevant char
input =
escape_string(&(orig_input.to_string() + "!" + &".".repeat(20 - unpadded_length - 1)));
}
let length = input.len() as i32;
let mut out = String::new();
let mut chars: Vec<_> = input.chars().collect();
for i in 0..chars.len() {
let c = chars[i];
let mut x = c as u8 as i32;
if c >= '0' && c <= '9' {
x += 43; // wrap up if numerical
}
let mut new_c = (length + 7i32 * (x - 65)) % 36 + 65;
if new_c >= 91 {
new_c -= 43; // wrap back down to numerical
}
let new_c = new_c as u8 as char;
out.push(new_c);
if i + unpadded_length < chars.len() && chars[i + unpadded_length] == '.' {
// replace placeholder .s with this character, they'll get obfuscated later
chars[i + unpadded_length] = new_c;
}
}
out
}
/// Deobfuscate the given string.
pub fn deobfuscate_string(input: &str) -> String {
let input = input.to_uppercase();
let mut out = String::new();
for c in input.chars() {
let mut x = c as u8 as i32;
if c >= '0' && c <= '9' {
x += 43; // wrap up if numerical
}
let mut i = (31 * (x - input.len() as i32 - 65) % 36 + 36) % 36 + 65;
if i >= 91 {
i -= 43; // wrap back down to numerical
}
out.push(i as u8 as char);
}
// strip out !<padding> if needed
let unescaped = unescape_string(&out);
if unescaped.contains("!") {
unescaped.split("!").next().unwrap().to_string()
} else {
unescaped
}
}
@Masrawy2
Copy link

how i could use this script pls ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment