Skip to content

Commit 8cb3610

Browse files
committed
Link Obfuscator for URL encryption
split URLs into 3-5 parts, encrypt each part using XOR and base64, provide encryption and decryption functions for runtime URL reconstruction, suitable for secure URL obfuscation.
1 parent a2c7c9c commit 8cb3610

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

link_obfuscator/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "link_obfuscator"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
windows = { version = "0.61.1", features = [
8+
"Win32_Foundation",
9+
"Win32_System_Memory",
10+
"Win32_Networking_WinInet",
11+
"Win32_System_SystemServices",
12+
"Win32_System_SystemInformation",
13+
"Win32_System_Diagnostics_Debug",
14+
"Win32_System_Threading",
15+
] }
16+
17+
ntapi = "0.4.1"
18+
base64 = "0.22.1"
19+
rand = "0.9.1"
20+

link_obfuscator/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Link Obfuscator
2+
3+
The Link Obfuscator is a code snippet that can be used to encrypt and split URLs into 3-5 parts (ran), making it confused for reverse engineers while reversing. It uses XOR encryption combined with base64 encoding and generates random variable names for each encrypted part, enhancing obfuscation.
4+
5+
## Features
6+
7+
* The URL is split into 3-5 parts, with each part encrypted separately, requiring reverse engineers to identify and decrypt all segments correctly.
8+
* Variable names are randomly generated with lowercase prefixes, making it hard to trace or predict the code structure.
9+
* The XOR and base64 encoding combination obscures the data, and without the key, brute-forcing the decryption is computationally intensive.
10+
* The random splitting and variable naming eliminate consistent patterns, forcing reverse engineers to analyze each output individually.
11+
12+
## PoC
13+
14+
![poc_image](./image.png)
15+
16+
## Credits / Reference
17+
18+
* [5mukx](https://x.com/5mukx)

link_obfuscator/image.png

59.5 KB
Loading

link_obfuscator/src/main.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#![allow(deprecated)]
2+
3+
use rand::{Rng, distr::{Alphanumeric, Uniform}};
4+
use base64::{encode, decode};
5+
use std::string::String;
6+
7+
8+
fn random_var_name() -> String {
9+
let first_char = rand::thread_rng()
10+
.sample_iter(Uniform::new_inclusive(b'a', b'z').unwrap())
11+
.take(1)
12+
.map(char::from)
13+
.collect::<String>();
14+
let length = rand::thread_rng().gen_range(4..=9); // total length 5-10 including first char
15+
let rest: String = rand::thread_rng()
16+
.sample_iter(&Alphanumeric)
17+
.take(length)
18+
.map(char::from)
19+
.collect();
20+
first_char + &rest
21+
}
22+
23+
// XOR-based encryption with a key
24+
fn xor_encrypt(input: &str, key: &str) -> String {
25+
let key_bytes = key.as_bytes();
26+
let input_bytes = input.as_bytes();
27+
let mut result = Vec::new();
28+
29+
for (i, &byte) in input_bytes.iter().enumerate() {
30+
result.push(byte ^ key_bytes[i % key_bytes.len()]);
31+
}
32+
33+
encode(result)
34+
}
35+
36+
// XOR-based decryption with a key
37+
fn xor_decrypt(input: &str, key: &str) -> String {
38+
let decoded = decode(input).expect("Failed to decode base64");
39+
let key_bytes = key.as_bytes();
40+
let mut result = Vec::new();
41+
42+
for (i, &byte) in decoded.iter().enumerate() {
43+
result.push(byte ^ key_bytes[i % key_bytes.len()]);
44+
}
45+
46+
String::from_utf8(result).expect("Failed to convert to string")
47+
}
48+
49+
// split URL into 3-5 parts
50+
fn split_url(url: &str) -> Vec<String> {
51+
let num_parts = rand::thread_rng().gen_range(3..=5);
52+
let url_len = url.len();
53+
let mut parts = Vec::new();
54+
let mut start = 0;
55+
56+
for _ in 0..num_parts-1 {
57+
let part_len = rand::thread_rng().gen_range(url_len/num_parts/2..=url_len/num_parts);
58+
if start + part_len <= url_len {
59+
parts.push(url[start..start+part_len].to_string());
60+
start += part_len;
61+
}
62+
}
63+
64+
if start < url_len {
65+
parts.push(url[start..].to_string());
66+
}
67+
68+
parts
69+
}
70+
71+
// encryption algorithm
72+
pub fn encryption_algorithm(url: &str, key: &str) -> (Vec<(String, String)>, String) {
73+
let parts = split_url(url);
74+
let mut encrypted_parts = Vec::new();
75+
76+
for part in parts {
77+
let var_name = random_var_name();
78+
let encrypted = xor_encrypt(&part, key);
79+
encrypted_parts.push((var_name, encrypted));
80+
}
81+
82+
let mut code = String::new();
83+
for (var_name, encrypted) in &encrypted_parts {
84+
code.push_str(&format!("let {} = \"{}\";\n", var_name, encrypted));
85+
}
86+
87+
(encrypted_parts, code)
88+
}
89+
90+
pub fn decryption_algorithm(encrypted_parts: &[(String, String)], key: &str) -> (String, String) {
91+
let mut decrypted_parts = Vec::new();
92+
let mut code = String::new();
93+
94+
for (var_name, encrypted) in encrypted_parts {
95+
let decrypted = xor_decrypt(encrypted, key);
96+
decrypted_parts.push(decrypted.clone());
97+
code.push_str(&format!("let decrypted_{} = xor_decrypt({}, \"{}\");\n", var_name, var_name, key));
98+
}
99+
100+
let final_url = decrypted_parts.join("");
101+
code.push_str(&format!("let final_url = format!(\"{}\", {});\n",
102+
decrypted_parts.iter().map(|_| "{}").collect::<Vec<_>>().join(""),
103+
encrypted_parts.iter().map(|(var_name, _)| format!("decrypted_{}", var_name)).collect::<Vec<_>>().join(", ")));
104+
105+
(final_url, code)
106+
}
107+
108+
fn main() {
109+
let url = "https://testsite.com/files/malicious.exe";
110+
// replace any random key ->
111+
let key = "M@lWaREiwV_iMsCooL";
112+
113+
114+
let (encrypted_parts, enc_code) = encryption_algorithm(url, key);
115+
println!("Encrypted parts code:\n{}", enc_code);
116+
117+
let (decrypted_url, dec_code) = decryption_algorithm(&encrypted_parts, key);
118+
println!("Decryption code:\n{}", dec_code);
119+
println!("Decrypted URL: {}", decrypted_url);
120+
}

0 commit comments

Comments
 (0)