| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- from abc import ABC, abstractmethod
- from typing import List, Tuple, Dict, Optional
- import sys
- import os
- # Agregar el directorio padre al path para importar config
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- from config import MEMORY_SEARCH_CONFIG, UI_MESSAGES
- from core.memory_manager import MemoryManager
- class PatternSearcher(ABC):
- """Interfaz base para buscadores de patrones (Strategy Pattern)"""
-
- def __init__(self):
- pass
-
- @abstractmethod
- def get_patterns(self) -> Dict[str, Tuple[bytes, List[str]]]:
- """Retorna los patrones a buscar"""
- pass
-
- @abstractmethod
- def search(self, memory_manager: MemoryManager) -> List[Tuple[str, int]]:
- """Busca los patrones en memoria"""
- pass
-
- def pattern_matches(self, data: bytes, pattern: bytes, mask: List[str], offset: int) -> bool:
- """Verifica si un patrón coincide en una posición específica"""
- pattern_len = len(pattern)
- if offset + pattern_len > len(data):
- return False
-
- data_slice = data[offset:offset + pattern_len]
- for i, (p_byte, m_char) in enumerate(zip(pattern, mask)):
- if m_char != '?' and data_slice[i] != p_byte:
- return False
- return True
- class StaminaPatternSearcher(PatternSearcher):
- """Buscador específico para patrones de stamina"""
-
- def get_patterns(self) -> Dict[str, Tuple[bytes, List[str]]]:
- """Define los patrones específicos para stamina"""
- return {
- "stamina_pattern_1": (
- bytes([0x75, 0x00, 0xF3, 0x0F, 0x10, 0x44, 0x24, 0x08,
- 0xF3, 0x0F, 0x5A, 0xC0, 0xF2, 0x0F, 0x5A, 0xE8,
- 0xF3, 0x0F, 0x11, 0xAE, 0x8C, 0x01, 0x00, 0x00]),
- ['x', '?', 'x', 'x', 'x', 'x', 'x', 'x',
- 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
- 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x']
- )
- }
-
- def search(self, memory_manager: MemoryManager) -> List[Tuple[str, int]]:
- """Busca patrones de stamina en memoria"""
- patterns = self.get_patterns()
- regions = memory_manager.get_memory_regions()
- found_addresses = []
-
- print(UI_MESSAGES['info']['searching_patterns'].format(region_count=len(regions)))
-
- # Pre-calcular longitudes de patrones
- pattern_info = {name: (pattern, mask, len(pattern))
- for name, (pattern, mask) in patterns.items()}
-
- for region_idx, region in enumerate(regions):
- print(f" Región {region_idx + 1}/{len(regions)}: 0x{region['base']:X} - 0x{region['base'] + region['size']:X}")
-
- # Configuración optimizada de chunks desde config
- chunk_size = MEMORY_SEARCH_CONFIG['chunk_size']
- overlap = MEMORY_SEARCH_CONFIG['overlap']
-
- for offset in range(0, region['size'], chunk_size):
- current_address = region['base'] + offset
- read_size = min(chunk_size + overlap, region['size'] - offset)
-
- data = memory_manager.read_memory(current_address, read_size)
- if not data:
- continue
-
- # Buscar cada patrón
- data_len = len(data)
- for pattern_name, (pattern, mask, pattern_len) in pattern_info.items():
- search_limit = data_len - pattern_len + 1
- for i in range(search_limit):
- if self.pattern_matches(data, pattern, mask, i):
- found_address = current_address + i
- found_addresses.append((pattern_name, found_address))
- print(UI_MESSAGES['info']['pattern_found'].format(pattern_name=pattern_name, address=found_address))
- print(" 🛑 Deteniendo búsqueda - primer patrón encontrado")
- return found_addresses
-
- return found_addresses
|