dmanager 0.2.2

Manage concurrent access to overloaded memory sections.
#[macro_use]
extern crate litcrypt2;
use_litcrypt!();

use std::{collections::HashMap, cell::UnsafeCell};
use windows::Win32::Foundation::HANDLE;
use dinvoke_data::{PeMetadata, PVOID, PAGE_READWRITE};
use nanorand::{Rng, BufferedRng, WyRand};

pub struct Manager
{
    payloads: HashMap<usize, Vec<u8>>,
    payloads_metadata: HashMap<usize, PeMetadata>,
    decoys_metadata: HashMap<usize, PeMetadata>,
    decoys: HashMap<usize, Vec<u8>>,
    counter: HashMap<usize, i64>,
    keys: HashMap<usize, u8>
}

impl Manager {
    pub fn new () -> Manager {
        Manager{
            payloads: HashMap::new(),
            payloads_metadata: HashMap::new(),
            decoys_metadata: HashMap::new(),
            decoys: HashMap::new(),
            counter: HashMap::new(),
            keys: HashMap::new(),
        }
    }

    pub fn new_module (&mut self, address: usize, payload: Vec<u8>, decoy: Vec<u8>) -> Result<(), String>
    {   
        if self.payloads.contains_key(&address) {
            return Err(lc!("[x] This address is already mapped."));
        }

        unsafe 
        {
            let payload_metadata = manualmap::get_pe_metadata(payload.as_ptr(), false)?;
            let decoy_metadata = manualmap::get_pe_metadata(decoy.as_ptr(), false)?;

            let mut rand_bytes = [0u8; 15];
            let mut rng = BufferedRng::new(WyRand::new());
            rng.fill(&mut rand_bytes);
            let mut key_ptr = rand_bytes.as_ptr();

            let mut xor_key: u8 = *key_ptr;
            key_ptr = key_ptr.add(1);
            while *key_ptr != '\0' as u8 {
                xor_key = xor_key ^ *key_ptr;
                key_ptr = key_ptr.add(1);
            }

            let xored_payload = Manager::xor_module(payload, xor_key);
            let xored_decoy = Manager::xor_module(decoy, xor_key);

            self.payloads.insert(address, xored_payload);
            self.payloads_metadata.insert(address, payload_metadata);
            self.decoys_metadata.insert(address, decoy_metadata);
            self.decoys.insert(address, xored_decoy);
            self.counter.insert(address, 1);
            self.keys.insert(address, xor_key);

            Manager::hide_module(self, address)?;

        }

        Ok(())
    }

    pub fn new_shellcode (&mut self, address: usize, payload: Vec<u8>, decoy: Vec<u8>) -> Result<(), String>
    {   
        if self.payloads.contains_key(&address) {
            return Err(lc!("[x] This shellcode is already mapped."));
        }

        unsafe 
        {
            let mut rand_bytes = [0u8; 15];
            let mut rng = BufferedRng::new(WyRand::new());
            rng.fill(&mut rand_bytes);
            let mut key_ptr = rand_bytes.as_ptr();

            let mut xor_key: u8 = *key_ptr;
            key_ptr = key_ptr.add(1);
            while *key_ptr != '\0' as u8 {
                xor_key = xor_key ^ *key_ptr;
                key_ptr = key_ptr.add(1);
            }

            let xored_payload = Manager::xor_module(payload, xor_key);
            let xored_decoy = Manager::xor_module(decoy, xor_key);

            self.payloads.insert(address, xored_payload);
            self.decoys.insert(address, xored_decoy);
            self.counter.insert(address, 1);
            self.keys.insert(address, xor_key);

            Manager::hide_shellcode(self, address)?;

        }

        Ok(())
    }

    fn xor_module (module: Vec<u8>, key: u8) -> Vec<u8>
    {
        unsafe
        {
            let mut module_ptr = module.as_ptr();
            let mut final_module: Vec<u8> = vec![];

            for _i in 0..module.len() {
                final_module.push(*module_ptr ^ key);
                module_ptr = module_ptr.add(1);
            }

            final_module
        }
    }

