This commit is contained in:
nora 2025-02-09 21:11:02 +01:00
parent a6de0298f2
commit 559186088f
2 changed files with 102 additions and 44 deletions

View file

@ -2,7 +2,10 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
mod base_defs { 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; pub(crate) type HANDLE = usize;
@ -47,8 +50,22 @@ mod base_defs {
pub(super) mutex: std::sync::atomic::AtomicU64, pub(super) mutex: std::sync::atomic::AtomicU64,
pub(super) pad: [u8; 40 - 8], 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 { macro_rules! define_emulation_entry {
($($name:ident,)*) => { ($($name:ident,)*) => {
pub(crate) fn supports_dll(dll_name: &str) -> bool { pub(crate) fn supports_dll(dll_name: &str) -> bool {
@ -181,8 +198,8 @@ emulate!(
mod api_ms_win_core_synch_l1_2_0 { mod api_ms_win_core_synch_l1_2_0 {
fn InitializeCriticalSectionEx( fn InitializeCriticalSectionEx(
lpCriticalSection: *mut (), lpCriticalSection: *mut (),
dwSpinCount: u32, dwSpinCount: DWORD,
flags: u32, flags: DWORD,
) -> bool { ) -> bool {
delegate(kernel32) delegate(kernel32)
} }
@ -238,7 +255,7 @@ emulate!(
emulate!( emulate!(
"api-ms-win-crt-runtime-l1-1-0.dll", "api-ms-win-crt-runtime-l1-1-0.dll",
mod api_ms_win_crt_runtime_l1_1_0 { mod api_ms_win_crt_runtime_l1_1_0 {
fn __p___argc() -> *const u32 { fn __p___argc() -> *const DWORD {
static ARGC: i32 = 1; static ARGC: i32 = 1;
(&raw const ARGC).cast() (&raw const ARGC).cast()
} }
@ -275,7 +292,7 @@ emulate!(
/// <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/initterm-initterm-e?view=msvc-170> /// <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/initterm-initterm-e?view=msvc-170>
fn _initterm(_start: *const (), _end: *const ()) {} fn _initterm(_start: *const (), _end: *const ()) {}
/// <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/initterm-initterm-e?view=msvc-170> /// <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/initterm-initterm-e?view=msvc-170>
fn _initterm_e(_start: *const (), _end: *const ()) -> u32 { fn _initterm_e(_start: *const (), _end: *const ()) -> DWORD {
0 0
} }
fn _register_onexit_function() { fn _register_onexit_function() {
@ -339,9 +356,8 @@ emulate!(
fn AcquireSRWLockShared() { fn AcquireSRWLockShared() {
todo!("AcquireSRWLockShared") todo!("AcquireSRWLockShared")
} }
fn AddVectoredExceptionHandler() { /// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-addvectoredexceptionhandler>
todo!("AddVectoredExceptionHandler") fn AddVectoredExceptionHandler(_first: u64, _handler: *const ()) {}
}
fn AssignProcessToJobObject() { fn AssignProcessToJobObject() {
todo!("AssignProcessToJobObject") todo!("AssignProcessToJobObject")
} }
@ -473,8 +489,8 @@ emulate!(
todo!("FindNextFileW") todo!("FindNextFileW")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsalloc> /// <https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsalloc>
fn FlsAlloc(_callback: extern "win64" fn()) -> u32 { fn FlsAlloc(_callback: extern "win64" fn()) -> DWORD {
const FLS_OUT_OF_INDEXES: u32 = -1_i32 as u32; const FLS_OUT_OF_INDEXES: DWORD = -1_i32;
FLS_OUT_OF_INDEXES FLS_OUT_OF_INDEXES
} }
fn FlsFree() { fn FlsFree() {
@ -519,8 +535,9 @@ emulate!(
fn GetComputerNameExW() { fn GetComputerNameExW() {
todo!("GetComputerNameExW") todo!("GetComputerNameExW")
} }
fn GetConsoleMode() { /// <https://learn.microsoft.com/en-us/windows/console/getconsolemode>
todo!("GetConsoleMode") fn GetConsoleMode(_hConsoleHandle: HANDLE, _lpMode: *mut DWORD) -> bool {
true
} }
fn GetConsoleOutputCP() { fn GetConsoleOutputCP() {
todo!("GetConsoleOutputCP") todo!("GetConsoleOutputCP")
@ -535,18 +552,19 @@ emulate!(
todo!("GetCurrentProcess") todo!("GetCurrentProcess")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid> /// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid>
fn GetCurrentProcessId() -> u32 { fn GetCurrentProcessId() -> DWORD {
std::process::id() std::process::id() as DWORD
} }
fn GetCurrentThread() { /// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthread>
todo!("GetCurrentThread") fn GetCurrentThread() -> *mut () {
std::ptr::dangling_mut()
} }
// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadid> // <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadid>
fn GetCurrentThreadId() -> u32 { fn GetCurrentThreadId() -> DWORD {
use std::sync::atomic; 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! { 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) THREAD_ID.with(|id| *id)
@ -587,8 +605,8 @@ emulate!(
fn GetFullPathNameW() { fn GetFullPathNameW() {
todo!("GetFullPathNameW") todo!("GetFullPathNameW")
} }
fn GetLastError() -> u32 { fn GetLastError() -> DWORD {
1 crate::THREAD_STATE.with(|state| (*state.state.borrow().teb).last_error_number)
} }
fn GetLocaleInfoEx() { fn GetLocaleInfoEx() {
todo!("GetLocaleInfoEx") todo!("GetLocaleInfoEx")
@ -602,13 +620,15 @@ emulate!(
fn GetModuleFileNameW() { fn GetModuleFileNameW() {
todo!("GetModuleFileNameW") todo!("GetModuleFileNameW")
} }
fn GetModuleHandleA() { fn GetModuleHandleA() -> HANDLE {
todo!("GetModuleHandleA") tracing::error!("TODO GetModuleHandleW");
0
} }
fn GetModuleHandleExW() { fn GetModuleHandleExW() -> HANDLE {
todo!("GetModuleHandleExW") tracing::error!("TODO GetModuleHandleW");
0
} }
fn GetModuleHandleW() -> u64 { fn GetModuleHandleW() -> HANDLE {
tracing::error!("TODO GetModuleHandleW"); tracing::error!("TODO GetModuleHandleW");
0 0
} }
@ -634,8 +654,9 @@ emulate!(
// TODO: error handling... // TODO: error handling...
crate::va_for_dll_export_by_name(&dll, lpProcName.as_cstr(), 0) crate::va_for_dll_export_by_name(&dll, lpProcName.as_cstr(), 0)
} }
fn GetProcessHeap() { /// <https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-getprocessheap>
todo!("GetProcessHeap") fn GetProcessHeap() -> HANDLE {
1
} }
fn GetProcessId() { fn GetProcessId() {
todo!("GetProcessId") todo!("GetProcessId")
@ -646,8 +667,20 @@ emulate!(
fn GetStartupInfoW() { fn GetStartupInfoW() {
todo!("GetStartupInfoW") todo!("GetStartupInfoW")
} }
fn GetStdHandle() { /// <https://learn.microsoft.com/en-us/windows/console/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() { fn GetStringTypeW() {
todo!("GetStringTypeW") todo!("GetStringTypeW")
@ -665,8 +698,8 @@ emulate!(
fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *mut std::ffi::c_void) { fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *mut std::ffi::c_void) {
#[repr(C)] #[repr(C)]
struct _FILETIME { struct _FILETIME {
dwLowDateTime: u32, dwLowDateTime: DWORD,
dwHighDateTime: u32, dwHighDateTime: DWORD,
} }
lpSystemTimeAsFileTime.cast::<_FILETIME>().write(_FILETIME { lpSystemTimeAsFileTime.cast::<_FILETIME>().write(_FILETIME {
dwLowDateTime: 0, dwLowDateTime: 0,
@ -694,8 +727,23 @@ emulate!(
fn GetWindowsDirectoryW() { fn GetWindowsDirectoryW() {
todo!("GetWindowsDirectoryW") todo!("GetWindowsDirectoryW")
} }
fn HeapAlloc() { /// <https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-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() { fn HeapFree() {
todo!("HeapFree") todo!("HeapFree")
@ -729,8 +777,8 @@ emulate!(
} }
fn InitializeCriticalSectionEx( fn InitializeCriticalSectionEx(
lpCriticalSection: *mut (), lpCriticalSection: *mut (),
_dwSpinCount: u32, _dwSpinCount: DWORD,
_flags: u32, _flags: DWORD,
) -> bool { ) -> bool {
lpCriticalSection lpCriticalSection
.cast::<CRITICAL_SECTION>() .cast::<CRITICAL_SECTION>()
@ -755,7 +803,7 @@ emulate!(
false false
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent> /// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent>
fn IsProcessorFeaturePresent(_ProcessorFeature: u32) -> bool { fn IsProcessorFeaturePresent(_ProcessorFeature: DWORD) -> bool {
false false
} }
fn IsThreadAFiber() { fn IsThreadAFiber() {
@ -789,7 +837,7 @@ emulate!(
todo!("LoadLibraryExA") todo!("LoadLibraryExA")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw> /// <https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw>
fn LoadLibraryExW(lpLibFileName: LPCWSTR, _hFile: HANDLE, _dwFlags: u32) -> u64 { fn LoadLibraryExW(lpLibFileName: LPCWSTR, _hFile: HANDLE, _dwFlags: DWORD) -> u64 {
let result = crate::load_dll( let result = crate::load_dll(
&format!("{}.dll", &lpLibFileName.to_string()), &format!("{}.dll", &lpLibFileName.to_string()),
&crate::GLOBAL_STATE.executable_path(), &crate::GLOBAL_STATE.executable_path(),
@ -814,6 +862,7 @@ emulate!(
fn MoveFileExW() { fn MoveFileExW() {
todo!("MoveFileExW") todo!("MoveFileExW")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar>
fn MultiByteToWideChar() { fn MultiByteToWideChar() {
todo!("MultiByteToWideChar") todo!("MultiByteToWideChar")
} }
@ -924,8 +973,10 @@ emulate!(
fn SetInformationJobObject() { fn SetInformationJobObject() {
todo!("SetInformationJobObject") todo!("SetInformationJobObject")
} }
fn SetLastError() { /// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-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() { fn SetProcessAffinityMask() {
todo!("SetProcessAffinityMask") todo!("SetProcessAffinityMask")
@ -936,9 +987,8 @@ emulate!(
fn SetThreadErrorMode() { fn SetThreadErrorMode() {
todo!("SetThreadErrorMode") todo!("SetThreadErrorMode")
} }
fn SetThreadStackGuarantee() { /// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadstackguarantee>
todo!("SetThreadStackGuarantee") fn SetThreadStackGuarantee(_stack_size_in_bytes: *mut u64) {}
}
/// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter> /// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter>
fn SetUnhandledExceptionFilter(_lpTopLevelExceptionFilter: *mut ()) -> *mut () { fn SetUnhandledExceptionFilter(_lpTopLevelExceptionFilter: *mut ()) -> *mut () {
std::ptr::null_mut() std::ptr::null_mut()

View file

@ -10,7 +10,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
ptr, ptr,
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, AtomicUsize, Ordering},
LazyLock, Mutex, LazyLock, Mutex,
}, },
}; };
@ -293,6 +293,8 @@ pub fn execute(pe: &[u8], executable_path: &Path) {
client_id_unique_thread: 0, client_id_unique_thread: 0,
active_rpc_handle: ptr::null(), active_rpc_handle: ptr::null(),
thread_local_storage_pointer: &raw mut main_tls_slots, thread_local_storage_pointer: &raw mut main_tls_slots,
peb: ptr::null(),
last_error_number: 0,
}; };
main_teb.tib.this = &raw const main_teb; main_teb.tib.this = &raw const main_teb;
@ -386,6 +388,8 @@ struct TheGlobalState {
hmodule_to_dll: HashMap<u64, LoadedDll>, hmodule_to_dll: HashMap<u64, LoadedDll>,
next_emulated_hmodule_idx: AtomicU64, next_emulated_hmodule_idx: AtomicU64,
tls_slots: Vec<TlsSlot>, tls_slots: Vec<TlsSlot>,
handles: HashMap<usize, emulated::HandleImpl>,
next_handle_nr: AtomicUsize,
} }
enum TlsSlot { enum TlsSlot {
@ -436,6 +440,8 @@ static GLOBAL_STATE: GlobalStateWrapper = GlobalStateWrapper {
hmodule_to_dll: HashMap::new(), hmodule_to_dll: HashMap::new(),
next_emulated_hmodule_idx: AtomicU64::new(1), next_emulated_hmodule_idx: AtomicU64::new(1),
tls_slots: Vec::new(), 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, client_id_unique_thread: u64, // handle,
active_rpc_handle: *const (), active_rpc_handle: *const (),
thread_local_storage_pointer: *mut [*mut (); 64], thread_local_storage_pointer: *mut [*mut (); 64],
peb: *const (),
last_error_number: i32,
} }
const _: [(); 88] = const _: [(); 88] =
[(); std::mem::offset_of!(ThreadEnvironmentBlock, thread_local_storage_pointer)]; [(); std::mem::offset_of!(ThreadEnvironmentBlock, thread_local_storage_pointer)];