substrate/
lib.rs

1pub mod arch;
2pub mod debug;
3pub mod disasm;
4pub mod error;
5pub mod hook;
6pub mod symbol;
7pub mod utils;
8
9use error::{Result, SubstrateError};
10use std::ffi::CStr;
11use std::os::raw::{c_char, c_int, c_void};
12use std::ptr;
13use std::sync::atomic::{AtomicBool, Ordering};
14
15pub type MSImageRef = *const c_void;
16
17static MS_DEBUG: AtomicBool = AtomicBool::new(false);
18
19#[no_mangle]
20pub static mut MSDebug: bool = false;
21
22pub fn set_debug(enabled: bool) {
23    MS_DEBUG.store(enabled, Ordering::Relaxed);
24    unsafe { MSDebug = enabled; }
25}
26
27pub fn is_debug() -> bool {
28    MS_DEBUG.load(Ordering::Relaxed)
29}
30
31#[no_mangle]
32pub unsafe extern "C" fn MSHookFunction(
33    symbol: *mut c_void,
34    replace: *mut c_void,
35    result: *mut *mut c_void,
36) {
37    if symbol.is_null() {
38        return;
39    }
40
41    let result_ptr = if result.is_null() {
42        ptr::null_mut()
43    } else {
44        result as *mut *mut u8
45    };
46
47    #[cfg(target_arch = "x86_64")]
48    {
49        let _ = arch::x86_64::hook_function_x86_64(
50            symbol as *mut u8,
51            replace as *mut u8,
52            result_ptr,
53        );
54    }
55
56    #[cfg(target_arch = "arm")]
57    {
58        let symbol_addr = symbol as usize;
59        if (symbol_addr & 0x1) == 0 {
60            let _ = arch::arm::hook_function_arm(
61                symbol as *mut u8,
62                replace as *mut u8,
63                result_ptr,
64            );
65        } else {
66            let _ = arch::thumb::hook_function_thumb(
67                (symbol_addr & !0x1) as *mut u8,
68                replace as *mut u8,
69                result_ptr,
70            );
71        }
72    }
73
74    #[cfg(target_arch = "aarch64")]
75    {
76        let _ = arch::aarch64::hook_function_aarch64(
77            symbol as *mut u8,
78            replace as *mut u8,
79            result_ptr,
80        );
81    }
82}
83
84#[no_mangle]
85pub unsafe extern "C" fn A64HookFunction(
86    symbol: *mut c_void,
87    replace: *mut c_void,
88    result: *mut *mut c_void,
89) {
90    MSHookFunction(symbol, replace, result);
91}
92
93#[no_mangle]
94pub unsafe extern "C" fn MSFindSymbol(_image: MSImageRef, name: *const c_char) -> *mut c_void {
95    if name.is_null() {
96        return ptr::null_mut();
97    }
98
99    let _symbol_name = match CStr::from_ptr(name).to_str() {
100        Ok(s) => s,
101        Err(_) => return ptr::null_mut(),
102    };
103
104    ptr::null_mut()
105}
106
107#[no_mangle]
108pub unsafe extern "C" fn MSGetImageByName(_file: *const c_char) -> MSImageRef {
109    ptr::null()
110}
111
112#[no_mangle]
113pub unsafe extern "C" fn MSHookProcess(_pid: c_int, _library: *const c_char) -> bool {
114    false
115}
116
117pub unsafe fn hook_function<T>(symbol: *mut T, replace: *mut T) -> Result<*mut T> {
118    if symbol.is_null() || replace.is_null() {
119        return Err(SubstrateError::NullPointer);
120    }
121
122    let mut result: *mut T = ptr::null_mut();
123
124    #[cfg(target_arch = "x86_64")]
125    {
126        arch::x86_64::hook_function_x86_64(
127            symbol as *mut u8,
128            replace as *mut u8,
129            &mut result as *mut *mut T as *mut *mut u8,
130        )?;
131    }
132
133    #[cfg(target_arch = "arm")]
134    {
135        let symbol_addr = symbol as usize;
136        if (symbol_addr & 0x1) == 0 {
137            arch::arm::hook_function_arm(
138                symbol as *mut u8,
139                replace as *mut u8,
140                &mut result as *mut *mut T as *mut *mut u8,
141            )?;
142        } else {
143            arch::thumb::hook_function_thumb(
144                (symbol_addr & !0x1) as *mut u8,
145                replace as *mut u8,
146                &mut result as *mut *mut T as *mut *mut u8,
147            )?;
148        }
149    }
150
151    #[cfg(target_arch = "aarch64")]
152    {
153        arch::aarch64::hook_function_aarch64(
154            symbol as *mut u8,
155            replace as *mut u8,
156            &mut result as *mut *mut T as *mut *mut u8,
157        )?;
158    }
159
160    #[cfg(not(any(target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64")))]
161    {
162        return Err(SubstrateError::HookFailed("Architecture not implemented".to_string()));
163    }
164
165    Ok(result)
166}
167
168pub fn find_symbol_in_process(
169    pid: libc::pid_t,
170    library: &str,
171    symbol: &str,
172) -> Result<*mut c_void> {
173    let addr = symbol::finder::find_symbol_address(pid, symbol, library)?;
174    Ok(addr as *mut c_void)
175}