    pub fn map_module (&mut self, address: usize) -> Result<(),String>
    {
        unsafe
        {
            if self.payloads.contains_key(&address)
            {
                if self.counter.get(&address).unwrap() == &0
                {   
                    let payload = self.payloads.get(&address).unwrap();
                    let key = *self.keys.get(&address).unwrap();
                    let pe_info = self.payloads_metadata.get(&address).unwrap();
                    let decoy_info = self.decoys_metadata.get(&address).unwrap();
                    
                    let addr: PVOID = std::mem::transmute(address);
                    let handle = HANDLE {0: -1 as _};
                    let base_address: *mut PVOID = std::mem::transmute(&address);
                    let s: UnsafeCell<i64> = i64::default().into();
                    let size: *mut usize = std::mem::transmute(s.get());
                    
                    if decoy_info.is_32_bit {
                        *size = decoy_info.opt_header_32.SizeOfImage as usize;
                    } else {
                        *size = decoy_info.opt_header_64.size_of_image as usize;
                    }

                    let old_protection: *mut u32 = std::mem::transmute(&u32::default());
                    let ret = dinvoke::nt_protect_virtual_memory(handle, base_address, size, PAGE_READWRITE, old_protection);
                    
                    if ret != 0 {
                        return Err(lc!("[x] Error changing memory protection."));
                    }

                    dinvoke::rtl_zero_memory(*base_address, *size);
                    let mut decrypted_payload = Manager::xor_module(payload.to_vec(), key);
                    let _r = manualmap::map_to_allocated_memory(decrypted_payload.as_ptr(), addr, pe_info)?;
                    let decrypted_payload_ptr = decrypted_payload.as_mut_ptr();
                    
                    for i in 0..decrypted_payload.len() {
                        *(decrypted_payload_ptr.add(i)) = 0u8;
                    }
                } 

                self.counter.insert(address, self.counter[&address] + 1);
            }

            Ok(())
        }
    }

    pub fn hide_module(&mut self, address: usize) -> Result<(),String>
    {
        unsafe
        {
            if self.payloads.contains_key(&address)
            {
                if self.counter.get(&address).unwrap() == &1
                {   
                    let decoy = self.decoys.get(&address).unwrap();
                    let key = *self.keys.get(&address).unwrap();
                    let decrypted_decoy = Manager::xor_module(decoy.to_vec(), key);
                    let pe_info = self.decoys_metadata.get(&address).unwrap();
                    let addr: PVOID = std::mem::transmute(address);
    
                    let handle = HANDLE {0: -1 as _};
                    let base_address: *mut PVOID = std::mem::transmute(&address);
                    let s: UnsafeCell<usize> = usize::default().into();
                    let size: *mut usize = std::mem::transmute(s.get());
                    
                    if pe_info.is_32_bit {
                        *size = pe_info.opt_header_32.SizeOfImage as usize;
                    } else {
                        *size = pe_info.opt_header_64.size_of_image as usize;
                    }

                    let old_protection: *mut u32 = std::mem::transmute(&u32::default());
                    let ret = dinvoke::nt_protect_virtual_memory(handle, base_address, size, PAGE_READWRITE, old_protection);
                    dinvoke::rtl_zero_memory(*base_address, *size);

                    if ret != 0 {
                        return Err(lc!("[x] Error changing memory protection."));
                    }

                    let _r = manualmap::map_to_allocated_memory(decrypted_decoy.as_ptr(), addr, pe_info)?;
                } 

                if self.counter.get(&address).unwrap() >= &1 {
                    self.counter.insert(address, self.counter[&address] - 1);
                }

            }

            Ok(())
        }
    }

    pub fn hide_shellcode(&mut self, address: usize) -> Result<(),String>
    {
        if self.payloads.contains_key(&address)
        {
            if self.counter.get(&address).unwrap() == &1
            {   
                let decoy = self.decoys.get(&address).unwrap();
                let key = *self.keys.get(&address).unwrap();
                let decrypted_decoy = Manager::xor_module(decoy.to_vec(), key);    
                let result = dinvoke_overload::managed_module_stomping(&decrypted_decoy, address, 0);

                if !result.is_ok() {
                    return Err(lc!("[x] Error hiding shellcode."));
                }
            } 

            if self.counter.get(&address).unwrap() >= &1 {
                self.counter.insert(address, self.counter[&address] - 1);
            }
        }

        Ok(())
    }

    pub fn stomp_shellcode(&mut self, address: usize) -> Result<(),String>
    {
        if self.payloads.contains_key(&address)
        {
            if self.counter.get(&address).unwrap() == &0
            {   
                let payload = self.payloads.get(&address).unwrap();
                let key = *self.keys.get(&address).unwrap();
                let mut decrypted_payload = Manager::xor_module(payload.to_vec(), key);
                let result = dinvoke_overload::managed_module_stomping(&decrypted_payload, address, 0);
                let decrypted_payload_ptr = decrypted_payload.as_mut_ptr();
                unsafe {
                    for i in 0..decrypted_payload.len() {
                        *(decrypted_payload_ptr.add(i)) = 0u8;
                    }
                }

                if !result.is_ok() {
                    return Err(lc!("[x] Error stomping shellcode."));
                }
            } 

            self.counter.insert(address, self.counter[&address] + 1);
        }

        Ok(())
    }

}