use crate::memory::MemoryError;
use crate::memory_aobscan;
use crate::memory_hook::Architecture;
use crate::memory_resolver::MemoryAddress;
#[derive(Clone, Debug)]
pub enum AddressStrategy {
StaticPattern(String),
AobPattern {
pattern: String,
offset: i64,
},
AobPatternWithRange {
pattern: String,
start_address: usize,
length: usize,
offset: i64,
},
}
impl AddressStrategy {
pub fn static_pattern(pattern: impl Into<String>) -> Self {
AddressStrategy::StaticPattern(pattern.into())
}
pub fn aob_pattern(pattern: impl Into<String>) -> Self {
AddressStrategy::AobPattern {
pattern: pattern.into(),
offset: 0,
}
}
pub fn aob_pattern_with_offset(pattern: impl Into<String>, offset: i64) -> Self {
AddressStrategy::AobPattern {
pattern: pattern.into(),
offset,
}
}
pub fn aob_pattern_with_range(
pattern: impl Into<String>,
start_address: usize,
length: usize,
) -> Self {
AddressStrategy::AobPatternWithRange {
pattern: pattern.into(),
start_address,
length,
offset: 0,
}
}
pub fn aob_pattern_with_range_and_offset(
pattern: impl Into<String>,
start_address: usize,
length: usize,
offset: i64,
) -> Self {
AddressStrategy::AobPatternWithRange {
pattern: pattern.into(),
start_address,
length,
offset,
}
}
pub fn is_aob_scan(&self) -> bool {
matches!(
self,
AddressStrategy::AobPattern { .. } | AddressStrategy::AobPatternWithRange { .. }
)
}
pub fn is_static_pattern(&self) -> bool {
matches!(self, AddressStrategy::StaticPattern(_))
}
pub fn pattern(&self) -> &str {
match self {
AddressStrategy::StaticPattern(p) => p,
AddressStrategy::AobPattern { pattern, .. } => pattern,
AddressStrategy::AobPatternWithRange { pattern, .. } => pattern,
}
}
pub fn build_memory_address(
&self,
architecture: Architecture,
) -> Result<MemoryAddress, MemoryError> {
match self {
AddressStrategy::StaticPattern(pattern) => {
match architecture {
Architecture::X64 => MemoryAddress::new_x64(pattern).map_err(|e| {
MemoryError::InvalidAddress(format!(
"Failed to parse x64 pattern '{}': {}",
pattern, e
))
}),
Architecture::X86 => MemoryAddress::new_x86(pattern).map_err(|e| {
MemoryError::InvalidAddress(format!(
"Failed to parse x86 pattern '{}': {}",
pattern, e
))
}),
}
}
_ => Err(MemoryError::InvalidAddress(
"build_memory_address only supports StaticPattern strategy".to_string(),
)),
}
}
pub fn resolve(
&self,
handle: windows::Win32::Foundation::HANDLE,
pid: u32,
architecture: Architecture,
) -> Result<usize, MemoryError> {
match self {
AddressStrategy::StaticPattern(pattern) => {
let mem_addr = match architecture {
Architecture::X64 => MemoryAddress::new_x64(pattern).map_err(|e| {
MemoryError::InvalidAddress(format!(
"Failed to parse x64 pattern '{}': {}",
pattern, e
))
})?,
Architecture::X86 => MemoryAddress::new_x86(pattern).map_err(|e| {
MemoryError::InvalidAddress(format!(
"Failed to parse x86 pattern '{}': {}",
pattern, e
))
})?,
};
mem_addr.resolve_address(handle, pid).map_err(|e| {
MemoryError::InvalidAddress(format!(
"Failed to resolve address '{}': {}",
pattern, e
))
})
}
AddressStrategy::AobPattern { pattern, offset } => {
let results = memory_aobscan::AobScanBuilder::new(handle)
.pattern_str(pattern)
.map_err(|e| MemoryError::InvalidAddress(format!("AOB scan failed: {}", e)))?
.scan()
.map_err(|e| MemoryError::InvalidAddress(format!("AOB scan failed: {}", e)))?;
if results.is_empty() {
return Err(MemoryError::InvalidAddress(format!(
"AOB pattern '{}' not found",
pattern
)));
}
Ok((results[0] as i64 + offset) as usize)
}
AddressStrategy::AobPatternWithRange {
pattern,
start_address,
length,
offset,
} => {
let mut builder = memory_aobscan::AobScanBuilder::new(handle)
.pattern_str(pattern)
.map_err(|e| MemoryError::InvalidAddress(format!("AOB scan failed: {}", e)))?;
if *start_address != 0 {
builder = builder.start_address(*start_address);
}
if *length != 0 {
builder = builder.length(*length);
}
let results = builder
.scan()
.map_err(|e| MemoryError::InvalidAddress(format!("AOB scan failed: {}", e)))?;
if results.is_empty() {
return Err(MemoryError::InvalidAddress(format!(
"AOB pattern '{}' not found",
pattern
)));
}
Ok((results[0] as i64 + offset) as usize)
}
}
}
}