libmwemu 0.25.4

x86 32/64bits and system internals emulator, for securely emulating malware and other stuff.
Documentation
use super::nt_tib32::NtTib32;
use crate::maps::Maps;
use crate::maps::mem64::Mem64;

#[derive(Debug)]
pub struct TEB {
    pub nt_tib: NtTib32,
    pub environment_pointer: u32,
    pub process_id: u32,
    pub thread_id: u32,
    pub active_rpc_handle: u32,
    pub thread_local_storage_pointer: u32,
    pub process_environment_block: u32,
    pub last_error_value: u32,
    pub count_of_owned_critical_sections: u32,
    pub csr_client_thread: u32,
    pub win32_thread_info: u32,
    pub user32_reserved: [u32; 26],
    pub user_reserved: [u32; 5],
    pub wow32_reserved: u32,
    pub current_locale: u32,
    pub fp_software_status_register: u32,
    pub exception_code: u32,
    pub activation_context_stack_pointer: u32,
}

impl TEB {
    pub const NT_TIB_OFFSET: u64 = 0x00;
    pub const ENVIRONMENT_POINTER_OFFSET: u64 = 0x1c;
    pub const CLIENT_ID_OFFSET: u64 = 0x20;
    pub const CLIENT_ID_PROCESS_ID_OFFSET: u64 = 0x20;
    pub const CLIENT_ID_THREAD_ID_OFFSET: u64 = 0x24;
    pub const ACTIVE_RPC_HANDLE_OFFSET: u64 = 0x28;
    pub const THREAD_LOCAL_STORAGE_POINTER_OFFSET: u64 = 0x2c;
    pub const PROCESS_ENVIRONMENT_BLOCK_OFFSET: u64 = 0x30;
    pub const LAST_ERROR_VALUE_OFFSET: u64 = 0x34;
    pub const COUNT_OF_OWNED_CRITICAL_SECTIONS_OFFSET: u64 = 0x38;
    pub const CSR_CLIENT_THREAD_OFFSET: u64 = 0x3c;
    pub const WIN32_THREAD_INFO_OFFSET: u64 = 0x40;
    pub const USER32_RESERVED_OFFSET: u64 = 0x44;
    pub const USER_RESERVED_OFFSET: u64 = 0xac;
    pub const WOW32_RESERVED_OFFSET: u64 = 0xc0;
    pub const CURRENT_LOCALE_OFFSET: u64 = 0xc4;
    pub const FP_SOFTWARE_STATUS_REGISTER_OFFSET: u64 = 0xc8;
    pub const EXCEPTION_CODE_OFFSET: u64 = 0x1a4;
    pub const ACTIVATION_CONTEXT_STACK_POINTER_OFFSET: u64 = 0x1a8;

    pub fn size() -> usize {
        0x1038
    }

    pub fn map_size() -> usize {
        0x2000
    }

    pub fn new(peb_addr: u32) -> TEB {
        TEB {
            nt_tib: NtTib32::new(),
            environment_pointer: 0,
            process_id: 3240,
            thread_id: 1,
            active_rpc_handle: 0,
            thread_local_storage_pointer: 0,
            process_environment_block: peb_addr,
            last_error_value: 0,
            count_of_owned_critical_sections: 0,
            csr_client_thread: 0,
            win32_thread_info: 0,
            user32_reserved: [0; 26],
            user_reserved: [0; 5],
            wow32_reserved: 0,
            current_locale: 0,
            fp_software_status_register: 0,
            exception_code: 0,
            activation_context_stack_pointer: 0,
        }
    }

    pub fn set_last_error(&mut self, err: u32) {
        self.last_error_value = err;
    }

