scanmem alternative with concurrent memory scanning
at master 3.1 kB view raw
1use anyhow::Result; 2use log::info; 3use std::fs; 4use std::path::Path; 5use std::str::FromStr; 6 7pub struct Process { 8 pub pid: i32, 9 #[allow(dead_code)] 10 pub name: String, 11} 12 13#[derive(Debug, Clone)] 14pub struct MemoryRegion { 15 pub start_addr: usize, 16 pub end_addr: usize, 17 #[allow(dead_code)] 18 pub permissions: String, 19 #[allow(dead_code)] 20 pub offset: usize, 21 #[allow(dead_code)] 22 pub pathname: String, 23} 24 25impl Process { 26 pub fn find_by_name(name: &str) -> Result<Self> { 27 // Search for process using pgrep-like functionality 28 let proc_dir = Path::new("/proc"); 29 let mut found_pid = None; 30 31 for entry in fs::read_dir(proc_dir)? { 32 let entry = entry?; 33 let path = entry.path(); 34 35 if !path.is_dir() { 36 continue; 37 } 38 39 let file_name = path.file_name().unwrap().to_string_lossy(); 40 if !file_name.chars().all(|c| c.is_digit(10)) { 41 continue; 42 } 43 44 let pid = i32::from_str(&file_name)?; 45 let cmdline_path = path.join("cmdline"); 46 47 if !cmdline_path.exists() { 48 continue; 49 } 50 51 let cmdline = fs::read_to_string(cmdline_path)?; 52 if cmdline.contains(name) { 53 println!("Process found with PID: {}", pid); 54 found_pid = Some(pid); 55 break; 56 } 57 } 58 59 match found_pid { 60 Some(pid) => Ok(Process { 61 pid, 62 name: name.to_string(), 63 }), 64 None => anyhow::bail!("Process '{}' not found", name), 65 } 66 } 67 68 pub fn get_memory_maps(&self) -> Result<Vec<MemoryRegion>> { 69 let maps_path = format!("/proc/{}/maps", self.pid); 70 info!("maps file located at {} opened.", maps_path); 71 72 let maps_content = fs::read_to_string(&maps_path)?; 73 let mut regions = Vec::new(); 74 75 for line in maps_content.lines() { 76 let parts: Vec<&str> = line.split_whitespace().collect(); 77 if parts.len() < 5 { 78 continue; 79 } 80 81 let addr_range: Vec<&str> = parts[0].split('-').collect(); 82 if addr_range.len() != 2 { 83 continue; 84 } 85 86 let start_addr = usize::from_str_radix(addr_range[0], 16)?; 87 let end_addr = usize::from_str_radix(addr_range[1], 16)?; 88 let permissions = parts[1].to_string(); 89 90 // Only add regions with read permission 91 if permissions.contains('r') { 92 regions.push(MemoryRegion { 93 start_addr, 94 end_addr, 95 permissions, 96 offset: usize::from_str_radix(parts[2], 16)?, 97 pathname: if parts.len() > 5 { 98 parts[5..].join(" ") 99 } else { 100 String::new() 101 }, 102 }); 103 } 104 } 105 106 info!("{} suitable regions found.", regions.len()); 107 Ok(regions) 108 } 109}