I am using Rust to write a DLL that is going to be injected into other process and I want to call functions that are located at known addresses from the executable of that process. I use transmute
to cast a hardcoded address to a function pointer but I might potentially have many functions and I'd like an easier way of managing that.
Ideally I'd only have extern "C"
declarations like when linking with a DLL instead of an implementation with copy-pasted cast for each function.
lib.rs
fn add_one(i: u32) -> u32 {
let add_one_from_exe_location = 0xd51000;
let add_one_from_exe: unsafe extern "C" fn(u32) -> u32 =
unsafe { std::mem::transmute(add_one_from_exe_location as *const ()) };
unsafe { add_one_from_exe(i) }
}
fn hello() {
println!("hello from dll");
println!("1 + 1 = {}", add_one(1));
}
#[no_mangle]
pub extern "stdcall" fn DllMain(
_: winapi::shared::minwindef::HINSTANCE,
fdw_reason: winapi::shared::minwindef::DWORD,
_lpv_reserved: winapi::shared::minwindef::LPVOID,
) -> i32 {
match fdw_reason {
winapi::um::winnt::DLL_PROCESS_ATTACH => {
hello();
}
_ => (),
}
true as i32
}
Here's an example of an executable
main.rs
#[no_mangle]
extern "C" fn add_one(x: u32) -> u32 {
x + 1
}
fn main() {
use std::{thread, time};
let mut x = 0;
loop {
x = add_one(x);
thread::sleep(time::Duration::from_millis(1000));
println!("{}", x);
}
}
When I inject the DLL it outputs
41
hello from dll
1 + 1 = 2
42