    pub fn load(addr: u64, maps: &Maps) -> TEB {
        let mut user32_reserved = [0; 26];
        for (index, value) in user32_reserved.iter_mut().enumerate() {
            *value = maps
                .read_dword(Self::USER32_RESERVED_OFFSET + addr + index as u64 * 4)
                .unwrap();
        }
        let mut user_reserved = [0; 5];
        for (index, value) in user_reserved.iter_mut().enumerate() {
            *value = maps
                .read_dword(Self::USER_RESERVED_OFFSET + addr + index as u64 * 4)
                .unwrap();
        }

        TEB {
            nt_tib: NtTib32::load(addr + Self::NT_TIB_OFFSET, maps),
            environment_pointer: maps
                .read_dword(addr + Self::ENVIRONMENT_POINTER_OFFSET)
                .unwrap(),
            process_id: maps
                .read_dword(addr + Self::CLIENT_ID_PROCESS_ID_OFFSET)
                .unwrap(),
            thread_id: maps
                .read_dword(addr + Self::CLIENT_ID_THREAD_ID_OFFSET)
                .unwrap(),
            active_rpc_handle: maps
                .read_dword(addr + Self::ACTIVE_RPC_HANDLE_OFFSET)
                .unwrap(),
            thread_local_storage_pointer: maps
                .read_dword(addr + Self::THREAD_LOCAL_STORAGE_POINTER_OFFSET)
                .unwrap(),
            process_environment_block: maps
                .read_dword(addr + Self::PROCESS_ENVIRONMENT_BLOCK_OFFSET)
                .unwrap(),
            last_error_value: maps
                .read_dword(addr + Self::LAST_ERROR_VALUE_OFFSET)
                .unwrap(),
            count_of_owned_critical_sections: maps
                .read_dword(addr + Self::COUNT_OF_OWNED_CRITICAL_SECTIONS_OFFSET)
                .unwrap(),
            csr_client_thread: maps
                .read_dword(addr + Self::CSR_CLIENT_THREAD_OFFSET)
                .unwrap(),
            win32_thread_info: maps
                .read_dword(addr + Self::WIN32_THREAD_INFO_OFFSET)
                .unwrap(),
            user32_reserved,
            user_reserved,
            wow32_reserved: maps.read_dword(addr + Self::WOW32_RESERVED_OFFSET).unwrap(),
            current_locale: maps.read_dword(addr + Self::CURRENT_LOCALE_OFFSET).unwrap(),
            fp_software_status_register: maps
                .read_dword(addr + Self::FP_SOFTWARE_STATUS_REGISTER_OFFSET)
                .unwrap(),
            exception_code: maps.read_dword(addr + Self::EXCEPTION_CODE_OFFSET).unwrap(),
            activation_context_stack_pointer: maps
                .read_dword(addr + Self::ACTIVATION_CONTEXT_STACK_POINTER_OFFSET)
                .unwrap(),
        }
    }

