| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- import sys
- import os
- # Agregar el directorio padre al path para importar config
- sys.path.append(os.path.dirname(os.path.abspath(__file__)))
- from config import TARGET_PROCESS, UI_MESSAGES
- from core.memory_manager import MemoryManager
- from patterns.pattern_searcher import StaminaPatternSearcher, SpeedPatternSearcher
- from patches.patch_factory import PatchFactory
- from utils.helpers import HexDumper, BackupManager, UserInterface
- class AdvancedPatcher:
- """Clase principal del patcher que coordina todos los módulos (Facade Pattern)"""
-
- def __init__(self):
- self.memory_manager = MemoryManager()
- self.patch_factory = PatchFactory()
- self.hex_dumper = HexDumper()
- self.backup_manager = BackupManager(self.memory_manager)
- self.ui = UserInterface()
- self.target_process = TARGET_PROCESS['name']
-
- def show_patch_menu(self) -> tuple:
- """Muestra el menú de selección de parches"""
- print("\n🎯 Selecciona el tipo de parche a aplicar:")
- print("1. Stamina infinita")
- print("2. Velocidad de movimiento")
- print("3. Salir")
-
- while True:
- try:
- choice = input("\n➤ Ingresa tu opción (1-3): ").strip()
- if choice == '1':
- return ('stamina', None)
- elif choice == '2':
- return self.show_speed_menu()
- elif choice == '3':
- return (None, None)
- else:
- print("❌ Opción inválida. Por favor ingresa 1, 2 o 3.")
- except KeyboardInterrupt:
- return (None, None)
-
- def show_speed_menu(self) -> tuple:
- """Muestra el menú de selección de velocidad"""
- multipliers = self.patch_factory.get_speed_multipliers()
- print("\n🏃 Selecciona el multiplicador de velocidad:")
- for i, mult in enumerate(multipliers, 1):
- print(f"{i}. {mult}")
-
- while True:
- try:
- choice = input(f"\n➤ Ingresa tu opción (1-{len(multipliers)}): ").strip()
- try:
- index = int(choice) - 1
- if 0 <= index < len(multipliers):
- return ('speed', multipliers[index])
- else:
- print(f"❌ Opción inválida. Por favor ingresa un número entre 1 y {len(multipliers)}.")
- except ValueError:
- print("❌ Por favor ingresa un número válido.")
- except KeyboardInterrupt:
- return (None, None)
-
- def apply_patch(self, patch_type: str, speed_multiplier: str = None) -> bool:
- """Aplica el parche especificado usando todos los módulos"""
- # Buscar y abrir el proceso
- if not self.memory_manager.open_process(self.target_process):
- print(UI_MESSAGES['error']['process_not_found'].format(process_name=self.target_process))
- return False
-
- # Seleccionar el buscador de patrones apropiado
- if patch_type == 'stamina':
- pattern_searcher = StaminaPatternSearcher()
- print(UI_MESSAGES['info']['searching_stamina'])
- elif patch_type == 'speed':
- pattern_searcher = SpeedPatternSearcher()
- print(UI_MESSAGES['info']['searching_speed'])
- else:
- print(f"❌ Tipo de parche no soportado: {patch_type}")
- return False
-
- # Buscar patrones
- found_addresses = pattern_searcher.search(self.memory_manager)
-
- if not found_addresses:
- print(UI_MESSAGES['error']['no_patterns_found'])
- return False
-
- # Mostrar direcciones encontradas
- self.ui.print_found_addresses(found_addresses)
-
- # Seleccionar dirección objetivo
- target_address = self.ui.select_target_address(found_addresses)
-
- # Crear el parche
- if patch_type == 'speed' and speed_multiplier:
- patch = self.patch_factory.create_patch(patch_type, speed_multiplier=speed_multiplier)
- else:
- patch = self.patch_factory.create_patch(patch_type)
-
- if not patch:
- print(f"❌ No se pudo crear el parche de {patch_type}")
- return False
-
- print(f"\n📋 {patch.get_description()}")
-
- # Leer código original
- original_size = patch.get_patch_size()
- original_code = self.memory_manager.read_memory(target_address, original_size)
- if not original_code:
- print("❌ No se pudo leer el código original")
- return False
-
- # Crear backup
- self.backup_manager.backup_original_code(target_address, len(original_code))
-
- # Mostrar código original
- print(UI_MESSAGES['info']['original_code'])
- self.hex_dumper.print_hex_dump(original_code, target_address)
-
- # Generar datos del parche
- patch_data = patch.create_patch(original_code)
-
- # Mostrar código del parche
- print(UI_MESSAGES['info']['patch_to_apply'])
- self.hex_dumper.print_hex_dump(patch_data)
-
- # Confirmar aplicación
- if not self.ui.confirm_patch():
- print(UI_MESSAGES['error']['operation_cancelled'])
- return False
-
- # Aplicar el parche
- print(UI_MESSAGES['info']['applying_patch'])
- if self.memory_manager.write_memory(target_address, patch_data):
- print(UI_MESSAGES['success']['patch_applied'])
-
- # Verificar que el patch se escribió correctamente
- verification_data = self.memory_manager.read_memory(target_address, len(patch_data))
- if verification_data == patch_data:
- print(UI_MESSAGES['success']['verification_successful'])
- return True
- else:
- print(UI_MESSAGES['error']['verification_failed'])
- return False
- else:
- print(UI_MESSAGES['error']['patch_failed'])
- return False
-
- def cleanup(self):
- """Limpia los recursos utilizados"""
- self.memory_manager.close_process()
-
- def run(self) -> bool:
- """Ejecuta el proceso completo de patcheo"""
- print(UI_MESSAGES['info']['starting_patch_process'])
-
- success = False
- try:
- # Mostrar menú de selección
- patch_type, speed_multiplier = self.show_patch_menu()
-
- if patch_type is None:
- print(UI_MESSAGES['info']['goodbye'])
- return False
-
- success = self.apply_patch(patch_type, speed_multiplier)
- if success:
- print(UI_MESSAGES['success']['patching_completed'])
- if patch_type == 'stamina':
- print(UI_MESSAGES['success']['stamina_maintained'])
- elif patch_type == 'speed':
- print(UI_MESSAGES['success']['speed_modified'])
- else:
- print(UI_MESSAGES['error']['patching_failed'])
- except Exception as e:
- print(UI_MESSAGES['error']['patching_error'].format(error=e))
- finally:
- self.cleanup()
-
- return success
|