From 75492a30d661c5fbe98d7ffcf98185105d11158a Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Sun, 25 Feb 2024 23:37:56 +0200 Subject: [PATCH 01/16] Add implementation for linux systems --- Cargo.toml | 3 ++ src/main.rs | 3 +- src/util/process.rs | 129 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 06c8475..760c956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,5 +30,8 @@ features = [ "Win32_System_Threading", ] +[target.'cfg(target_os = "linux")'.dependencies] +procfs = "0.16.0" + [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index 0c484ae..8ee68a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,6 +102,7 @@ fn main() -> Result<()> { process.initialize()?; + /* // Start the timer. let now = Instant::now(); @@ -123,7 +124,7 @@ fn main() -> Result<()> { info!( "Done! Time elapsed: {:?}", now.elapsed() - ); + ); */ Ok(()) } diff --git a/src/util/process.rs b/src/util/process.rs index edfc29a..5197ba5 100644 --- a/src/util/process.rs +++ b/src/util/process.rs @@ -7,10 +7,19 @@ use std::ffi::{c_void, CStr}; use std::mem; use std::ptr; -use windows::Win32::Foundation::{CloseHandle, HANDLE}; -use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory; -use windows::Win32::System::Diagnostics::ToolHelp::*; -use windows::Win32::System::Threading::{OpenProcess, PROCESS_ALL_ACCESS}; +#[cfg(target_os = "windows")] +use windows::Win32::{ + Foundation::{CloseHandle, HANDLE}, + System::Diagnostics::Debug::ReadProcessMemory, + System::Diagnostics::ToolHelp::*, + System::Threading::{OpenProcess, PROCESS_ALL_ACCESS}, +}; + +#[cfg(target_os = "linux")] +use procfs::process::{self, all_processes}; +use std::fs::File; +use std::io::{Read, Seek, SeekFrom}; +use std::path::{Path, PathBuf}; /// Represents a Windows process. #[derive(Debug)] @@ -18,6 +27,7 @@ pub struct Process { /// ID of the process. id: u32, + #[cfg(target_os = "windows")] /// Handle to the process. handle: HANDLE, @@ -35,6 +45,7 @@ impl Process { /// # Returns /// /// * `Result` - A `Result` containing the `Process` instance if successful, or an error if the process could not be found. + #[cfg(target_os = "windows")] pub fn new(name: &str) -> Result { let id = Self::get_process_id_by_name(name)?; @@ -47,6 +58,15 @@ impl Process { }) } + #[cfg(target_os = "linux")] + pub fn new(process_name: &str) -> Result { + let id = Self::get_process_id_by_name(process_name.strip_suffix(".exe").unwrap())?; + Ok(Self { + id, + modules: HashMap::new(), + }) + } + /// Initializes the `Process` instance by parsing all loaded modules in the process. /// /// # Arguments @@ -165,6 +185,8 @@ impl Process { /// # Returns /// /// * `Result<()>` - A `Result` indicating the outcome of the operation. + + #[cfg(target_os = "windows")] pub fn read_memory_raw( &self, address: Address, @@ -183,6 +205,28 @@ impl Process { .map_err(|e| e.into()) } + #[cfg(target_os = "linux")] + pub fn read_memory_raw( + &self, + address: Address, + buffer: *mut c_void, + size: usize, + ) -> Result<()> { + let proc_mem_path = format!("/proc/{}/mem", self.id); + let mut mem_file = File::open(proc_mem_path)?; + + // Go to the start address + mem_file.seek(SeekFrom::Start( +
>::into(address) as u64 + ))?; + + let buffer_slice = unsafe { std::slice::from_raw_parts_mut(buffer as *mut u8, size) }; + + // Try to read the data + mem_file.read_exact(buffer_slice)?; + Ok(()) + } + /// Reads a null-terminated string from the process memory at the given address. /// /// # Arguments @@ -290,6 +334,7 @@ impl Process { /// # Returns /// /// * `Result` - A `Result` containing the process ID if successful, or an error if the process could not be found. + #[cfg(target_os = "windows")] fn get_process_id_by_name(process_name: &str) -> Result { let snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }?; @@ -313,6 +358,26 @@ impl Process { bail!("Process not found: {}", process_name) } + #[cfg(target_os = "linux")] + fn get_process_id_by_name(process_name: &str) -> Result { + use std::io::{BufRead, BufReader}; + + for process_iter in all_processes()? { + let Ok(process) = process_iter else { continue }; + let comm_path = format!("/proc/{}/comm", process.pid()); + if let Ok(comm_file) = File::open(Path::new(&comm_path)) { + let mut comm = String::new(); + if BufReader::new(comm_file).read_line(&mut comm).is_ok() { + comm.pop(); + if comm == process_name && process.pid() > 0 { + return Ok(process.pid() as u32); + } + } + } + } + bail!("Process not found: {}", process_name); + } + /// Parses the loaded modules of a process and stores them in a HashMap with the module name as the key and the module data as the value. /// /// # Arguments @@ -322,6 +387,8 @@ impl Process { /// # Returns /// /// * `Result<()>` - A `Result` indicating the outcome of the operation. + + #[cfg(target_os = "windows")] fn parse_loaded_modules(&mut self) -> Result<()> { let snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, self.id) }?; @@ -351,6 +418,59 @@ impl Process { Ok(()) } + fn get_transformed_module_name(path: PathBuf) -> Option { + if let Ok(module_path) = path.into_os_string().into_string() { + if let Some(module_name) = module_path.split('/').last() { + if module_name.starts_with("lib") && module_name.ends_with(".so") { + return Some(format!( + "{}.dll", + module_name.strip_prefix("lib")?.strip_suffix(".so")? + )); + } + } + } + None + } + + #[cfg(target_os = "linux")] + fn parse_loaded_modules(&mut self) -> Result<()> { + let process = process::Process::new(self.id as i32)?; + + let mut modules_info: HashMap = HashMap::new(); + + for mmap in process.maps()? { + let mmap_path = match mmap.pathname { + process::MMapPath::Path(path) => path, + _ => continue, + }; + let module_name = match Process::get_transformed_module_name(mmap_path) { + Some(new_path) => new_path, + None => continue, + }; + let module_entry = modules_info + .entry(module_name) + .or_insert_with(|| (mmap.address)); + *module_entry = ( + std::cmp::min(mmap.address.0, module_entry.0), + std::cmp::max(mmap.address.1, module_entry.1), + ); + } + + for (module_name, address_space) in modules_info.into_iter() { + let (start, end) = address_space; + let mut data = vec![0; (end - start + 1) as usize]; + if let Ok(_) = self.read_memory_raw( + (start as usize).into(), + data.as_mut_ptr() as *mut _, + data.len(), + ) { + self.modules.insert(module_name, data); + } + } + + Ok(()) + } + /// Converts a pattern string to a vector of bytes. /// /// # Arguments @@ -377,6 +497,7 @@ impl Process { /// Implements the `Drop` trait for the `Process` struct. /// /// When a `Process` instance goes out of scope, this implementation will automatically close the process handle if it is not invalid. +#[cfg(target_os = "windows")] impl Drop for Process { fn drop(&mut self) { if !self.handle.is_invalid() { From f2f607c7ac29eb8260e2ee5d617c6b202eef8a07 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 27 Feb 2024 23:29:30 +0200 Subject: [PATCH 02/16] Parse the modules as elf files --- src/util/mod.rs | 1 + src/util/module.rs | 100 +++++++++++++++++++++++++++++++++++++++++++- src/util/process.rs | 79 ++++++++++++++++++++++++++++------ 3 files changed, 167 insertions(+), 13 deletions(-) diff --git a/src/util/mod.rs b/src/util/mod.rs index 08a23a3..774eb38 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,5 +1,6 @@ pub use address::Address; pub use module::Module; +pub use module::ModuleEntry; pub use process::Process; pub mod address; diff --git a/src/util/module.rs b/src/util/module.rs index c51c36a..35d65a9 100644 --- a/src/util/module.rs +++ b/src/util/module.rs @@ -8,16 +8,34 @@ use goblin::pe::options::ParseOptions; use goblin::pe::section_table::SectionTable; use goblin::pe::PE; +#[cfg(target_os = "linux")] +use goblin::elf::{program_header, sym, Elf, SectionHeader}; +use std::path::PathBuf; + +#[cfg(target_os = "linux")] +#[derive(Debug)] +pub struct ModuleEntry { + pub path: PathBuf, + pub start_addr: Address, + pub data: Vec, + pub module_file_data: Vec, +} /// Represents a module loaded in a Windows process. pub struct Module<'a> { /// The name of the module. pub name: &'a str, /// A reference to a slice of bytes containing the module data. + #[cfg(target_os = "windows")] pub data: &'a [u8], - + // #[cfg(target_os = "linux")] + pub module_info: &'a ModuleEntry, + #[cfg(target_os = "windows")] /// The PE file format representation of the module. pub pe: PE<'a>, + + #[cfg(target_os = "linux")] + pub elf: Elf<'a>, } impl<'a> Module<'a> { @@ -31,6 +49,7 @@ impl<'a> Module<'a> { /// # Returns /// /// * `Result` - A `Result` containing a `Module` instance if successful, or an error if the module could not be parsed. + #[cfg(target_os = "windows")] pub fn parse(name: &'a str, data: &'a [u8]) -> Result { let pe = PE::parse_with_opts( data, @@ -43,6 +62,17 @@ impl<'a> Module<'a> { Ok(Self { name, data, pe }) } + // parse the elf + #[cfg(target_os = "linux")] + pub fn parse(name: &'a str, module_entry: &'a ModuleEntry) -> Result { + let elf = Elf::parse(&module_entry.module_file_data)?; + Ok(Self { + name, + module_info: module_entry, + elf, + }) + } + /// Returns the base address of the module. /// /// # Arguments @@ -53,10 +83,17 @@ impl<'a> Module<'a> { /// /// * `Address` - The base address of the module. #[inline] + #[cfg(target_os = "windows")] pub fn base(&self) -> Address { self.pe.image_base.into() } + #[inline] + #[cfg(target_os = "linux")] + pub fn base(&self) -> Address { + self.module_info.start_addr + } + /// Returns a slice of `Export` structs representing the exports of the module. /// /// # Arguments @@ -67,10 +104,23 @@ impl<'a> Module<'a> { /// /// * `&[Export]` - A slice of `Export` structs representing the exports of the module. #[inline] + #[cfg(target_os = "windows")] pub fn exports(&self) -> &'a [Export] { self.pe.exports.as_slice() } + #[inline] + #[cfg(target_os = "linux")] + pub fn exports(&self) -> Vec { + let exports: Vec = self + .elf + .dynsyms + .iter() + .filter(|sym| sym.st_bind() == sym::STB_GLOBAL || sym.st_bind() == sym::STB_WEAK) + .collect(); + exports + } + /// Returns the address of the export with the given name, if it exists. /// /// # Arguments @@ -81,6 +131,7 @@ impl<'a> Module<'a> { /// /// * `Option
` - The address of the export with the given name, if it exists. #[inline] + #[cfg(target_os = "windows")] pub fn get_export_by_name(&self, name: &str) -> Option
{ self.pe .exports @@ -89,6 +140,20 @@ impl<'a> Module<'a> { .map(|e| (self.pe.image_base + e.rva).into()) } + #[inline] + #[cfg(target_os = "linux")] + pub fn get_export_by_name(&self, name: &str) -> Option
{ + let base_addr: usize = self.base().into(); + self.elf + .dynsyms + .iter() + .find(|sym| { + (sym.st_bind() == sym::STB_GLOBAL || sym.st_bind() == sym::STB_WEAK) + && self.elf.dynstrtab.get_at(sym.st_name) == Some(name) + }) + .map(|sym| ((base_addr as u64 + sym.st_value) as usize).into()) + } + /// Returns the address of the imported function with the given name, if it exists. /// /// # Arguments @@ -99,6 +164,7 @@ impl<'a> Module<'a> { /// /// * `Option
` - The address of the imported function with the given name, if it exists. #[inline] + #[cfg(target_os = "windows")] pub fn get_import_by_name(&self, name: &str) -> Option
{ self.pe .imports @@ -107,6 +173,17 @@ impl<'a> Module<'a> { .map(|i| (self.pe.image_base + i.rva).into()) } + #[inline] + #[cfg(target_os = "linux")] + pub fn get_import_by_name(&self, name: &str) -> Option
{ + let base_addr: usize = self.base().into(); + self.elf + .dynsyms + .iter() + .find(|sym| sym.is_import() && self.elf.dynstrtab.get_at(sym.st_name) == Some(name)) + .map(|sym| ((base_addr as u64 + sym.st_value) as usize).into()) + } + /// Returns a slice of the imported functions of the module. /// /// # Arguments @@ -117,10 +194,23 @@ impl<'a> Module<'a> { /// /// * `&[Import]` - A slice of `Import` structs representing the imported functions of the module. #[inline] + #[cfg(target_os = "windows")] pub fn imports(&self) -> &'a [Import] { self.pe.imports.as_slice() } + #[inline] + #[cfg(target_os = "linux")] + pub fn imports(&self) -> Vec { + let imports: Vec = self + .elf + .dynsyms + .iter() + .filter(|sym| sym.is_import()) + .collect(); + imports + } + /// Returns a slice of the section table entries in the module's PE header. /// /// # Arguments @@ -131,10 +221,17 @@ impl<'a> Module<'a> { /// /// * `&[SectionTable]` - A slice of `SectionTable` structs representing the section table entries in the module's PE header. #[inline] + #[cfg(target_os = "windows")] pub fn sections(&self) -> &[SectionTable] { self.pe.sections.as_slice() } + #[inline] + #[cfg(target_os = "linux")] + pub fn sections(&self) -> &[SectionHeader] { + self.elf.section_headers.as_slice() + } + /// Returns the size of the module. /// /// # Arguments @@ -145,6 +242,7 @@ impl<'a> Module<'a> { /// /// * `u32` - The size of the module. #[inline] + #[cfg(target_os = "windows")] pub fn size(&self) -> u32 { self.pe .header diff --git a/src/util/process.rs b/src/util/process.rs index 5197ba5..bd4fb1e 100644 --- a/src/util/process.rs +++ b/src/util/process.rs @@ -1,4 +1,4 @@ -use super::{Address, Module}; +use super::{Address, Module, ModuleEntry}; use anyhow::{bail, Result}; @@ -32,7 +32,11 @@ pub struct Process { handle: HANDLE, /// A HashMap containing the name of each module and its corresponding raw data. + #[cfg(target_os = "windows")] modules: HashMap>, + + #[cfg(target_os = "linux")] + modules: HashMap, } impl Process { @@ -91,6 +95,7 @@ impl Process { /// # Returns /// /// * `Option
` - The address of the first occurrence of the pattern if found, or `None` if the pattern was not found. + #[cfg(target_os = "windows")] pub fn find_pattern(&self, module_name: &str, pattern: &str) -> Option
{ let module = self.get_module_by_name(module_name)?; @@ -109,6 +114,30 @@ impl Process { None } + #[cfg(target_os = "linux")] + pub fn find_pattern(&self, module_name: &str, pattern: &str) -> Option
{ + let module = self.get_module_by_name(module_name)?; + + let pattern_bytes = Self::pattern_to_bytes(pattern); + + for (i, window) in module + .module_info + .data + .windows(pattern_bytes.len()) + .enumerate() + { + if window + .iter() + .zip(&pattern_bytes) + .all(|(&x, &y)| x == y as u8 || y == -1) + { + return Some(module.base() + i); + } + } + + None + } + /// Returns an optional `Module` instance by its name. /// /// # Arguments @@ -122,7 +151,8 @@ impl Process { pub fn get_module_by_name<'a>(&'a self, name: &'a str) -> Option> { self.modules .get(name) - .map(|data| Module::parse(name, data).unwrap()) + .map(|entry| Module::parse(name, entry).unwrap()) + // Module::parse(name, self.modules.get_mut(name)?).ok() } /// Returns a vector of `Module` instances parsed from the process's loaded modules. @@ -137,8 +167,8 @@ impl Process { pub fn modules(&self) -> Result> { let mut modules = Vec::new(); - for (name, data) in &self.modules { - modules.push(Module::parse(name, data)?); + for (name, entry) in &self.modules { + modules.push(Module::parse(name, entry)?); } Ok(modules) @@ -418,6 +448,15 @@ impl Process { Ok(()) } + #[cfg(target_os = "linux")] + fn read_elf_file(path: &PathBuf) -> Result> { + let mut file = File::open(path)?; + let mut data = Vec::new(); + file.read_to_end(&mut data)?; + + Ok(data) + } + fn get_transformed_module_name(path: PathBuf) -> Option { if let Ok(module_path) = path.into_os_string().into_string() { if let Some(module_name) = module_path.split('/').last() { @@ -436,27 +475,35 @@ impl Process { fn parse_loaded_modules(&mut self) -> Result<()> { let process = process::Process::new(self.id as i32)?; - let mut modules_info: HashMap = HashMap::new(); + let mut modules_info: HashMap = HashMap::new(); for mmap in process.maps()? { let mmap_path = match mmap.pathname { process::MMapPath::Path(path) => path, _ => continue, }; - let module_name = match Process::get_transformed_module_name(mmap_path) { + let module_name = match Process::get_transformed_module_name(mmap_path.clone()) { Some(new_path) => new_path, None => continue, }; + if module_name != "client.dll" + && module_name != "engine2.dll" + && module_name != "inputsystem.dll" + && module_name != "matchmaking.dll" + && module_name != "schemasystem.dll" + { + continue; + } let module_entry = modules_info .entry(module_name) - .or_insert_with(|| (mmap.address)); - *module_entry = ( - std::cmp::min(mmap.address.0, module_entry.0), - std::cmp::max(mmap.address.1, module_entry.1), + .or_insert_with(|| (mmap.address, mmap_path)); + module_entry.0 = ( + std::cmp::min(mmap.address.0, module_entry.0 .0), + std::cmp::max(mmap.address.1, module_entry.0 .1), ); } - for (module_name, address_space) in modules_info.into_iter() { + for (module_name, (address_space, path)) in modules_info.into_iter() { let (start, end) = address_space; let mut data = vec![0; (end - start + 1) as usize]; if let Ok(_) = self.read_memory_raw( @@ -464,7 +511,15 @@ impl Process { data.as_mut_ptr() as *mut _, data.len(), ) { - self.modules.insert(module_name, data); + self.modules.insert( + module_name, + ModuleEntry { + path: path.clone(), + start_addr: (start as usize).into(), + data: data, + module_file_data: Process::read_elf_file(&path)?, + }, + ); } } From 2314d4d492c2e9bd18263fe81e71e97a68dc0ad8 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Thu, 29 Feb 2024 22:23:52 +0200 Subject: [PATCH 03/16] Allow to add signed integers to Address variables --- src/dumper/offsets.rs | 2 +- src/util/address.rs | 8 ++++++-- src/util/process.rs | 14 ++++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/dumper/offsets.rs b/src/dumper/offsets.rs index d5810d1..59be15e 100644 --- a/src/dumper/offsets.rs +++ b/src/dumper/offsets.rs @@ -81,7 +81,7 @@ pub fn dump_offsets( let mut result: usize = 0; process.read_memory_raw( - address.add(start), + address.add(start.try_into().unwrap()), &mut result as *mut _ as *mut _, end - start, )?; diff --git a/src/util/address.rs b/src/util/address.rs index 3ddd41c..8af0b1d 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -18,8 +18,12 @@ impl Address { /// /// * `Address` - A new `Address` struct with the value of the current address plus the given value. #[inline] - pub fn add(&self, value: usize) -> Self { - Self(self.0 + value) + pub fn add(&self, value: i64) -> Self { + if value.is_negative() { + self.sub(value.wrapping_abs() as usize) + } else { + Self(self.0 + value as usize) + } } /// Returns true if the value of the address is zero. diff --git a/src/util/process.rs b/src/util/process.rs index bd4fb1e..5a0eec1 100644 --- a/src/util/process.rs +++ b/src/util/process.rs @@ -322,11 +322,12 @@ impl Process { length: Option, ) -> Result
{ // The displacement value can be negative. - let displacement = self.read_memory::(address.add(offset.unwrap_or(0x1)))?; + let displacement = + self.read_memory::(address.add(offset.unwrap_or(0x1).try_into().unwrap()))?; Ok(address - .add(length.unwrap_or(0x5)) - .add(displacement as usize)) + .add(length.unwrap_or(0x5).try_into().unwrap()) + .add(displacement.into())) } /// Resolves the absolute address of a RIP-relative address. @@ -348,11 +349,12 @@ impl Process { length: Option, ) -> Result
{ // The displacement value can be negative. - let displacement = self.read_memory::(address.add(offset.unwrap_or(0x3)))?; + let displacement = + self.read_memory::(address.add(offset.unwrap_or(0x3).try_into().unwrap()))?; Ok(address - .add(length.unwrap_or(0x7)) - .add(displacement as usize)) + .add(length.unwrap_or(0x7).try_into().unwrap()) + .add(displacement.into())) } /// Returns the process ID of the first process with the given name. From 0bb4e59be82edfa79eb33af2b70bd40412bbdee9 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Thu, 29 Feb 2024 22:25:17 +0200 Subject: [PATCH 04/16] Port "dump interfaces" to linux --- src/dumper/interfaces.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/dumper/interfaces.rs b/src/dumper/interfaces.rs index 1abca17..efd0801 100644 --- a/src/dumper/interfaces.rs +++ b/src/dumper/interfaces.rs @@ -109,8 +109,21 @@ pub fn dump_interfaces( if let Some(create_interface_export) = module.get_export_by_name("CreateInterface") { info!("Dumping interfaces in {}...", module.name); - let create_interface_address = - process.resolve_rip(create_interface_export, None, None)?; + let create_interface_address; + + #[cfg(target_os = "windows")] + { + create_interface_address = + process.resolve_rip(create_interface_export, None, None)?; + } + + #[cfg(target_os = "linux")] + { + let create_interface_fn = + process.resolve_jmp(create_interface_export, None, None)?; + create_interface_address = + process.resolve_rip(create_interface_fn.add(0x10), None, None)?; + } let mut node = process.read_memory::<*mut InterfaceNode>(create_interface_address)?; From fe920e142624d0f90741f5dffff0ba8fbf78765f Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Fri, 1 Mar 2024 19:42:44 +0200 Subject: [PATCH 05/16] Rename `util` directory to `os` --- src/{util => os}/address.rs | 0 src/{util => os}/mod.rs | 0 src/{util => os}/module.rs | 0 src/{util => os}/process.rs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/{util => os}/address.rs (100%) rename src/{util => os}/mod.rs (100%) rename src/{util => os}/module.rs (100%) rename src/{util => os}/process.rs (100%) diff --git a/src/util/address.rs b/src/os/address.rs similarity index 100% rename from src/util/address.rs rename to src/os/address.rs diff --git a/src/util/mod.rs b/src/os/mod.rs similarity index 100% rename from src/util/mod.rs rename to src/os/mod.rs diff --git a/src/util/module.rs b/src/os/module.rs similarity index 100% rename from src/util/module.rs rename to src/os/module.rs diff --git a/src/util/process.rs b/src/os/process.rs similarity index 100% rename from src/util/process.rs rename to src/os/process.rs From 5daaee321ad60d3a9922d9f0f99fd33869966d17 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Fri, 1 Mar 2024 20:44:18 +0200 Subject: [PATCH 06/16] Replace `Address` type with `usize` --- src/dumper/interfaces.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dumper/interfaces.rs b/src/dumper/interfaces.rs index c91578b..20b299f 100644 --- a/src/dumper/interfaces.rs +++ b/src/dumper/interfaces.rs @@ -71,7 +71,7 @@ pub fn dump_interfaces( let create_interface_fn = process.resolve_jmp(create_interface_export, None, None)?; create_interface_address = - process.resolve_rip(create_interface_fn.add(0x10), None, None)?; + process.resolve_rip(create_interface_fn + 0x10, None, None)?; } let mut node = process.read_memory::<*mut InterfaceNode>(create_interface_address)?; From ede86928d89a208b2d518bc0306ab54590f91965 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Fri, 1 Mar 2024 20:44:54 +0200 Subject: [PATCH 07/16] Handle situations when displacement is negative --- src/os/process.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/os/process.rs b/src/os/process.rs index d8e2624..4238732 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -199,7 +199,12 @@ impl Process { // The displacement value can be negative. let displacement = self.read_memory::(address + offset.unwrap_or(0x1))?; - Ok((address + displacement as usize) + length.unwrap_or(0x5)) + let final_address = if displacement.is_negative() { + address - displacement.wrapping_abs() as usize + } else { + address + displacement as usize + } + length.unwrap_or(0x5); + Ok(final_address) } pub fn resolve_rip( @@ -211,7 +216,12 @@ impl Process { // The displacement value can be negative. let displacement = self.read_memory::(address + offset.unwrap_or(0x3))?; - Ok((address + displacement as usize) + length.unwrap_or(0x7)) + let final_address = if displacement.is_negative() { + address - displacement.wrapping_abs() as usize + } else { + address + displacement as usize + } + length.unwrap_or(0x7); + Ok(final_address) } #[cfg(target_os = "windows")] From 1ef287c5352ae485a58599ba689325a5cf2ac114 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Fri, 1 Mar 2024 21:00:53 +0200 Subject: [PATCH 08/16] Use data from `.so` file instead of the one loaded into the process --- src/os/module.rs | 3 +-- src/os/process.rs | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/os/module.rs b/src/os/module.rs index 05272fa..1a30980 100644 --- a/src/os/module.rs +++ b/src/os/module.rs @@ -16,7 +16,6 @@ pub struct ModuleEntry { pub path: PathBuf, pub start_addr: usize, pub data: Vec, - pub module_file_data: Vec, } /// Represents a module loaded in a Windows process. pub struct Module<'a> { @@ -54,7 +53,7 @@ impl<'a> Module<'a> { // parse the elf #[cfg(target_os = "linux")] pub fn parse(name: &'a str, module_entry: &'a ModuleEntry) -> Result { - let elf = Elf::parse(&module_entry.module_file_data)?; + let elf = Elf::parse(&module_entry.data)?; Ok(Self { name, module_info: module_entry, diff --git a/src/os/process.rs b/src/os/process.rs index 4238732..f6a97c7 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -355,19 +355,14 @@ impl Process { for (module_name, (address_space, path)) in modules_info.into_iter() { let (start, end) = address_space; - let mut data = vec![0; (end - start + 1) as usize]; - if let Ok(_) = self.read_memory_raw( - (start as usize).into(), - data.as_mut_ptr() as *mut _, - data.len(), - ) { + // let mut data = vec![0; (end - start + 1) as usize]; + if let Ok(data) = Process::read_elf_file(&path) { self.modules.insert( module_name, ModuleEntry { path: path.clone(), start_addr: start as usize, data: data, - module_file_data: Process::read_elf_file(&path)?, }, ); } From 10a908ab6f6c88c8b9b88e48cb1f18491da26b32 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 5 Mar 2024 01:16:32 +0200 Subject: [PATCH 09/16] Port `schemasystems` dumper to linux --- src/sdk/schema_system.rs | 17 +++++++++++------ src/sdk/schema_system_type_scope.rs | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/sdk/schema_system.rs b/src/sdk/schema_system.rs index 07dc8b2..4e595e0 100644 --- a/src/sdk/schema_system.rs +++ b/src/sdk/schema_system.rs @@ -13,10 +13,13 @@ pub struct SchemaSystem<'a> { impl<'a> SchemaSystem<'a> { pub fn new(process: &'a Process) -> Result { - let mut address = process.find_pattern( - "schemasystem.dll", - "48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28" - ).expect("unable to find schema system pattern"); + let mut address = process + .find_pattern( + "schemasystem.dll", + "48 8D 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 8d 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 ? ? ? c3" + // "48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28" + ) + .expect("unable to find schema system pattern"); address = process.resolve_rip(address, None, None)?; @@ -24,13 +27,15 @@ impl<'a> SchemaSystem<'a> { } pub fn type_scopes(&self) -> Result> { - let size = self.process.read_memory::(self.address + 0x190)?; + // let size = self.process.read_memory::(self.address + 0x190)?; + let size = self.process.read_memory::(self.address + 0x1f8)?; if size == 0 { bail!("no type scopes found"); } - let data = self.process.read_memory::(self.address + 0x198)?; + // let data = self.process.read_memory::(self.address + 0x198)?; + let data = self.process.read_memory::(self.address + 0x200)?; let mut addresses = vec![0; size as usize]; diff --git a/src/sdk/schema_system_type_scope.rs b/src/sdk/schema_system_type_scope.rs index 1db085e..945e1ad 100644 --- a/src/sdk/schema_system_type_scope.rs +++ b/src/sdk/schema_system_type_scope.rs @@ -17,7 +17,8 @@ impl<'a> SchemaSystemTypeScope<'a> { pub fn classes(&self) -> Result> { let declared_classes = self .process - .read_memory::>(self.address + 0x5B8)?; + .read_memory::>(self.address + 0x620)?; + // .read_memory::>(self.address + 0x5B8)?; let classes: Vec = declared_classes .elements(self.process)? From 96da055d1af3ec90141cb684b1f7f81cc0cb9821 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 5 Mar 2024 13:40:07 +0200 Subject: [PATCH 10/16] Move platform specific configs in config.rs --- src/config.rs | 33 ++++++++++++++ src/main.rs | 2 +- src/os/process.rs | 69 ++++++++++------------------- src/sdk/schema_system.rs | 18 ++++---- src/sdk/schema_system_type_scope.rs | 7 ++- 5 files changed, 72 insertions(+), 57 deletions(-) diff --git a/src/config.rs b/src/config.rs index 78d12e7..7bdd914 100644 --- a/src/config.rs +++ b/src/config.rs @@ -39,3 +39,36 @@ pub struct Signature { pub pattern: String, pub operations: Vec, } + +#[derive(Debug)] +pub struct SchemaSystemConfig { + pub module_name: &'static str, + pub pattern: &'static str, + pub type_scope_size_offset: usize, + pub type_scope_data_offset: usize, + pub declared_classes_offset: usize, +} + +#[cfg(target_os = "windows")] +pub const SCHEMA_CONF: SchemaSystemConfig = SchemaSystemConfig { + module_name: "schemasystem.dll", + pattern: "48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28", + type_scope_size_offset: 0x190, + type_scope_data_offset: 0x198, + declared_classes_offset: 0x5B8, +}; + +#[cfg(target_os = "linux")] +pub const SCHEMA_CONF: SchemaSystemConfig = SchemaSystemConfig { + module_name: "libschemasystem.so", + pattern: "48 8D 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 8d 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 ? ? ? c3", + type_scope_size_offset: 0x1f8, + type_scope_data_offset: 0x200, + declared_classes_offset: 0x620, +}; + +#[cfg(target_os = "windows")] +pub const PROC_NAME: &str = "cs2.exe"; + +#[cfg(target_os = "linux")] +pub const PROC_NAME: &str = "cs2"; diff --git a/src/main.rs b/src/main.rs index a3c63f6..a649573 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,7 +93,7 @@ fn main() -> Result<()> { // Create the output directory if it doesn't exist. fs::create_dir_all(&output)?; - let mut process = Process::new("cs2.exe")?; + let mut process = Process::new(config::PROC_NAME)?; let now = Instant::now(); diff --git a/src/os/process.rs b/src/os/process.rs index f6a97c7..c25681a 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -56,8 +56,8 @@ impl Process { } #[cfg(target_os = "linux")] - pub fn new(process_name: &str) -> Result { - let id = Self::get_process_id_by_name(process_name.strip_suffix(".exe").unwrap())?; + pub fn new(name: &str) -> Result { + let id = Self::get_process_id_by_name(name)?; let mut process = Self { id, modules: HashMap::new(), @@ -298,29 +298,6 @@ impl Process { Ok(()) } - #[cfg(target_os = "linux")] - fn read_elf_file(path: &PathBuf) -> Result> { - let mut file = File::open(path)?; - let mut data = Vec::new(); - file.read_to_end(&mut data)?; - - Ok(data) - } - - fn get_transformed_module_name(path: PathBuf) -> Option { - if let Ok(module_path) = path.into_os_string().into_string() { - if let Some(module_name) = module_path.split('/').last() { - if module_name.starts_with("lib") && module_name.ends_with(".so") { - return Some(format!( - "{}.dll", - module_name.strip_prefix("lib")?.strip_suffix(".so")? - )); - } - } - } - None - } - #[cfg(target_os = "linux")] fn parse_loaded_modules(&mut self) -> Result<()> { let process = process::Process::new(self.id as i32)?; @@ -328,35 +305,37 @@ impl Process { let mut modules_info: HashMap = HashMap::new(); for mmap in process.maps()? { - let mmap_path = match mmap.pathname { + let module_path = match mmap.pathname { process::MMapPath::Path(path) => path, _ => continue, }; - let module_name = match Process::get_transformed_module_name(mmap_path.clone()) { - Some(new_path) => new_path, - None => continue, + let get_module_name = |path: &PathBuf| -> Option { + path.file_name() + .and_then(|name| name.to_str()) + .filter(|name| name.starts_with("lib") && name.ends_with(".so")) + .map(|name| name.to_string()) }; - if module_name != "client.dll" - && module_name != "engine2.dll" - && module_name != "inputsystem.dll" - && module_name != "matchmaking.dll" - && module_name != "schemasystem.dll" - { - continue; + if let Some(module_name) = get_module_name(&module_path) { + let module_entry = modules_info + .entry(module_name) + .or_insert_with(|| (mmap.address, module_path)); + module_entry.0 = ( + std::cmp::min(mmap.address.0, module_entry.0 .0), + std::cmp::max(mmap.address.1, module_entry.0 .1), + ); } - let module_entry = modules_info - .entry(module_name) - .or_insert_with(|| (mmap.address, mmap_path)); - module_entry.0 = ( - std::cmp::min(mmap.address.0, module_entry.0 .0), - std::cmp::max(mmap.address.1, module_entry.0 .1), - ); } for (module_name, (address_space, path)) in modules_info.into_iter() { let (start, end) = address_space; - // let mut data = vec![0; (end - start + 1) as usize]; - if let Ok(data) = Process::read_elf_file(&path) { + let read_elf_file = |path: &PathBuf| -> Result> { + let mut file = File::open(path)?; + let mut data = Vec::new(); + file.read_to_end(&mut data)?; + + Ok(data) + }; + if let Ok(data) = read_elf_file(&path) { self.modules.insert( module_name, ModuleEntry { diff --git a/src/sdk/schema_system.rs b/src/sdk/schema_system.rs index 4e595e0..52816f9 100644 --- a/src/sdk/schema_system.rs +++ b/src/sdk/schema_system.rs @@ -6,6 +6,8 @@ use super::SchemaSystemTypeScope; use crate::os::Process; +use crate::config::SCHEMA_CONF; + pub struct SchemaSystem<'a> { process: &'a Process, address: usize, @@ -14,11 +16,7 @@ pub struct SchemaSystem<'a> { impl<'a> SchemaSystem<'a> { pub fn new(process: &'a Process) -> Result { let mut address = process - .find_pattern( - "schemasystem.dll", - "48 8D 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 8d 05 ? ? ? ? c3 ? ? ? 00 00 00 00 00 48 ? ? ? c3" - // "48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28" - ) + .find_pattern(SCHEMA_CONF.module_name, SCHEMA_CONF.pattern) .expect("unable to find schema system pattern"); address = process.resolve_rip(address, None, None)?; @@ -27,15 +25,17 @@ impl<'a> SchemaSystem<'a> { } pub fn type_scopes(&self) -> Result> { - // let size = self.process.read_memory::(self.address + 0x190)?; - let size = self.process.read_memory::(self.address + 0x1f8)?; + let size = self + .process + .read_memory::(self.address + SCHEMA_CONF.type_scope_size_offset)?; if size == 0 { bail!("no type scopes found"); } - // let data = self.process.read_memory::(self.address + 0x198)?; - let data = self.process.read_memory::(self.address + 0x200)?; + let data = self + .process + .read_memory::(self.address + SCHEMA_CONF.type_scope_data_offset)?; let mut addresses = vec![0; size as usize]; diff --git a/src/sdk/schema_system_type_scope.rs b/src/sdk/schema_system_type_scope.rs index 945e1ad..c576408 100644 --- a/src/sdk/schema_system_type_scope.rs +++ b/src/sdk/schema_system_type_scope.rs @@ -4,6 +4,8 @@ use super::{SchemaClassInfo, SchemaTypeDeclaredClass, UtlTsHash}; use crate::os::Process; +use crate::config::SCHEMA_CONF; + pub struct SchemaSystemTypeScope<'a> { process: &'a Process, address: usize, @@ -17,8 +19,9 @@ impl<'a> SchemaSystemTypeScope<'a> { pub fn classes(&self) -> Result> { let declared_classes = self .process - .read_memory::>(self.address + 0x620)?; - // .read_memory::>(self.address + 0x5B8)?; + .read_memory::>( + self.address + SCHEMA_CONF.declared_classes_offset, + )?; let classes: Vec = declared_classes .elements(self.process)? From c19eaf1756370963b537f58854cb16ba1125ea7a Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 5 Mar 2024 18:01:00 +0200 Subject: [PATCH 11/16] Fix compilation errors on windows --- src/os/mod.rs | 4 +++- src/os/module.rs | 4 ++-- src/os/process.rs | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/os/mod.rs b/src/os/mod.rs index cc86f99..266a781 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -1,5 +1,7 @@ -pub use module::Module; +#[cfg(target_os = "linux")] pub use module::ModuleEntry; + +pub use module::Module; pub use process::Process; pub mod module; diff --git a/src/os/module.rs b/src/os/module.rs index 1a30980..fc2e91d 100644 --- a/src/os/module.rs +++ b/src/os/module.rs @@ -94,7 +94,7 @@ impl<'a> Module<'a> { #[inline] #[cfg(target_os = "windows")] pub fn imports(&self) -> &[Import] { - self.pe.imports + &self.pe.imports } #[inline] @@ -158,7 +158,7 @@ impl<'a> Module<'a> { #[inline] #[cfg(target_os = "windows")] pub fn sections(&self) -> &[SectionTable] { - self.pe.sections + &self.pe.sections } #[inline] diff --git a/src/os/process.rs b/src/os/process.rs index c25681a..710268d 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -1,4 +1,6 @@ -use super::{Module, ModuleEntry}; +use super::Module; +#[cfg(target_os = "linux")] +use super::ModuleEntry; use anyhow::{bail, Result}; @@ -66,7 +68,7 @@ impl Process { Ok(process) } #[cfg(target_os = "windows")] - pub fn find_pattern(&self, module_name: &str, pattern: &str) -> Option
{ + pub fn find_pattern(&self, module_name: &str, pattern: &str) -> Option { let module = self.get_module_by_name(module_name)?; let pattern_bytes = Self::pattern_to_bytes(pattern); From 6a1600d432146c569d72d2dc17299d6425b418bc Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Wed, 6 Mar 2024 10:34:47 +0200 Subject: [PATCH 12/16] Solve `unused imports` warning --- src/os/module.rs | 12 ++++++------ src/os/process.rs | 7 +++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/os/module.rs b/src/os/module.rs index fc2e91d..2cc4ec5 100644 --- a/src/os/module.rs +++ b/src/os/module.rs @@ -1,13 +1,13 @@ use anyhow::Result; -use goblin::pe::export::Export; -use goblin::pe::import::Import; -use goblin::pe::options::ParseOptions; -use goblin::pe::section_table::SectionTable; -use goblin::pe::PE; +#[cfg(target_os = "windows")] +use goblin::pe::{ + export::Export, import::Import, options::ParseOptions, section_table::SectionTable, PE, +}; #[cfg(target_os = "linux")] -use goblin::elf::{program_header, sym, Elf, SectionHeader}; +use goblin::elf::{sym, Elf, SectionHeader}; +#[cfg(target_os = "linux")] use std::path::PathBuf; #[cfg(target_os = "linux")] diff --git a/src/os/process.rs b/src/os/process.rs index 710268d..2c9607c 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -5,10 +5,13 @@ use super::ModuleEntry; use anyhow::{bail, Result}; use std::collections::HashMap; -use std::ffi::{c_void, CStr}; +use std::ffi::c_void; use std::mem; -use std::ptr; +#[cfg(target_os = "windows")] +use std::ffi::CStr; +#[cfg(target_os = "windows")] +use std::ptr; #[cfg(target_os = "windows")] use windows::Win32::{ Foundation::{CloseHandle, HANDLE}, From 7e573bdcb688bb4945429c593ffe319de2d06ec5 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Wed, 6 Mar 2024 10:35:48 +0200 Subject: [PATCH 13/16] Add first offsets config for linux --- config_linux.json | 132 ++++++++++++++++++++++++++++++++++++++++++ src/config.rs | 6 ++ src/dumper/offsets.rs | 4 +- src/main.rs | 4 +- 4 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 config_linux.json diff --git a/config_linux.json b/config_linux.json new file mode 100644 index 0000000..d700ac7 --- /dev/null +++ b/config_linux.json @@ -0,0 +1,132 @@ +{ + "signatures": [ + { + "name": "dwBuildNumber", + "module": "libengine2.so", + "pattern": "89 15 ? ? ? ? 48 83 ? ? 48 8D 3D ? ? ? ?", + "operations": [ + { + "type": "rip", + "offset": 2, + "length": 6 + } + ] + }, + { + "name": "dwNetworkGameClient_deltaTick", + "module": "libengine2.so", + "pattern": "89 83 ? ? ? ? B8 01", + "operations": [ + { + "type": "slice", + "start": 2, + "end": 4 + } + ] + }, + { + "name": "dwEntityList", + "module": "libclient.so", + "pattern": "48 8B 3D ? ? ? ? 44 89 E3 45 89 E6 C1 ? 0E", + "operations": [ + { + "type": "rip" + } + ] + }, + { + "name": "dwForceAttack", + "module": "libclient.so", + "pattern": "4c 8d ? ? ? ? ? 4d 89 ? 48 89 ? ? ? ? ? eb", + "operations": [ + { + "type": "rip" + }, + { + "type": "add", + "value": 48 + } + ] + }, + { + "name": "dwForceAttack2", + "module": "libclient.so", + "pattern": "4c 8d ? ? ? ? ? 48 8d ? ? ? ? ? 48 89 ? ? ? ? ? e8 ? ? ? ? 49 ? ? ? 31 d2 48 c7 ? ? ? ? ? ? 08", + "operations": [ + { + "type": "rip" + }, + { + "type": "add", + "value": 48 + } + ] + }, + { + "name": "dwGameEntitySystem", + "module": "libclient.so", + "pattern": "48 89 3d ? ? ? ? e9 ? ? ? ? 55", + "operations": [ + { + "type": "rip" + } + ] + }, + { + "name": "dwGameEntitySystem_getHighestEntityIndex", + "module": "libclient.so", + "pattern": "8b 87 ? ? ? ? c3 66 ? ? ? ? ? ? ? ? 8b 97", + "operations": [ + { + "type": "slice", + "start": 2, + "end": 4 + } + ] + }, + { + "name": "dwGameRules", + "module": "libclient.so", + "pattern": "48 89 3d ? ? ? ? 8b", + "operations": [ + { + "type": "rip" + } + ] + }, + { + "name": "dwLocalPlayerController", + "module": "libclient.so", + "pattern": "48 8B 15 ? ? ? ? 31 C0 48 85 D2 74 5C", + "operations": [ + { + "type": "rip" + } + ] + }, + { + "name": "dwLocalPlayerPawn", + "module": "libclient.so", + "pattern": "48 8D 05 ? ? ? ? C3 ? ? ? 00 00 00 00 00 C7 47 40", + "operations": [ + { + "type": "rip" + }, + { + "type": "add", + "value": 56 + } + ] + }, + { + "name": "dwViewMatrix", + "module": "libclient.so", + "pattern": "4c 8d 05 ? ? ? ? 48 ? ? 48 8d ? ? ? ? ? e8 ? ? ? ? 8b", + "operations": [ + { + "type": "rip" + } + ] + } + ] +} diff --git a/src/config.rs b/src/config.rs index 7bdd914..875e390 100644 --- a/src/config.rs +++ b/src/config.rs @@ -72,3 +72,9 @@ pub const PROC_NAME: &str = "cs2.exe"; #[cfg(target_os = "linux")] pub const PROC_NAME: &str = "cs2"; + +#[cfg(target_os = "windows")] +pub const OFFSETS_CONF: &str = "config.json"; + +#[cfg(target_os = "linux")] +pub const OFFSETS_CONF: &str = "config_linux.json"; diff --git a/src/dumper/offsets.rs b/src/dumper/offsets.rs index d098b2c..f88510e 100644 --- a/src/dumper/offsets.rs +++ b/src/dumper/offsets.rs @@ -7,8 +7,8 @@ use simplelog::{debug, error, info}; use super::{generate_files, Entries, Entry}; use crate::builder::FileBuilderEnum; -use crate::config::Config; use crate::config::Operation::*; +use crate::config::{self, Config}; use crate::os::Process; pub fn dump_offsets( @@ -17,7 +17,7 @@ pub fn dump_offsets( file_path: &str, indent: usize, ) -> Result<()> { - let file = File::open("config.json")?; + let file = File::open(config::OFFSETS_CONF)?; let config: Config = serde_json::from_reader(file)?; diff --git a/src/main.rs b/src/main.rs index a649573..0982a23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,8 +86,8 @@ fn main() -> Result<()> { TermLogger::init(log_level, config, TerminalMode::Mixed, ColorChoice::Auto)?; - if !Path::new("config.json").exists() { - bail!("Missing config.json file"); + if !Path::new(config::OFFSETS_CONF).exists() { + bail!("Missing {} file", config::OFFSETS_CONF); } // Create the output directory if it doesn't exist. From e12cfcc226c7c73a4130ee878a636ba9dd5a5dbf Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Wed, 6 Mar 2024 10:40:56 +0200 Subject: [PATCH 14/16] Solve unused imports on windows --- src/os/process.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/os/process.rs b/src/os/process.rs index 2c9607c..ee813b8 100644 --- a/src/os/process.rs +++ b/src/os/process.rs @@ -22,8 +22,11 @@ use windows::Win32::{ #[cfg(target_os = "linux")] use procfs::process::{self, all_processes}; +#[cfg(target_os = "linux")] use std::fs::File; +#[cfg(target_os = "linux")] use std::io::{Read, Seek, SeekFrom}; +#[cfg(target_os = "linux")] use std::path::{Path, PathBuf}; /// Represents a Windows process. From fa963c7d158686e85fd86772f974196c6be95e99 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Wed, 6 Mar 2024 10:41:33 +0200 Subject: [PATCH 15/16] Remove duplicate `#[inline]` --- src/os/module.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/os/module.rs b/src/os/module.rs index 2cc4ec5..5c1767f 100644 --- a/src/os/module.rs +++ b/src/os/module.rs @@ -135,7 +135,6 @@ impl<'a> Module<'a> { #[inline] #[cfg(target_os = "windows")] - #[inline] pub fn import_by_name(&self, name: &str) -> Option { self.pe .imports From cfb038485f156666f9a72eba0f9c2399f5e54f7b Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Wed, 6 Mar 2024 10:53:42 +0200 Subject: [PATCH 16/16] Remove deprecated `address.rs` --- src/os/address.rs | 215 ---------------------------------------------- 1 file changed, 215 deletions(-) delete mode 100644 src/os/address.rs diff --git a/src/os/address.rs b/src/os/address.rs deleted file mode 100644 index 8af0b1d..0000000 --- a/src/os/address.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::fmt::{LowerHex, UpperHex}; -use std::ops::{Add, AddAssign, Sub, SubAssign}; - -/// Represents a memory address. -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] -#[repr(transparent)] -pub struct Address(pub usize); - -impl Address { - /// Adds the given value to the current address and returns a new `Address`. - /// - /// # Arguments - /// - /// * `&self` - A reference to the `Address` struct. - /// * `value` - The value to add to the current address. - /// - /// # Returns - /// - /// * `Address` - A new `Address` struct with the value of the current address plus the given value. - #[inline] - pub fn add(&self, value: i64) -> Self { - if value.is_negative() { - self.sub(value.wrapping_abs() as usize) - } else { - Self(self.0 + value as usize) - } - } - - /// Returns true if the value of the address is zero. - /// - /// # Arguments - /// - /// * `&self` - A reference to the `Address` struct. - /// - /// # Returns - /// - /// * `bool` - True if the value of the address is zero, false otherwise. - #[inline] - pub fn is_zero(&self) -> bool { - self.0 == 0 - } - - /// Subtracts a value from the current address and returns a new `Address`. - /// - /// # Arguments - /// - /// * `&self` - A reference to the `Address` struct. - /// * `value` - The value to subtract from the current address. - /// - /// # Returns - /// - /// * `Address` - A new `Address` struct with the value of the current address minus the given value. - #[inline] - pub fn sub(&self, value: usize) -> Self { - Self(self.0 - value) - } - - /// Returns a raw pointer to the underlying data as a `*const T`. - /// - /// # Arguments - /// - /// * `&self` - A reference to the `Address` struct. - /// - /// # Returns - /// - /// * `*const T` - A raw pointer to the underlying data as a `*const T`. - #[inline] - pub fn as_ptr(&self) -> *const T { - self.0 as *const T - } - - /// Returns a mutable pointer to the underlying data. - /// - /// # Arguments - /// - /// * `&self` - A reference to the `Address` struct. - /// - /// # Returns - /// - /// * `*mut T` - A mutable pointer to the underlying data. - #[inline] - pub fn as_mut_ptr(&self) -> *mut T { - self.0 as *mut T - } -} - -/// Converts a `usize` value to an `Address` struct. -impl From for Address { - fn from(value: usize) -> Self { - Self(value) - } -} - -/// Converts a raw pointer to a `usize` value and creates an `Address` instance from it. -impl From<*const u8> for Address { - fn from(value: *const u8) -> Self { - Self(value as usize) - } -} - -/// Converts a raw pointer to a `usize` value and wraps it in an `Address` struct. -impl From<*mut u8> for Address { - fn from(value: *mut u8) -> Self { - Self(value as usize) - } -} - -/// Converts an `Address` struct to a `usize` value. -impl From
for usize { - fn from(value: Address) -> Self { - value.0 - } -} - -/// Converts an `Address` struct to a raw pointer to an unsigned 8-bit integer. -impl From
for *const u8 { - fn from(value: Address) -> Self { - value.0 as *const u8 - } -} - -/// Converts an `Address` struct to a raw pointer to a mutable unsigned 8-bit integer. -impl From
for *mut u8 { - fn from(value: Address) -> Self { - value.0 as *mut u8 - } -} - -/// Implements the addition of a `usize` value to an `Address` value. -impl Add for Address { - type Output = Self; - - /// Adds a `usize` value to an `Address` value and returns the result. - fn add(self, rhs: usize) -> Self::Output { - Self(self.0 + rhs) - } -} - -/// Implements the addition of two `Address` instances. -impl Add
for Address { - type Output = Self; - - /// Adds two `Address` instances and returns a new `Address`. - fn add(self, rhs: Address) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Implements the `AddAssign` trait for `Address` struct. -impl AddAssign for Address { - /// Adds the given `rhs` value to the `Address` struct. - fn add_assign(&mut self, rhs: usize) { - self.0 += rhs; - } -} - -/// Implements the `AddAssign` trait for `Address`. -impl AddAssign
for Address { - /// Adds the given `rhs` value to the `Address` struct. - fn add_assign(&mut self, rhs: Address) { - self.0 += rhs.0; - } -} - -/// Implements the subtraction of a `usize` from an `Address`. -impl Sub for Address { - type Output = Self; - - /// Subtracts the given `rhs` from `&self`. - fn sub(self, rhs: usize) -> Self::Output { - Self(self.0 - rhs) - } -} - -/// Implements the subtraction operation for `Address`. -impl Sub
for Address { - type Output = Self; - - /// Subtracts the given `rhs` from `&self`. - fn sub(self, rhs: Address) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -/// Implements the subtraction assignment operation for `Address` and `usize`. -impl SubAssign for Address { - /// Subtracts the given `rhs` from the `Address`. - fn sub_assign(&mut self, rhs: usize) { - self.0 -= rhs; - } -} - -/// Implements the subtraction assignment operator for `Address`. -impl SubAssign
for Address { - /// Subtracts the value of `rhs` from `&self`. - fn sub_assign(&mut self, rhs: Address) { - self.0 -= rhs.0; - } -} - -/// Implements the `UpperHex` trait for the `Address` struct. -impl UpperHex for Address { - /// Formats the value of `&self` using the `write!` macro and the `UpperHex` format specifier. - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:#X}", self.0) - } -} - -/// Implements the `LowerHex` trait for the `Address` struct. -impl LowerHex for Address { - /// Formats the value of `&self` using the `write!` macro and the `LowerHex` format specifier. - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:#x}", self.0) - } -}