specter/memory/info/
image.rs1#[cfg(feature = "dev_release")]
4use crate::utils::logger;
5use std::ffi::CStr;
6
7#[cfg(feature = "dev_release")]
8use mach2::dyld::{
9 _dyld_get_image_header, _dyld_get_image_name, _dyld_get_image_vmaddr_slide, _dyld_image_count,
10};
11#[cfg(not(feature = "dev_release"))]
12use mach2::dyld::{_dyld_get_image_header, _dyld_get_image_name, _dyld_image_count};
13use thiserror::Error;
14
15#[derive(Error, Debug)]
16pub enum ImageError {
18 #[error("Image not found: {0}")]
20 NotFound(String),
21}
22
23use once_cell::sync::Lazy;
24use parking_lot::RwLock;
25use std::collections::HashMap;
26
27static IMAGE_CACHE: Lazy<RwLock<HashMap<String, usize>>> =
28 Lazy::new(|| RwLock::new(HashMap::new()));
29
30pub fn get_image_base(image_name: &str) -> Result<usize, ImageError> {
38 {
39 let cache = IMAGE_CACHE.read();
40 if let Some(&base) = cache.get(image_name) {
41 return Ok(base);
42 }
43 }
44
45 unsafe {
46 let count = _dyld_image_count();
47
48 for i in 0..count {
49 let name_ptr = _dyld_get_image_name(i);
50 if name_ptr.is_null() {
51 continue;
52 }
53
54 let name = CStr::from_ptr(name_ptr).to_string_lossy();
55 if name.contains(image_name) {
56 let header = _dyld_get_image_header(i);
57 #[cfg(feature = "dev_release")]
58 let slide = _dyld_get_image_vmaddr_slide(i);
59
60 #[cfg(feature = "dev_release")]
61 logger::info(&format!(
62 "Found image: {} (Index: {}, Base: {:p}, Slide: {:#x})",
63 name, i, header, slide
64 ));
65
66 let base = header as usize;
67
68 IMAGE_CACHE.write().insert(image_name.to_string(), base);
69
70 return Ok(base);
71 }
72 }
73 }
74
75 #[cfg(feature = "dev_release")]
76 logger::warning(&format!("Image not found: {}", image_name));
77 Err(ImageError::NotFound(image_name.to_string()))
78}