sig.rs (3246B) - raw


      1 use std::sync::Mutex;
      2 
      3 use procfs::process::MMPermissions;
      4 
      5 use crate::mapped_lib::MappedLib;
      6 
      7 
      8 static SIGNATURE_CACHE: Mutex<Vec<(String, Vec<usize>)>> = Mutex::new(Vec::new());
      9 
     10 pub fn add_signatures(signatures: Vec<(String, Vec<usize>)>) {
     11     SIGNATURE_CACHE.lock().unwrap().extend(signatures);
     12 }
     13 
     14 pub fn get_signatures() -> Vec<(String, Vec<usize>)> {
     15     SIGNATURE_CACHE.lock().unwrap().clone()
     16 }
     17 
     18 pub fn find_signatures(module_base: usize, size: usize, pattern: &str, once: bool) -> Vec<usize> {
     19     let mut results = Vec::new();
     20     let mut bytes = Vec::new();
     21     let mut mask = Vec::new();
     22     let mut i = 0;
     23 
     24     if let Some(cache) = SIGNATURE_CACHE.lock().unwrap().iter().find(|(sig, _)| sig == pattern) {
     25         return cache.1.clone().into_iter().map(|offset| module_base + offset).collect();
     26     }
     27 
     28     while i < pattern.len() {
     29         if pattern.chars().nth(i).unwrap() == '?' {
     30             bytes.push(0);
     31             mask.push('?');
     32         } else {
     33             bytes.push(u8::from_str_radix(&pattern[i..i+2], 16).unwrap());
     34             mask.push('x');
     35         }
     36         i += 3;
     37     }
     38 
     39     let mut i = 0;
     40     let size = size - bytes.len();
     41     while i < size {
     42         let mut found = true;
     43         let mut j = 0;
     44 
     45         while j < bytes.len() {
     46             if mask[j] == '?' || bytes[j] == unsafe { *(module_base as *const u8).offset(i as isize + j as isize) } {
     47                 j += 1;
     48                 continue;
     49             }
     50             found = false;
     51             break;
     52         }
     53         if found {
     54             if once {
     55                 SIGNATURE_CACHE.lock().unwrap().push((pattern.to_string(), vec![i]));
     56                 return vec![module_base + i];
     57             }
     58             results.push(module_base + i);
     59         }
     60         i += 1;
     61     }
     62 
     63     SIGNATURE_CACHE.lock().unwrap().push((pattern.to_string(), results.clone()));
     64     results
     65 }
     66 
     67 pub fn find_signature_executable(mapped_lib: &MappedLib, pattern: &str) -> Option<usize> {
     68     let executable_regions = mapped_lib.regions.iter().filter(|region| {
     69         region.perms.contains(MMPermissions::EXECUTE) && region.perms.contains(MMPermissions::READ)
     70     }).collect::<Vec<_>>();
     71 
     72     for region in executable_regions {
     73         let size = (region.end - region.start) as usize;
     74         let module_base = region.start as usize;
     75 
     76         if size > 0 {
     77             let results = find_signatures(module_base, size, pattern, true);
     78 
     79             if results.is_empty() {
     80                 warn!("Signature not found in region: {:#x} - {:#x}", region.start, region.end);
     81             } else {
     82                 debug!("Found {} results in region: {:#x} - {:#x}", results.len(), region.start, region.end);
     83                 return Some(results[0]);
     84             }
     85         }
     86     }
     87 
     88     None
     89 }
     90 
     91 pub fn find_signature(mapped_lib: &MappedLib, _arm64_pattern: &str, _arm64_offset: i64, _arm32_pattern: &str, _arm32_offset: i64) -> Option<usize> {
     92     #[cfg(target_arch = "aarch64")]
     93     {
     94         return find_signature_executable(mapped_lib, _arm64_pattern).map(|address| (address as i64 + _arm64_offset) as usize);
     95     }
     96     #[cfg(target_arch = "arm")]
     97     {
     98         return find_signature_executable(mapped_lib, _arm32_pattern).map(|address| (address as i64 + _arm32_offset) as usize);
     99     }
    100 }