    pub fn load_map(addr: u64, map: &Mem64) -> TEB {
        let mut user32_reserved = [0; 26];
        for (index, value) in user32_reserved.iter_mut().enumerate() {
            *value = map.read_dword(Self::USER32_RESERVED_OFFSET + addr + index as u64 * 4);
        }
        let mut user_reserved = [0; 5];
        for (index, value) in user_reserved.iter_mut().enumerate() {
            *value = map.read_dword(Self::USER_RESERVED_OFFSET + addr + index as u64 * 4);
        }

        TEB {
            nt_tib: NtTib32::load_map(addr + Self::NT_TIB_OFFSET, map),
            environment_pointer: map.read_dword(addr + Self::ENVIRONMENT_POINTER_OFFSET),
            process_id: map.read_dword(addr + Self::CLIENT_ID_PROCESS_ID_OFFSET),
            thread_id: map.read_dword(addr + Self::CLIENT_ID_THREAD_ID_OFFSET),
            active_rpc_handle: map.read_dword(addr + Self::ACTIVE_RPC_HANDLE_OFFSET),
            thread_local_storage_pointer: map
                .read_dword(addr + Self::THREAD_LOCAL_STORAGE_POINTER_OFFSET),
            process_environment_block: map
                .read_dword(addr + Self::PROCESS_ENVIRONMENT_BLOCK_OFFSET),
            last_error_value: map.read_dword(addr + Self::LAST_ERROR_VALUE_OFFSET),
            count_of_owned_critical_sections: map
                .read_dword(addr + Self::COUNT_OF_OWNED_CRITICAL_SECTIONS_OFFSET),
            csr_client_thread: map.read_dword(addr + Self::CSR_CLIENT_THREAD_OFFSET),
            win32_thread_info: map.read_dword(addr + Self::WIN32_THREAD_INFO_OFFSET),
            user32_reserved,
            user_reserved,
            wow32_reserved: map.read_dword(addr + Self::WOW32_RESERVED_OFFSET),
            current_locale: map.read_dword(addr + Self::CURRENT_LOCALE_OFFSET),
            fp_software_status_register: map
                .read_dword(addr + Self::FP_SOFTWARE_STATUS_REGISTER_OFFSET),
            exception_code: map.read_dword(addr + Self::EXCEPTION_CODE_OFFSET),
            activation_context_stack_pointer: map
                .read_dword(addr + Self::ACTIVATION_CONTEXT_STACK_POINTER_OFFSET),
        }
    }

    pub fn save(&self, mem: &mut Mem64) {
        let base = mem.get_base();
        self.nt_tib.save(base + Self::NT_TIB_OFFSET, mem);
        mem.write_dword(
            base + Self::ENVIRONMENT_POINTER_OFFSET,
            self.environment_pointer,
        );
        mem.write_dword(base + Self::CLIENT_ID_PROCESS_ID_OFFSET, self.process_id);
        mem.write_dword(base + Self::CLIENT_ID_THREAD_ID_OFFSET, self.thread_id);
        mem.write_dword(
            base + Self::ACTIVE_RPC_HANDLE_OFFSET,
            self.active_rpc_handle,
        );
        mem.write_dword(
            base + Self::THREAD_LOCAL_STORAGE_POINTER_OFFSET,
            self.thread_local_storage_pointer,
        );
        mem.write_dword(
            base + Self::PROCESS_ENVIRONMENT_BLOCK_OFFSET,
            self.process_environment_block,
        );
        mem.write_dword(base + Self::LAST_ERROR_VALUE_OFFSET, self.last_error_value);
        mem.write_dword(
            base + Self::COUNT_OF_OWNED_CRITICAL_SECTIONS_OFFSET,
            self.count_of_owned_critical_sections,
        );
        mem.write_dword(
            base + Self::CSR_CLIENT_THREAD_OFFSET,
            self.csr_client_thread,
        );
        mem.write_dword(
            base + Self::WIN32_THREAD_INFO_OFFSET,
            self.win32_thread_info,
        );
        for (index, value) in self.user32_reserved.iter().enumerate() {
            mem.write_dword(
                base + Self::USER32_RESERVED_OFFSET + index as u64 * 4,
                *value,
            );
        }
        for (index, value) in self.user_reserved.iter().enumerate() {
            mem.write_dword(base + Self::USER_RESERVED_OFFSET + index as u64 * 4, *value);
        }
        mem.write_dword(base + Self::WOW32_RESERVED_OFFSET, self.wow32_reserved);
        mem.write_dword(base + Self::CURRENT_LOCALE_OFFSET, self.current_locale);
        mem.write_dword(
            base + Self::FP_SOFTWARE_STATUS_REGISTER_OFFSET,
            self.fp_software_status_register,
        );
        mem.write_dword(base + Self::EXCEPTION_CODE_OFFSET, self.exception_code);
        mem.write_dword(
            base + Self::ACTIVATION_CONTEXT_STACK_POINTER_OFFSET,
            self.activation_context_stack_pointer,
        );
    }

    pub fn print(&self) {
        log::trace!("{:#x?}", self);
    }
}