Hpmason / retour-rs

A cross-platform detour library written in Rust
Other
99 stars 18 forks source link

need support for "thiscall" #51

Closed zhefenfei closed 3 months ago

zhefenfei commented 4 months ago

need support fo "thiscall"

Hpmason commented 4 months ago

thiscall ABI should be supported, is behind a feature flag thiscall-abi. You should be able to modify your Cargo.toml to enable it:

[dependencies]
retour = { version = "0.3", features = ["thiscall-abi"] }

A little background on why the feature flag: It was originally put under a feature flag because it was nightly-only and I wanted this crate to support stable rust. Even after it stabilizing in rust v1.73.0, it's still behind the flag to maintain a lower minimum supported rust version (MSRV).

If you have any issues with the flag enabled, let me know and I can try to help out further!

zhefenfei commented 4 months ago

static_detour! { static Test: unsafe extern "thiscall" fn(i32,i32,i32,i32)->i32; }

pub fn set_hook() { unsafe { let originalcall = std::mem::transmute::< , unsafe extern "thiscall" fn(i32, i32, i32, i32) -> i32,

(0x00BE5900); Test.initialize(original_call, test_hook) .unwrap() .enable() .unwrap() }; }

[no_mangle]

unsafe extern "thiscall" fn test_hook(arg0: i32, arg1: i32, arg2: i32, arg3: i32) -> i32 { unsafe { Test.call(arg0, arg1, arg2, arg3) }; 0 }

pls see this test in StaticDetour. i tried this ,but when initialize will show error like =================error========================================================== expected a Fn(i32, i32, i32, i32) closure, found unsafe extern "thiscall" fn(i32, i32, i32, i32) -> i32 {test_hook} the trait Fn<(i32, i32, i32, i32)> is not implemented for fn item unsafe extern "thiscall" fn(i32, i32, i32, i32) -> i32 {test_hook} unsafe function cannot be called generically without an unsafe blockrustcClick for full compiler diagnostic string_pool.rs(5722, 14): required by a bound introduced by this call statik.rs(107, 8): required by a bound in StaticDetour::<T>::initialize ijl15::assembly::string_pool unsafe extern "thiscall" fn test_hook(arg0: i32, arg1: i32, arg2: i32, arg3: i32) -> i32``` =================error==========================================================

i tried GenericDetour work is ok.but i wanna know why cause this problem.

Hpmason commented 4 months ago

Ah I see the issue. This isn't an issue exclusive to "thiscall" ABI, it's an issue with unsafe hooks.

StaticDetour is meant to allow any function to be detoured by another function with the same arguments and return type. That's done through the Fn trait (not to be confused with the fn type ), the bound being D: Fn<T::Arguments, Output = T::Output> + Send + 'static. The Fn trait is only implemented for safe functions. There's a dicussion about it in the GitHub issue here that goes into some of the reasons why unsafe fns don't implement Fn trait.

In order to hook an unsafe/extern function, you can just use a safe, rust ABI, function:

static_detour! {
    static Test: unsafe extern "thiscall" fn(i32, i32, i32, i32) -> i32;
}

pub fn set_hook() {
    unsafe {
        let original_call = std::mem::transmute::<
            usize,
            unsafe extern "thiscall" fn(i32, i32, i32, i32) -> i32,
        >(0x00BE5900);
        Test.initialize(original_call, test_hook)
            .unwrap()
            .enable()
            .unwrap()
    };
}

fn test_hook(arg0: i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
    unsafe { Test.call(arg0, arg1, arg2, arg3) };
    0
}