import time from typing import 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 HEX_DUMP_CONFIG, BACKUP_CONFIG, UI_MESSAGES from core.memory_manager import MemoryManager class HexDumper: """Utilidad para volcados hexadecimales""" @staticmethod def print_hex_dump(data: bytes, base_address: int = 0): """Imprime un volcado hexadecimal de los datos""" bytes_per_line = HEX_DUMP_CONFIG['bytes_per_line'] address_width = HEX_DUMP_CONFIG['address_width'] for i in range(0, len(data), bytes_per_line): line_data = data[i:i+bytes_per_line] hex_part = ' '.join(f'{b:02X}' for b in line_data) ascii_part = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in line_data) print(f" 0x{base_address + i:0{address_width}X}: {hex_part:<48} {ascii_part}") class BackupManager: """Gestor de copias de seguridad""" def __init__(self, memory_manager: MemoryManager): self.memory_manager = memory_manager def backup_original_code(self, address: int, size: int) -> Optional[str]: """Crea una copia de seguridad del código original""" data = self.memory_manager.read_memory(address, size) if data and BACKUP_CONFIG['enabled']: timestamp = int(time.time()) filename = BACKUP_CONFIG['filename_format'].format(address=address, timestamp=timestamp) try: with open(filename, 'wb') as f: f.write(data) print(UI_MESSAGES['success']['backup_saved'].format(filename=filename)) return filename except IOError as e: print(f"❌ Error al guardar backup: {e}") return None class UserInterface: """Utilidades para interacción con el usuario""" @staticmethod def confirm_action(message: str) -> bool: """Solicita confirmación del usuario""" response = input(f"\n❓ {message} (s/N): ").strip().lower() return response in ['s', 'si', 'sí', 'y', 'yes'] @staticmethod def confirm_patch() -> bool: """Solicita confirmación para aplicar el patch""" response = input("\n❓ ¿Aplicar el parche? (s/N): ").strip().lower() return response in ['s', 'si', 'sí', 'y', 'yes'] @staticmethod def print_banner(): """Imprime el banner de la aplicación""" banner = UI_MESSAGES['banner'] print(banner['title']) print(banner['description']) print(banner['warning']) print(banner['admin_note'] + "\n") @staticmethod def print_found_addresses(found_addresses: list): """Imprime las direcciones encontradas""" print(f"\n📍 Se encontraron {len(found_addresses)} coincidencias:") for i, (pattern_name, address) in enumerate(found_addresses): print(f" {i + 1}. {pattern_name}: 0x{address:X}") @staticmethod def select_target_address(found_addresses: list) -> int: """Selecciona la dirección objetivo de la lista""" target_address = next( (address for pattern_name, address in found_addresses if "pattern_1" in pattern_name), found_addresses[0][1] # Fallback a la primera coincidencia ) print(UI_MESSAGES['info']['using_address'].format(address=target_address)) return target_address