From 559186088fe083cc6e6a19aa299cf7cd4b02f2c5 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sun, 9 Feb 2025 21:11:02 +0100 Subject: [PATCH] stuff --- src/emulated.rs | 136 +++++++++++++++++++++++++++++++++--------------- src/lib.rs | 10 +++- 2 files changed, 102 insertions(+), 44 deletions(-) diff --git a/src/emulated.rs b/src/emulated.rs index 60cff5a..a8cd9ac 100644 --- a/src/emulated.rs +++ b/src/emulated.rs @@ -2,7 +2,10 @@ #![allow(non_camel_case_types)] mod base_defs { - use std::{ffi::CStr, fmt::Debug}; + use std::{ffi::CStr, fmt::Debug, os::fd::RawFd, sync::atomic::Ordering}; + + pub(crate) type SIZE_T = usize; + pub(crate) type DWORD = i32; pub(crate) type HANDLE = usize; @@ -47,7 +50,21 @@ mod base_defs { pub(super) mutex: std::sync::atomic::AtomicU64, pub(super) pad: [u8; 40 - 8], } + + pub(crate) enum HandleImpl { + Fd(#[expect(dead_code)] RawFd), + } + + impl crate::GlobalStateWrapper { + pub(crate) fn crate_handle(&self, imp: HandleImpl) -> HANDLE { + let mut state = self.state.lock().unwrap(); + let handle = state.next_handle_nr.fetch_add(1, Ordering::Relaxed); + assert!(state.handles.insert(handle, imp).is_none()); + handle + } + } } +pub(crate) use base_defs::HandleImpl; macro_rules! define_emulation_entry { ($($name:ident,)*) => { @@ -181,8 +198,8 @@ emulate!( mod api_ms_win_core_synch_l1_2_0 { fn InitializeCriticalSectionEx( lpCriticalSection: *mut (), - dwSpinCount: u32, - flags: u32, + dwSpinCount: DWORD, + flags: DWORD, ) -> bool { delegate(kernel32) } @@ -238,7 +255,7 @@ emulate!( emulate!( "api-ms-win-crt-runtime-l1-1-0.dll", mod api_ms_win_crt_runtime_l1_1_0 { - fn __p___argc() -> *const u32 { + fn __p___argc() -> *const DWORD { static ARGC: i32 = 1; (&raw const ARGC).cast() } @@ -275,7 +292,7 @@ emulate!( /// fn _initterm(_start: *const (), _end: *const ()) {} /// - fn _initterm_e(_start: *const (), _end: *const ()) -> u32 { + fn _initterm_e(_start: *const (), _end: *const ()) -> DWORD { 0 } fn _register_onexit_function() { @@ -339,9 +356,8 @@ emulate!( fn AcquireSRWLockShared() { todo!("AcquireSRWLockShared") } - fn AddVectoredExceptionHandler() { - todo!("AddVectoredExceptionHandler") - } + /// + fn AddVectoredExceptionHandler(_first: u64, _handler: *const ()) {} fn AssignProcessToJobObject() { todo!("AssignProcessToJobObject") } @@ -473,8 +489,8 @@ emulate!( todo!("FindNextFileW") } /// - fn FlsAlloc(_callback: extern "win64" fn()) -> u32 { - const FLS_OUT_OF_INDEXES: u32 = -1_i32 as u32; + fn FlsAlloc(_callback: extern "win64" fn()) -> DWORD { + const FLS_OUT_OF_INDEXES: DWORD = -1_i32; FLS_OUT_OF_INDEXES } fn FlsFree() { @@ -519,8 +535,9 @@ emulate!( fn GetComputerNameExW() { todo!("GetComputerNameExW") } - fn GetConsoleMode() { - todo!("GetConsoleMode") + /// + fn GetConsoleMode(_hConsoleHandle: HANDLE, _lpMode: *mut DWORD) -> bool { + true } fn GetConsoleOutputCP() { todo!("GetConsoleOutputCP") @@ -535,18 +552,19 @@ emulate!( todo!("GetCurrentProcess") } /// - fn GetCurrentProcessId() -> u32 { - std::process::id() + fn GetCurrentProcessId() -> DWORD { + std::process::id() as DWORD } - fn GetCurrentThread() { - todo!("GetCurrentThread") + /// + fn GetCurrentThread() -> *mut () { + std::ptr::dangling_mut() } // - fn GetCurrentThreadId() -> u32 { + fn GetCurrentThreadId() -> DWORD { use std::sync::atomic; - static THREAD_ID_COUNTER: atomic::AtomicU32 = atomic::AtomicU32::new(0); + static THREAD_ID_COUNTER: atomic::AtomicI32 = atomic::AtomicI32::new(0); std::thread_local! { - static THREAD_ID: u32 = THREAD_ID_COUNTER.fetch_add(1, atomic::Ordering::Relaxed); + static THREAD_ID: DWORD = THREAD_ID_COUNTER.fetch_add(1, atomic::Ordering::Relaxed); } THREAD_ID.with(|id| *id) @@ -587,8 +605,8 @@ emulate!( fn GetFullPathNameW() { todo!("GetFullPathNameW") } - fn GetLastError() -> u32 { - 1 + fn GetLastError() -> DWORD { + crate::THREAD_STATE.with(|state| (*state.state.borrow().teb).last_error_number) } fn GetLocaleInfoEx() { todo!("GetLocaleInfoEx") @@ -602,13 +620,15 @@ emulate!( fn GetModuleFileNameW() { todo!("GetModuleFileNameW") } - fn GetModuleHandleA() { - todo!("GetModuleHandleA") + fn GetModuleHandleA() -> HANDLE { + tracing::error!("TODO GetModuleHandleW"); + 0 } - fn GetModuleHandleExW() { - todo!("GetModuleHandleExW") + fn GetModuleHandleExW() -> HANDLE { + tracing::error!("TODO GetModuleHandleW"); + 0 } - fn GetModuleHandleW() -> u64 { + fn GetModuleHandleW() -> HANDLE { tracing::error!("TODO GetModuleHandleW"); 0 } @@ -634,8 +654,9 @@ emulate!( // TODO: error handling... crate::va_for_dll_export_by_name(&dll, lpProcName.as_cstr(), 0) } - fn GetProcessHeap() { - todo!("GetProcessHeap") + /// + fn GetProcessHeap() -> HANDLE { + 1 } fn GetProcessId() { todo!("GetProcessId") @@ -646,8 +667,20 @@ emulate!( fn GetStartupInfoW() { todo!("GetStartupInfoW") } - fn GetStdHandle() { - todo!("GetStdHandle") + /// + fn GetStdHandle(nStdHandle: DWORD) -> HANDLE { + const STD_INPUT_HANDLE: DWORD = -10; + const STD_OUTPUT_HANDLE: DWORD = -11; + const STD_ERROR_HANDLE: DWORD = -12; + + let fd = match nStdHandle { + STD_INPUT_HANDLE => 0, + STD_OUTPUT_HANDLE => 1, + STD_ERROR_HANDLE => 2, + _ => panic!("invalid std handle: {nStdHandle}"), + }; + + crate::GLOBAL_STATE.crate_handle(HandleImpl::Fd(fd)) } fn GetStringTypeW() { todo!("GetStringTypeW") @@ -665,8 +698,8 @@ emulate!( fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *mut std::ffi::c_void) { #[repr(C)] struct _FILETIME { - dwLowDateTime: u32, - dwHighDateTime: u32, + dwLowDateTime: DWORD, + dwHighDateTime: DWORD, } lpSystemTimeAsFileTime.cast::<_FILETIME>().write(_FILETIME { dwLowDateTime: 0, @@ -694,8 +727,23 @@ emulate!( fn GetWindowsDirectoryW() { todo!("GetWindowsDirectoryW") } - fn HeapAlloc() { - todo!("HeapAlloc") + /// + fn HeapAlloc(heap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> *mut u8 { + const HEAP_GENERATE_EXCEPTIONS: DWORD = 0x00000004; + const HEAP_ZERO_MEMORY: DWORD = 0x00000008; + assert_eq!(heap, 1); + + let layout = std::alloc::Layout::from_size_align(dwBytes as usize, 8).unwrap(); + + let result = if (dwFlags & HEAP_ZERO_MEMORY) == 1 { + std::alloc::alloc_zeroed(layout) + } else { + std::alloc::alloc(layout) + }; + if (dwFlags & HEAP_GENERATE_EXCEPTIONS) == 1 && result.is_null() { + panic!("throw exception lol"); + } + result } fn HeapFree() { todo!("HeapFree") @@ -729,8 +777,8 @@ emulate!( } fn InitializeCriticalSectionEx( lpCriticalSection: *mut (), - _dwSpinCount: u32, - _flags: u32, + _dwSpinCount: DWORD, + _flags: DWORD, ) -> bool { lpCriticalSection .cast::() @@ -755,7 +803,7 @@ emulate!( false } /// - fn IsProcessorFeaturePresent(_ProcessorFeature: u32) -> bool { + fn IsProcessorFeaturePresent(_ProcessorFeature: DWORD) -> bool { false } fn IsThreadAFiber() { @@ -789,7 +837,7 @@ emulate!( todo!("LoadLibraryExA") } /// - fn LoadLibraryExW(lpLibFileName: LPCWSTR, _hFile: HANDLE, _dwFlags: u32) -> u64 { + fn LoadLibraryExW(lpLibFileName: LPCWSTR, _hFile: HANDLE, _dwFlags: DWORD) -> u64 { let result = crate::load_dll( &format!("{}.dll", &lpLibFileName.to_string()), &crate::GLOBAL_STATE.executable_path(), @@ -814,6 +862,7 @@ emulate!( fn MoveFileExW() { todo!("MoveFileExW") } + /// fn MultiByteToWideChar() { todo!("MultiByteToWideChar") } @@ -924,8 +973,10 @@ emulate!( fn SetInformationJobObject() { todo!("SetInformationJobObject") } - fn SetLastError() { - todo!("SetLastError") + /// + fn SetLastError(dw_err_code: DWORD) { + crate::THREAD_STATE + .with(|state| (*state.state.borrow_mut().teb).last_error_number = dw_err_code); } fn SetProcessAffinityMask() { todo!("SetProcessAffinityMask") @@ -936,9 +987,8 @@ emulate!( fn SetThreadErrorMode() { todo!("SetThreadErrorMode") } - fn SetThreadStackGuarantee() { - todo!("SetThreadStackGuarantee") - } + /// + fn SetThreadStackGuarantee(_stack_size_in_bytes: *mut u64) {} /// fn SetUnhandledExceptionFilter(_lpTopLevelExceptionFilter: *mut ()) -> *mut () { std::ptr::null_mut() diff --git a/src/lib.rs b/src/lib.rs index 4001afc..a556ade 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ use std::{ path::{Path, PathBuf}, ptr, sync::{ - atomic::{AtomicU64, Ordering}, + atomic::{AtomicU64, AtomicUsize, Ordering}, LazyLock, Mutex, }, }; @@ -293,6 +293,8 @@ pub fn execute(pe: &[u8], executable_path: &Path) { client_id_unique_thread: 0, active_rpc_handle: ptr::null(), thread_local_storage_pointer: &raw mut main_tls_slots, + peb: ptr::null(), + last_error_number: 0, }; main_teb.tib.this = &raw const main_teb; @@ -386,6 +388,8 @@ struct TheGlobalState { hmodule_to_dll: HashMap, next_emulated_hmodule_idx: AtomicU64, tls_slots: Vec, + handles: HashMap, + next_handle_nr: AtomicUsize, } enum TlsSlot { @@ -436,6 +440,8 @@ static GLOBAL_STATE: GlobalStateWrapper = GlobalStateWrapper { hmodule_to_dll: HashMap::new(), next_emulated_hmodule_idx: AtomicU64::new(1), tls_slots: Vec::new(), + handles: HashMap::new(), + next_handle_nr: AtomicUsize::new(1), }) }), }; @@ -460,6 +466,8 @@ struct ThreadEnvironmentBlock { client_id_unique_thread: u64, // handle, active_rpc_handle: *const (), thread_local_storage_pointer: *mut [*mut (); 64], + peb: *const (), + last_error_number: i32, } const _: [(); 88] = [(); std::mem::offset_of!(ThreadEnvironmentBlock, thread_local_storage_pointer)];