MSHookFunction

Function MSHookFunction 

Source
#[unsafe(no_mangle)]
pub unsafe extern "C" fn MSHookFunction( symbol: *mut c_void, replace: *mut c_void, result: *mut *mut c_void, )
Expand description

Hook a function at runtime by redirecting its execution to a replacement function.

This is the primary C-compatible hooking function that works across all supported architectures (x86-64, ARMv7, ARM64). It installs an inline hook by modifying the target function’s prologue to jump to your replacement function, while preserving the original instructions in a trampoline.

§Arguments

  • symbol - Pointer to the function to hook (must not be null)
  • replace - Pointer to your replacement function (must not be null)
  • result - Output pointer that receives the trampoline address to call the original function. Pass null if you don’t need to call the original function.

§Safety

This function is unsafe because it:

  • Modifies executable code at runtime
  • Requires valid function pointers
  • Changes memory protection flags
  • Can cause undefined behavior if pointers are invalid

§Examples

use substrate::MSHookFunction;
use std::os::raw::c_void;

static mut ORIGINAL: *mut c_void = std::ptr::null_mut();

unsafe extern "C" fn my_replacement() {
    println!("Hooked!");
    if !ORIGINAL.is_null() {
        let orig: extern "C" fn() = std::mem::transmute(ORIGINAL);
        orig();
    }
}

unsafe {
    let target = 0x12345678 as *mut c_void;
    MSHookFunction(target, my_replacement as *mut c_void, &mut ORIGINAL);
}
Examples found in repository?
examples/library_hook.rs (lines 38-42)
18fn main() {
19    println!("=== Library Function Hook Example ===\n");
20
21    println!("This example demonstrates hooking a function in a shared library.");
22    println!("Note: This requires a target library to be loaded.\n");
23
24    let library_name = "libexample.so";
25    let function_offset = 0x1234;
26
27    unsafe {
28        println!("Checking if {} is loaded...", library_name);
29
30        if utils::is_library_loaded(library_name) {
31            println!("✓ Library is loaded!");
32
33            match utils::get_absolute_address(library_name, function_offset) {
34                Ok(addr) => {
35                    println!("Target address: 0x{:x}", addr);
36                    println!("Installing hook...");
37
38                    MSHookFunction(
39                        addr as *mut c_void,
40                        my_hooked_function as *mut c_void,
41                        &mut OLD_FUNCTION
42                    );
43
44                    println!("✓ Hook installed!");
45                    println!("Original function: {:p}", OLD_FUNCTION);
46                }
47                Err(e) => {
48                    eprintln!("✗ Failed to get address: {}", e);
49                }
50            }
51        } else {
52            println!("✗ Library '{}' is not loaded", library_name);
53            println!("\nTo use this example:");
54            println!("1. Replace 'libexample.so' with your target library");
55            println!("2. Replace 0x1234 with the actual function offset");
56            println!("3. Make sure the library is loaded before running");
57        }
58    }
59}
More examples
Hide additional examples
examples/android_game_hook.rs (lines 67-71)
45fn main() {
46    println!("=== Android Game Hook Example (IL2CPP/Unity) ===\n");
47
48    let library = "libil2cpp.so";
49
50    let update_offset_str = "0x123456";
51    let fixed_update_offset_str = "0x789ABC";
52
53    println!("Waiting for {} to load...", library);
54
55    if wait_for_library(library, 30) {
56        println!("✓ {} loaded!", library);
57
58        unsafe {
59            match string_to_offset(update_offset_str) {
60                Ok(update_offset) => {
61                    println!("\nHooking Update() at offset: 0x{:X}", update_offset);
62
63                    match get_absolute_address(library, update_offset) {
64                        Ok(addr) => {
65                            println!("Absolute address: 0x{:x}", addr);
66
67                            MSHookFunction(
68                                addr as *mut c_void,
69                                hooked_update as *mut c_void,
70                                &mut OLD_UPDATE
71                            );
72
73                            if !OLD_UPDATE.is_null() {
74                                println!("✓ Update() hooked successfully!");
75                            }
76                        }
77                        Err(e) => eprintln!("✗ Failed to get address: {}", e),
78                    }
79                }
80                Err(e) => eprintln!("✗ Invalid offset: {}", e),
81            }
82
83            match string_to_offset(fixed_update_offset_str) {
84                Ok(fixed_offset) => {
85                    println!("\nHooking FixedUpdate() at offset: 0x{:X}", fixed_offset);
86
87                    match get_absolute_address(library, fixed_offset) {
88                        Ok(addr) => {
89                            println!("Absolute address: 0x{:x}", addr);
90
91                            MSHookFunction(
92                                addr as *mut c_void,
93                                hooked_fixed_update as *mut c_void,
94                                &mut OLD_FIXED_UPDATE
95                            );
96
97                            if !OLD_FIXED_UPDATE.is_null() {
98                                println!("✓ FixedUpdate() hooked successfully!");
99                            }
100                        }
101                        Err(e) => eprintln!("✗ Failed to get address: {}", e),
102                    }
103                }
104                Err(e) => eprintln!("✗ Invalid offset: {}", e),
105            }
106
107            println!("\n=== Hooks Installed ===");
108            println!("The game functions will now call your hooks.");
109            println!("\nNote: Replace the offset values with real ones from your game!");
110        }
111    } else {
112        eprintln!("✗ Timeout waiting for {} to load", library);
113        eprintln!("\nTo use this example:");
114        eprintln!("1. Find function offsets using IDA Pro, Ghidra, or similar");
115        eprintln!("2. Replace the offset strings with actual values");
116        eprintln!("3. Run as part of an injected library in the game process");
117    }
118}