substrate/
utils.rs

1use crate::error::{Result, SubstrateError};
2use std::ffi::CStr;
3use std::fs::File;
4use std::io::{BufRead, BufReader};
5use std::os::raw::{c_char, c_void};
6
7pub fn find_library(library_name: &str) -> Result<usize> {
8    let maps_file = File::open("/proc/self/maps").map_err(|e| {
9        SubstrateError::FileNotFound(format!("Failed to open /proc/self/maps: {}", e))
10    })?;
11
12    let reader = BufReader::new(maps_file);
13
14    for line in reader.lines() {
15        let line = line.map_err(|e| {
16            SubstrateError::ParseError(format!("Failed to read line: {}", e))
17        })?;
18
19        if line.contains(library_name) {
20            let parts: Vec<&str> = line.split_whitespace().collect();
21            if !parts.is_empty() {
22                if let Some(addr_str) = parts[0].split('-').next() {
23                    return usize::from_str_radix(addr_str, 16).map_err(|e| {
24                        SubstrateError::ParseError(format!("Failed to parse address: {}", e))
25                    });
26                }
27            }
28        }
29    }
30
31    Err(SubstrateError::LibraryNotFound(library_name.to_string()))
32}
33
34pub fn get_absolute_address(library_name: &str, relative_addr: usize) -> Result<usize> {
35    let base = find_library(library_name)?;
36    Ok(base + relative_addr)
37}
38
39pub fn is_library_loaded(library_name: &str) -> bool {
40    if let Ok(file) = File::open("/proc/self/maps") {
41        let reader = BufReader::new(file);
42        for line in reader.lines().flatten() {
43            if line.contains(library_name) {
44                return true;
45            }
46        }
47    }
48    false
49}
50
51pub fn string_to_offset(s: &str) -> Result<usize> {
52    let s = s.trim_start_matches("0x").trim_start_matches("0X");
53    usize::from_str_radix(s, 16).map_err(|e| {
54        SubstrateError::ParseError(format!("Failed to parse offset: {}", e))
55    })
56}
57
58#[no_mangle]
59pub unsafe extern "C" fn findLibrary(library: *const c_char) -> usize {
60    if library.is_null() {
61        return 0;
62    }
63
64    let library_name = match CStr::from_ptr(library).to_str() {
65        Ok(s) => s,
66        Err(_) => return 0,
67    };
68
69    find_library(library_name).unwrap_or(0)
70}
71
72#[no_mangle]
73pub unsafe extern "C" fn getAbsoluteAddress(library: *const c_char, offset: usize) -> usize {
74    if library.is_null() {
75        return 0;
76    }
77
78    let library_name = match CStr::from_ptr(library).to_str() {
79        Ok(s) => s,
80        Err(_) => return 0,
81    };
82
83    get_absolute_address(library_name, offset).unwrap_or(0)
84}
85
86#[no_mangle]
87pub unsafe extern "C" fn isLibraryLoaded(library: *const c_char) -> bool {
88    if library.is_null() {
89        return false;
90    }
91
92    let library_name = match CStr::from_ptr(library).to_str() {
93        Ok(s) => s,
94        Err(_) => return false,
95    };
96
97    is_library_loaded(library_name)
98}
99
100#[no_mangle]
101pub unsafe extern "C" fn string2Offset(s: *const c_char) -> usize {
102    if s.is_null() {
103        return 0;
104    }
105
106    let string = match CStr::from_ptr(s).to_str() {
107        Ok(s) => s,
108        Err(_) => return 0,
109    };
110
111    string_to_offset(string).unwrap_or(0)
112}
113
114#[no_mangle]
115pub unsafe extern "C" fn hook(
116    offset: *mut c_void,
117    ptr: *mut c_void,
118    orig: *mut *mut c_void,
119) {
120    #[cfg(target_arch = "aarch64")]
121    {
122        crate::A64HookFunction(offset, ptr, orig);
123    }
124
125    #[cfg(not(target_arch = "aarch64"))]
126    {
127        crate::MSHookFunction(offset, ptr, orig);
128    }
129}