Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push xuqqmwmwvlwo #79

Merged
merged 11 commits into from
Feb 2, 2025
2 changes: 1 addition & 1 deletion memory/src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl<'m> Mem<'m> {
}
}

/// Create a new Mem with arbitrary lifetime. Very unsafe, used in stack_args codegen.
/// Create a new Mem with arbitrary lifetime. Very unsafe, used in calling_convertion codegen.
pub unsafe fn detach<'a, 'b>(&'a self) -> Mem<'b> {
std::mem::transmute(*self)
}
Expand Down
8 changes: 4 additions & 4 deletions win32/derive/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ fn fn_wrapper(module: TokenStream, dllexport: &parse::DllExport) -> (TokenStream
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
};

let (func, defn) = if dllexport.func.sig.asyncness.is_some() {
(
quote!(Handler::Async(wrappers::#sym_name)),
quote! {
pub unsafe fn #sym_name(machine: &mut Machine, stack_args: u32) -> std::pin::Pin<Box<dyn std::future::Future<Output = u32>>> {
pub unsafe fn #sym_name(machine: &mut Machine, stack_args: u32) -> std::pin::Pin<Box<dyn std::future::Future<Output = u64>>> {
#fetch_args
let machine: *mut Machine = machine;
Box::pin(async move {
Expand All @@ -91,7 +91,7 @@ fn fn_wrapper(module: TokenStream, dllexport: &parse::DllExport) -> (TokenStream
(
quote!(Handler::Sync(wrappers::#sym_name)),
quote! {
pub unsafe fn #sym_name(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn #sym_name(machine: &mut Machine, stack_args: u32) -> u64 {
#fetch_args
let result = #impls_mod::#base_name(machine, #(#args),*);
#return_result
Expand Down Expand Up @@ -134,7 +134,7 @@ pub fn shims_module(module_name: &str, dllexports: parse::DllExports) -> TokenSt

mod wrappers {
use ::memory::Extensions;
use crate::{machine::Machine, winapi::{self, stack_args::*, types::*}};
use crate::{machine::Machine, winapi::{self, calling_convention::*, types::*}};
use winapi::#module::*; // for types
#(#wrappers)*
}
Expand Down
Binary file modified win32/dll/ucrtbase.dll
Binary file not shown.
14 changes: 9 additions & 5 deletions win32/src/machine_emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,14 @@ impl MachineX<Emulator> {
Handler::Sync(func) => {
let ret = unsafe { func(self, stack_args) };
let regs = &mut self.emu.x86.cpu_mut().regs;
regs.set32(x86::Register::EAX, ret);
regs.set32(x86::Register::EAX, ret as u32);
regs.set32(x86::Register::EDX, (ret >> 32) as u32);

// Clear registers to make traces clean.
// eax holds return value; other registers are callee-saved per ABI.
// After call, attempt to clear registers to make execution traces easier to match.
// eax: holds return value
regs.set32(x86::Register::ECX, 0);
regs.set32(x86::Register::EDX, 0);
// edx: sometimes used for 64-bit returns
// ebx: callee-saved
}

Handler::Async(func) => {
Expand Down Expand Up @@ -236,9 +238,11 @@ impl MachineX<Emulator> {
}

pub fn dump_state(&self, eip_offset: usize) {
x86::debug::dump_state(self.emu.x86.cpu(), self.mem(), &self.labels, eip_offset);
let cpu = self.emu.x86.cpu();
x86::debug::dump_state(cpu, self.mem(), &self.labels, eip_offset);
println!("stack:");
self.dump_stack();
x86::debug::dump_fpu_state(cpu);
}

/// Patch in an int3 over the instruction at that addr, backing up the current one.
Expand Down
9 changes: 8 additions & 1 deletion win32/src/machine_unicorn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,17 @@ impl MachineX<Emulator> {
Handler::Sync(func) => {
let ret = unsafe { func(self, stack_args) };

self.emu.unicorn.reg_write(RegisterX86::EAX, ret).unwrap();
self.emu
.unicorn
.reg_write(RegisterX86::EAX, ret as u64)
.reg_write(RegisterX86::EDX, ret >> 32)
.unwrap();

// After call, attempt to clear registers to make execution traces easier to match.
// eax: holds return value
self.emu.unicorn.reg_write(RegisterX86::ECX, 0).unwrap();
// edx: sometimes used for 64-bit returns
// ebx: callee-saved
}
Handler::Async(func) => {
let return_address = eip;
Expand Down
4 changes: 2 additions & 2 deletions win32/src/shims.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
use crate::Machine;
use std::collections::HashMap;

pub type SyncHandler = unsafe fn(&mut Machine, u32) -> u32;
pub type SyncHandler = unsafe fn(&mut Machine, u32) -> u64;
pub type AsyncHandler =
unsafe fn(&mut Machine, u32) -> std::pin::Pin<Box<dyn std::future::Future<Output = u32>>>;
unsafe fn(&mut Machine, u32) -> std::pin::Pin<Box<dyn std::future::Future<Output = u64>>>;
#[derive(Debug, Clone, Copy)]
pub enum Handler {
Sync(SyncHandler),
Expand Down
6 changes: 3 additions & 3 deletions win32/src/shims_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ std::arch::global_asm!(
"pushq %rdi", // preserve edi
"pushq %rsi", // preserve esi
"call {call64}", // call 64-bit Rust
// clear registers to make traces clean
// eax holds return value, leave alone
// After call, attempt to clear registers to make execution traces easier to match.
// eax: holds return value
"xorl %ecx, %ecx",
// edx: sometimes used for 64-bit returns
// ebx: callee-saved
"xorl %edx, %edx",
"popq %rsi", // restore esi
"popq %rdi", // restore edi
// ebp: callee-saved
Expand Down
34 changes: 17 additions & 17 deletions win32/src/winapi/advapi32/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::{
mod wrappers {
use crate::{
machine::Machine,
winapi::{self, stack_args::*, types::*},
winapi::{self, calling_convention::*, types::*},
};
use ::memory::Extensions;
use winapi::advapi32::*;
pub unsafe fn RegCloseKey(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegCloseKey(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let __trace_record = if crate::trace::enabled("advapi32") {
Expand All @@ -30,9 +30,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegCreateKeyA(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegCreateKeyA(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpSubKey = <Option<&str>>::from_stack(mem, stack_args + 4u32);
Expand All @@ -56,9 +56,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegCreateKeyExW(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegCreateKeyExW(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpSubKey = <Option<&Str16>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -105,9 +105,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegOpenKeyExA(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegOpenKeyExA(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpSubKey = <Option<&str>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -137,9 +137,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegQueryValueExA(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegQueryValueExA(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpValueName = <Option<&str>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -177,9 +177,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegQueryValueExW(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegQueryValueExW(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpValueName = <Option<&Str16>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -217,9 +217,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegSetValueExA(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegSetValueExA(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpValueName = <Option<&str>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -257,9 +257,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn RegSetValueExW(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn RegSetValueExW(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, stack_args + 0u32);
let lpValueName = <Option<&Str16>>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -297,7 +297,7 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
}
const SHIMS: [Shim; 8usize] = [
Expand Down
30 changes: 15 additions & 15 deletions win32/src/winapi/bass/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::{
mod wrappers {
use crate::{
machine::Machine,
winapi::{self, stack_args::*, types::*},
winapi::{self, calling_convention::*, types::*},
};
use ::memory::Extensions;
use winapi::bass::*;
pub unsafe fn BASS_ChannelGetPosition(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_ChannelGetPosition(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let mode = <u32>::from_stack(mem, stack_args + 0u32);
let __trace_record = if crate::trace::enabled("bass") {
Expand All @@ -30,9 +30,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_Free(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_Free(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let arg1 = <u32>::from_stack(mem, stack_args + 0u32);
let __trace_record = if crate::trace::enabled("bass") {
Expand All @@ -50,9 +50,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_Init(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_Init(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let arg1 = <u32>::from_stack(mem, stack_args + 0u32);
let arg2 = <u32>::from_stack(mem, stack_args + 4u32);
Expand All @@ -78,9 +78,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_MusicLoad(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_MusicLoad(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let arg1 = <u32>::from_stack(mem, stack_args + 0u32);
let arg2 = <u32>::from_stack(mem, stack_args + 4u32);
Expand Down Expand Up @@ -108,9 +108,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_MusicPlay(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_MusicPlay(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let arg1 = <u32>::from_stack(mem, stack_args + 0u32);
let __trace_record = if crate::trace::enabled("bass") {
Expand All @@ -128,9 +128,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_MusicSetPositionScaler(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_MusicSetPositionScaler(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let arg1 = <u32>::from_stack(mem, stack_args + 0u32);
let arg2 = <u32>::from_stack(mem, stack_args + 4u32);
Expand All @@ -149,9 +149,9 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
pub unsafe fn BASS_Start(machine: &mut Machine, stack_args: u32) -> u32 {
pub unsafe fn BASS_Start(machine: &mut Machine, stack_args: u32) -> u64 {
let mem = machine.mem().detach();
let __trace_record = if crate::trace::enabled("bass") {
crate::trace::Record::new(winapi::bass::BASS_Start_pos, "bass", "BASS_Start", &[])
Expand All @@ -163,7 +163,7 @@ mod wrappers {
if let Some(mut __trace_record) = __trace_record {
__trace_record.exit(&result);
}
result.to_raw()
result.into_abireturn()
}
}
const SHIMS: [Shim; 7usize] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
//! Functions to unsafely grab winapi function arguments from an x86 stack.
//! Functions implementing the win32 calling convention:
//! - reading arguments from the stack;
//! - converting return values into a form suitable for putting in registers
//!
//! These functions work with an arbitrary stack pointer (for input) and convert to
//! plain values (for output) so that different machine implementations can do their
//! own control over the stack and moving return values into registers.

use super::types::{CStr, Str16};
use crate::str16::expect_ascii;
Expand Down Expand Up @@ -188,31 +194,41 @@ impl<'a> FromStack<'a> for VarArgs {
}
}

/// Types that can be returned from a winapi function, passed via EAX.
pub trait ToX86 {
fn to_raw(&self) -> u32;
/// Types that can be returned from a winapi function, passed via EAX and sometimes EDX.
pub trait ABIReturn {
fn into_abireturn(self) -> u64;
}
impl ToX86 for bool {
fn to_raw(&self) -> u32 {
if *self {

impl ABIReturn for bool {
fn into_abireturn(self) -> u64 {
if self {
1
} else {
0
}
}
}
impl ToX86 for u32 {
fn to_raw(&self) -> u32 {
*self

impl ABIReturn for u64 {
fn into_abireturn(self) -> u64 {
self
}
}
impl ToX86 for i32 {
fn to_raw(&self) -> u32 {
*self as u32

impl ABIReturn for u32 {
fn into_abireturn(self) -> u64 {
self as u64
}
}
impl ToX86 for () {
fn to_raw(&self) -> u32 {

impl ABIReturn for i32 {
fn into_abireturn(self) -> u64 {
self as u32 as u64
}
}

impl ABIReturn for () {
fn into_abireturn(self) -> u64 {
0
}
}
Loading