emulation

This commit is contained in:
nora 2025-02-01 22:28:37 +01:00
parent e8ba83c443
commit 8c23716f8f
3 changed files with 250 additions and 156 deletions

View file

@ -1,4 +1,9 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
mod base_defs { mod base_defs {
use std::{ffi::CStr, fmt::Debug};
pub(crate) type HANDLE = usize; pub(crate) type HANDLE = usize;
#[repr(transparent)] #[repr(transparent)]
@ -23,6 +28,25 @@ mod base_defs {
f.write_str(&self.to_string()) f.write_str(&self.to_string())
} }
} }
#[repr(transparent)]
pub(crate) struct LPCSTR(pub *const std::ffi::c_char);
impl LPCSTR {
pub(crate) fn as_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0) }
}
}
impl std::fmt::Debug for LPCSTR {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(self.as_cstr(), f)
}
}
#[repr(C)]
pub(super) struct CRITICAL_SECTION {
pub(super) mutex: std::sync::atomic::AtomicU64,
pub(super) pad: [u8; 40 - 8],
}
} }
macro_rules! define_emulation_entry { macro_rules! define_emulation_entry {
@ -56,6 +80,16 @@ define_emulation_entry!(
ws2_32, ws2_32,
); );
macro_rules! make_body {
($name:ident $($argname:ident),* @ delegate($dll:ident)) => {
crate::emulated::$dll::$name($($argname),*)
};
($name:ident $($argname:ident),* @ $($body:tt)*) => {
#[allow(unused_unsafe)]
unsafe { $($body)* }
};
}
macro_rules! emulate { macro_rules! emulate {
($dllname:literal, mod $modname:ident { ($dllname:literal, mod $modname:ident {
$( $(
@ -79,7 +113,7 @@ macro_rules! emulate {
if function_name == stringify!($name) { if function_name == stringify!($name) {
unsafe { unsafe {
// NOTE: The ABI string is a lie..... // NOTE: The ABI string is a lie.....
return Some(std::mem::transmute($name::trampoline as unsafe extern "C" fn($($argty),*))); return Some(std::mem::transmute($name as unsafe extern "win64" fn($($argty),*) $(-> $ret)?));
} }
} }
)* )*
@ -87,43 +121,13 @@ macro_rules! emulate {
None None
} }
$(
#[allow(non_snake_case)]
mod $name {
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::emulated::base_defs::*; use crate::emulated::base_defs::*;
// https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions $(
cfg_if::cfg_if! {
if #[cfg(windows)] {
pub(super) unsafe extern "C" fn trampoline($($argname: $argty)*) {
unsafe { inner($($argname),*) }
}
} else if #[cfg(all(target_os = "linux", target_arch = "x86_64"))] {
#[naked_function::naked]
#[export_name = concat!("portability_callconv_trampoline_", stringify!($modname), "__", stringify!($name))]
pub(super) unsafe extern "C" fn trampoline($($argname: $argty),*) {
// Map Windows arguments to System V arguments.
// For now we only support 4 integer arguments.
asm!(
"mov rdi, rcx", // arg 1
"mov rsi, rdx", // arg 2
"mov rdx, r8", // arg 3
"mov rcx, r9", // arg 4
"jmp {}",
sym inner,
);
}
} else {
compile_error!("unsupported architecture or operating system");
}
}
$(#[$attr])* $(#[$attr])*
unsafe extern "C" fn inner($($argname: $argty),*) $(-> $ret)? { pub(super) unsafe extern "win64" fn $name($($argname: $argty),*) $(-> $ret)? {
#[allow(unused_unsafe)] make_body! { $name $($argname),* @ $($body)* }
unsafe { $($body)* }
}
} }
)* )*
} }
@ -165,9 +169,17 @@ emulate!(
} }
} }
); );
emulate!( emulate!(
"api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-synch-l1-2-0.dll",
mod api_ms_win_core_synch_l1_2_0 { mod api_ms_win_core_synch_l1_2_0 {
fn InitializeCriticalSectionEx(
lpCriticalSection: *mut (),
dwSpinCount: u32,
flags: u32,
) -> bool {
delegate(kernel32)
}
fn WaitOnAddress() { fn WaitOnAddress() {
todo!("WaitOnAddress") todo!("WaitOnAddress")
} }
@ -293,9 +305,8 @@ emulate!(
fn DecodePointer() { fn DecodePointer() {
todo!("DecodePointer") todo!("DecodePointer")
} }
fn DeleteCriticalSection() { /// <https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-deletecriticalsection>
todo!("DeleteCriticalSection") fn DeleteCriticalSection(_lpCriticalSection: *mut ()) {}
}
fn DeleteFiber() { fn DeleteFiber() {
todo!("DeleteFiber") todo!("DeleteFiber")
} }
@ -314,8 +325,19 @@ emulate!(
fn EncodePointer() { fn EncodePointer() {
todo!("EncodePointer") todo!("EncodePointer")
} }
fn EnterCriticalSection() { /// <https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-entercriticalsection>
todo!("EnterCriticalSection") fn EnterCriticalSection(lpCriticalSection: *mut CRITICAL_SECTION) {
// a shitty spinlock
while (&*lpCriticalSection)
.mutex
.compare_exchange_weak(
0,
1,
std::sync::atomic::Ordering::Acquire,
std::sync::atomic::Ordering::Relaxed,
)
.is_err()
{}
} }
fn EnumSystemLocalesW() { fn EnumSystemLocalesW() {
todo!("EnumSystemLocalesW") todo!("EnumSystemLocalesW")
@ -335,8 +357,10 @@ emulate!(
fn FindNextFileW() { fn FindNextFileW() {
todo!("FindNextFileW") todo!("FindNextFileW")
} }
fn FlsAlloc() { /// <https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsalloc>
todo!("FlsAlloc") fn FlsAlloc(_callback: extern "win64" fn()) -> u32 {
const FLS_OUT_OF_INDEXES: u32 = -1_i32 as u32;
FLS_OUT_OF_INDEXES
} }
fn FlsFree() { fn FlsFree() {
todo!("FlsFree") todo!("FlsFree")
@ -448,8 +472,8 @@ emulate!(
fn GetFullPathNameW() { fn GetFullPathNameW() {
todo!("GetFullPathNameW") todo!("GetFullPathNameW")
} }
fn GetLastError() { fn GetLastError() -> u32 {
todo!("GetLastError") 1
} }
fn GetLocaleInfoEx() { fn GetLocaleInfoEx() {
todo!("GetLocaleInfoEx") todo!("GetLocaleInfoEx")
@ -469,8 +493,9 @@ emulate!(
fn GetModuleHandleExW() { fn GetModuleHandleExW() {
todo!("GetModuleHandleExW") todo!("GetModuleHandleExW")
} }
fn GetModuleHandleW() { fn GetModuleHandleW() -> u64 {
todo!("GetModuleHandleW") tracing::error!("TODO GetModuleHandleW");
0
} }
fn GetNativeSystemInfo() { fn GetNativeSystemInfo() {
todo!("GetNativeSystemInfo") todo!("GetNativeSystemInfo")
@ -482,8 +507,17 @@ emulate!(
todo!("GetOverlappedResult") todo!("GetOverlappedResult")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress> /// <https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress>
fn GetProcAddress(hModule: u64, lpProcName: LPCWSTR) { fn GetProcAddress(hModule: u64, lpProcName: LPCSTR) -> usize {
todo!("GetProcAddress: {lpProcName:?}") let dll = crate::GLOBAL_STATE
.state
.lock()
.unwrap()
.hmodule_to_dll
.get(&hModule)
.cloned()
.unwrap();
// TODO: error handling...
crate::va_for_dll_export_by_name(&dll, lpProcName.as_cstr(), 0)
} }
fn GetProcessHeap() { fn GetProcessHeap() {
todo!("GetProcessHeap") todo!("GetProcessHeap")
@ -578,8 +612,19 @@ emulate!(
fn InitializeCriticalSectionAndSpinCount() { fn InitializeCriticalSectionAndSpinCount() {
todo!("InitializeCriticalSectionAndSpinCount") todo!("InitializeCriticalSectionAndSpinCount")
} }
fn InitializeCriticalSectionEx() { fn InitializeCriticalSectionEx(
todo!("InitializeCriticalSectionEx") lpCriticalSection: *mut (),
_dwSpinCount: u32,
_flags: u32,
) -> bool {
lpCriticalSection
.cast::<CRITICAL_SECTION>()
.write(CRITICAL_SECTION {
mutex: Default::default(),
pad: Default::default(),
});
const _: () = assert!(size_of::<CRITICAL_SECTION>() == 40);
true
} }
fn InitializeProcThreadAttributeList() { fn InitializeProcThreadAttributeList() {
todo!("InitializeProcThreadAttributeList") todo!("InitializeProcThreadAttributeList")
@ -590,11 +635,13 @@ emulate!(
fn InterlockedFlushSList() { fn InterlockedFlushSList() {
todo!("InterlockedFlushSList") todo!("InterlockedFlushSList")
} }
fn IsDebuggerPresent() { /// <https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent>
todo!("IsDebuggerPresent") fn IsDebuggerPresent() -> bool {
false
} }
fn IsProcessorFeaturePresent() { /// <https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent>
todo!("IsProcessorFeaturePresent") fn IsProcessorFeaturePresent(_ProcessorFeature: u32) -> bool {
false
} }
fn IsThreadAFiber() { fn IsThreadAFiber() {
todo!("IsThreadAFiber") todo!("IsThreadAFiber")
@ -633,8 +680,8 @@ emulate!(
&crate::GLOBAL_STATE.executable_path(), &crate::GLOBAL_STATE.executable_path(),
); );
match result { match result {
crate::LoadedDll::Emulated => 1, Some(result) => result.hmodule(),
crate::LoadedDll::Real(img, _, _) => img.base as u64, None => 0,
} }
} }
fn LoadLibraryW() { fn LoadLibraryW() {
@ -762,8 +809,9 @@ emulate!(
fn SetThreadStackGuarantee() { fn SetThreadStackGuarantee() {
todo!("SetThreadStackGuarantee") todo!("SetThreadStackGuarantee")
} }
fn SetUnhandledExceptionFilter() { /// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter>
todo!("SetUnhandledExceptionFilter") fn SetUnhandledExceptionFilter(_lpTopLevelExceptionFilter: *mut ()) -> *mut () {
std::ptr::null_mut()
} }
fn SetWaitableTimer() { fn SetWaitableTimer() {
todo!("SetWaitableTimer") todo!("SetWaitableTimer")
@ -804,8 +852,10 @@ emulate!(
fn TryAcquireSRWLockExclusive() { fn TryAcquireSRWLockExclusive() {
todo!("TryAcquireSRWLockExclusive") todo!("TryAcquireSRWLockExclusive")
} }
fn UnhandledExceptionFilter() { /// <https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-unhandledexceptionfilter>
todo!("UnhandledExceptionFilter") fn UnhandledExceptionFilter(_ExceptionInfo: *const ()) -> u64 {
const EXCEPTION_CONTINUE_SEARCH: u64 = 0x0;
EXCEPTION_CONTINUE_SEARCH
} }
fn UnlockFile() { fn UnlockFile() {
todo!("UnlockFile") todo!("UnlockFile")
@ -866,14 +916,20 @@ emulate!(
fn NtWriteFile() { fn NtWriteFile() {
todo!("NtWriteFile") todo!("NtWriteFile")
} }
/// <https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlcapturecontext>
fn RtlCaptureContext() { fn RtlCaptureContext() {
todo!("RtlCaptureContext") tracing::error!("TODO: RtlCaptureContext - looks like someone feels like crashing...")
} }
fn RtlGetLastNtStatus() { fn RtlGetLastNtStatus() {
todo!("RtlGetLastNtStatus") todo!("RtlGetLastNtStatus")
} }
fn RtlLookupFunctionEntry() { /// <https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtllookupfunctionentry>
todo!("RtlLookupFunctionEntry") fn RtlLookupFunctionEntry(
_ControlPc: u64,
_ImageBase: *mut (),
_HistoryTable: *mut (),
) -> *const () {
std::ptr::null()
} }
fn RtlNtStatusToDosError() { fn RtlNtStatusToDosError() {
todo!("RtlNtStatusToDosError") todo!("RtlNtStatusToDosError")

View file

@ -2,11 +2,15 @@ mod emulated;
mod sys; mod sys;
use std::{ use std::{
collections::HashMap,
ffi::{CStr, CString}, ffi::{CStr, CString},
fmt::Debug, fmt::Debug,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Mutex, sync::{
atomic::{AtomicU64, Ordering},
LazyLock, Mutex,
},
}; };
#[derive(Clone, Copy, Debug, bytemuck::Zeroable, bytemuck::Pod)] #[derive(Clone, Copy, Debug, bytemuck::Zeroable, bytemuck::Pod)]
@ -252,7 +256,9 @@ pub fn execute(pe: &[u8], executable_path: &Path) {
tracing::debug!("YOLO to {:#x}", entrypoint); tracing::debug!("YOLO to {:#x}", entrypoint);
unsafe { unsafe {
let result = sys::call_entrypoint_via_stdcall(entrypoint); let entrypoint =
std::mem::transmute::<usize, unsafe extern "win64" fn() -> u32>(entrypoint);
let result = entrypoint();
tracing::info!("result: {result}"); tracing::info!("result: {result}");
}; };
} }
@ -280,29 +286,59 @@ impl<'pe> DerefMut for Image<'pe> {
#[derive(Clone)] #[derive(Clone)]
enum LoadedDll { enum LoadedDll {
Emulated, Emulated {
Real(Image<'static>, ExportDirectoryTable, Vec<CString>), name: String,
hmodule: u64,
},
Real {
name: String,
img: Image<'static>,
edt: ExportDirectoryTable,
export_names: Vec<CString>,
},
}
impl LoadedDll {
fn hmodule(&self) -> u64 {
match self {
Self::Emulated { hmodule, .. } => *hmodule,
Self::Real { img, .. } => img.base as u64,
}
}
} }
struct TheGlobalState { struct TheGlobalState {
loaded_libraries: Vec<(String, LoadedDll)>, loaded_libraries: Vec<(String, LoadedDll)>,
executable_path: Option<PathBuf>, executable_path: Option<PathBuf>,
hmodule_to_dll: HashMap<u64, LoadedDll>,
next_emulated_hmodule_idx: AtomicU64,
} }
struct GlobalStateWrapper { struct GlobalStateWrapper {
state: Mutex<TheGlobalState>, state: std::sync::LazyLock<Mutex<TheGlobalState>>,
} }
impl GlobalStateWrapper { impl GlobalStateWrapper {
fn executable_path(&self) -> PathBuf { fn executable_path(&self) -> PathBuf {
self.state.lock().unwrap().executable_path.clone().unwrap() self.state.lock().unwrap().executable_path.clone().unwrap()
} }
fn get_emulated_hmodule_idx(&self) -> u64 {
self.state
.lock()
.unwrap()
.next_emulated_hmodule_idx
.fetch_add(1, Ordering::Relaxed)
}
} }
static GLOBAL_STATE: GlobalStateWrapper = GlobalStateWrapper { static GLOBAL_STATE: GlobalStateWrapper = GlobalStateWrapper {
state: Mutex::new(TheGlobalState { state: LazyLock::new(|| {
Mutex::new(TheGlobalState {
loaded_libraries: Vec::new(), loaded_libraries: Vec::new(),
executable_path: None, executable_path: None,
hmodule_to_dll: HashMap::new(),
next_emulated_hmodule_idx: AtomicU64::new(1),
})
}), }),
}; };
@ -465,7 +501,8 @@ fn load_inner<'pe>(pe: &'pe [u8], executable_path: &Path, is_dll: bool) -> Image
break; break;
} }
let dll = load_dll(dll_name, executable_path); let dll = load_dll(dll_name, executable_path)
.unwrap_or_else(|| panic!("could not find dll {dll_name}"));
let import_lookups = bytemuck::cast_slice::<u8, u64>( let import_lookups = bytemuck::cast_slice::<u8, u64>(
&image[import_directory.import_address_table_rva as usize..], &image[import_directory.import_address_table_rva as usize..],
@ -477,36 +514,21 @@ fn load_inner<'pe>(pe: &'pe [u8], executable_path: &Path, is_dll: bool) -> Image
break; break;
} }
fn compute_export_rva(
export_directory_table: &ExportDirectoryTable,
unbiased_ordinal: usize,
img: &Image<'_>,
) -> usize {
let eat_addr_rva = export_directory_table.export_address_table_rva as usize
+ (unbiased_ordinal * 4);
let export_rva = u32::from_ne_bytes(img[eat_addr_rva..][..4].try_into().unwrap());
if (img.opt_header.export_table.rva
..(img.opt_header.export_table.rva + img.opt_header.export_table.size))
.contains(&export_rva)
{
todo!("symbol forwarding")
}
export_rva as usize
}
let ordinal_name_flag = import_lookup >> 63; let ordinal_name_flag = import_lookup >> 63;
let resolved_va = if ordinal_name_flag == 1 { let resolved_va = if ordinal_name_flag == 1 {
let ordinal_number = import_lookup & 0xFFFF; let ordinal_number = import_lookup & 0xFFFF;
tracing::debug!("import by ordinal: {ordinal_number}"); tracing::debug!("import by ordinal: {ordinal_number}");
match &dll { match &dll {
LoadedDll::Emulated => { LoadedDll::Emulated { .. } => {
tracing::error!("unsupported: emulated import via ordinal for {dll_name}. resolving them to 0"); tracing::error!("unsupported: emulated import via ordinal for {dll_name}. resolving them to 0");
0 0
} }
LoadedDll::Real(img, export_directory_table, _) => { LoadedDll::Real {
img,
edt: export_directory_table,
..
} => {
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#export-ordinal-table // https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#export-ordinal-table
let unbiased_ordinal = let unbiased_ordinal =
ordinal_number as usize - export_directory_table.ordinal_base as usize; ordinal_number as usize - export_directory_table.ordinal_base as usize;
@ -528,37 +550,7 @@ fn load_inner<'pe>(pe: &'pe [u8], executable_path: &Path, is_dll: bool) -> Image
CStr::from_bytes_until_nul(&image[hint_name_table_rva as usize + 2..]).unwrap(); CStr::from_bytes_until_nul(&image[hint_name_table_rva as usize + 2..]).unwrap();
tracing::debug!("import by name: hint={hint} name={func_name:?}"); tracing::debug!("import by name: hint={hint} name={func_name:?}");
match &dll { va_for_dll_export_by_name(&dll, func_name, hint as usize)
LoadedDll::Emulated => emulated::emulate(dll_name, func_name.to_str().unwrap())
.unwrap_or_else(|| {
panic!("could not find function {func_name:?} in dll {dll_name:?}");
}),
LoadedDll::Real(img, export_directory_table, names) => {
let idx =
if names.get(hint as usize) == Some(&func_name.to_owned()) {
hint as usize
} else {
names.binary_search(&func_name.to_owned()).unwrap_or_else(|_| {
panic!("could not find function {func_name:?} in dll {dll_name}")
})
};
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#export-ordinal-table
let ordinal_table = bytemuck::cast_slice::<u8, u16>(
&img[export_directory_table.ordinal_table_rva as usize..]
[..2 * export_directory_table.number_of_name_pointers as usize],
);
let unbiased_ordinal = ordinal_table[idx];
let export_rva = compute_export_rva(
export_directory_table,
unbiased_ordinal as usize,
img,
);
img.base + export_rva as usize
}
}
}; };
assert_eq!(size_of::<usize>(), size_of::<u64>()); assert_eq!(size_of::<usize>(), size_of::<u64>());
@ -597,7 +589,63 @@ fn load_inner<'pe>(pe: &'pe [u8], executable_path: &Path, is_dll: bool) -> Image
image image
} }
fn load_dll(dll_name: &str, executable_path: &Path) -> LoadedDll { fn va_for_dll_export_by_name(dll: &LoadedDll, func_name: &CStr, hint: usize) -> usize {
match &dll {
LoadedDll::Emulated { name, .. } => emulated::emulate(name, func_name.to_str().unwrap())
.unwrap_or_else(|| {
panic!("could not find function {func_name:?} in dll {name:?}");
}),
LoadedDll::Real {
name,
img,
edt: export_directory_table,
export_names: names,
} => {
let idx = if names.get(hint) == Some(&func_name.to_owned()) {
hint as usize
} else {
names
.binary_search(&func_name.to_owned())
.unwrap_or_else(|_| {
panic!("could not find function {func_name:?} in dll {name}")
})
};
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#export-ordinal-table
let ordinal_table = bytemuck::cast_slice::<u8, u16>(
&img[export_directory_table.ordinal_table_rva as usize..]
[..2 * export_directory_table.number_of_name_pointers as usize],
);
let unbiased_ordinal = ordinal_table[idx];
let export_rva =
compute_export_rva(export_directory_table, unbiased_ordinal as usize, img);
img.base + export_rva as usize
}
}
}
fn compute_export_rva(
export_directory_table: &ExportDirectoryTable,
unbiased_ordinal: usize,
img: &Image<'_>,
) -> usize {
let eat_addr_rva =
export_directory_table.export_address_table_rva as usize + (unbiased_ordinal * 4);
let export_rva = u32::from_ne_bytes(img[eat_addr_rva..][..4].try_into().unwrap());
if (img.opt_header.export_table.rva
..(img.opt_header.export_table.rva + img.opt_header.export_table.size))
.contains(&export_rva)
{
todo!("symbol forwarding")
}
export_rva as usize
}
fn load_dll(dll_name: &str, executable_path: &Path) -> Option<LoadedDll> {
tracing::debug!("loading dll {dll_name}"); tracing::debug!("loading dll {dll_name}");
let already_loaded = GLOBAL_STATE let already_loaded = GLOBAL_STATE
@ -609,14 +657,17 @@ fn load_dll(dll_name: &str, executable_path: &Path) -> LoadedDll {
.find(|(name, _)| name == dll_name) .find(|(name, _)| name == dll_name)
.map(Clone::clone); .map(Clone::clone);
if let Some((_, already_loaded)) = already_loaded { if let Some((_, already_loaded)) = already_loaded {
return already_loaded; return Some(already_loaded);
} }
let dll = find_dll(&dll_name, executable_path); let dll = find_dll(&dll_name, executable_path);
let dll = match dll { let dll = match dll {
Some(DllLocation::Emulated) => { Some(DllLocation::Emulated) => {
tracing::debug!("emulating {dll_name:?}"); tracing::debug!("emulating {dll_name:?}");
LoadedDll::Emulated LoadedDll::Emulated {
name: dll_name.to_owned(),
hmodule: GLOBAL_STATE.get_emulated_hmodule_idx(),
}
} }
Some(DllLocation::Found(path)) => { Some(DllLocation::Found(path)) => {
let file = std::fs::File::open(&path).unwrap(); let file = std::fs::File::open(&path).unwrap();
@ -659,10 +710,15 @@ fn load_dll(dll_name: &str, executable_path: &Path) -> LoadedDll {
tracing::trace!(?name, "DLL {dll_name} has export"); tracing::trace!(?name, "DLL {dll_name} has export");
} }
LoadedDll::Real(img, export_directory_table, names) LoadedDll::Real {
name: dll_name.to_owned(),
img,
edt: export_directory_table,
export_names: names,
}
} }
None => { None => {
panic!("could not find dll {dll_name:?}"); return None;
} }
}; };
@ -672,8 +728,14 @@ fn load_dll(dll_name: &str, executable_path: &Path) -> LoadedDll {
.unwrap() .unwrap()
.loaded_libraries .loaded_libraries
.push((dll_name.to_owned(), dll.clone())); .push((dll_name.to_owned(), dll.clone()));
GLOBAL_STATE
.state
.lock()
.unwrap()
.hmodule_to_dll
.insert(dll.hmodule(), dll.clone());
dll Some(dll)
} }
fn parse_header(pe: &[u8]) -> (&CoffHeader, usize) { fn parse_header(pe: &[u8]) -> (&CoffHeader, usize) {

View file

@ -56,11 +56,6 @@ mod imp {
.map_err(Into::into) .map_err(Into::into)
} }
} }
pub(crate) unsafe fn call_entrypoint_via_stdcall(fnptr: *const ()) -> u32 {
let fnptr = unsafe { std::mem::transmute::<_, unsafe extern "stdcall" fn() -> u32>(fnptr) };
unsafe { fnptr() }
}
} }
#[cfg(unix)] #[cfg(unix)]
@ -91,25 +86,6 @@ mod imp {
Err(io::Error::last_os_error()) Err(io::Error::last_os_error())
} }
} }
pub(crate) unsafe fn call_entrypoint_via_stdcall(fnptr: usize) -> u32 {
let mut out: u32;
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
std::arch::asm!(
"call {}",
"mov {1:e}, eax",
in(reg) fnptr,
out(reg) out,
);
} else {
compile_error!("unsupported architecture");
}
}
out
}
} }
pub(crate) use imp::*; pub(crate) use imp::*;