#!/usr/bin/env python3 import ctypes import sys import struct import platform class MultiArchSupport: def __init__(self): try: self.kernel32 = ctypes.windll.kernel32 self.ntdll = ctypes.windll.ntdll except AttributeError: self.kernel32 = None self.ntdll = None def detect_architecture(self): try: system_info = ctypes.wintypes.SYSTEM_INFO() self.kernel32.GetSystemInfo(ctypes.byref(system_info)) arch_map = { 0: "x86", 6: "x64", 9: "x64", 12: "arm64" } return arch_map.get(system_info.wProcessorArchitecture, "unknown") except: if sys.maxsize > 2**32: return "x64" else: return "x86" def detect_process_arch(self, pid): try: process_handle = self.kernel32.OpenProcess( 0x1000, False, pid ) if process_handle: is_wow64 = ctypes.c_bool() success = self.kernel32.IsWow64Process( process_handle, ctypes.byref(is_wow64) ) self.kernel32.CloseHandle(process_handle) if success: if is_wow64.value: return "x86" else: system_arch = self.detect_architecture() return system_arch if system_arch != "unknown" else "x64" except: pass return self.detect_architecture() def get_pointer_size(self, architecture): arch_sizes = { "x86": 4, "x64": 8, "arm64": 8 } return arch_sizes.get(architecture, 8) def get_register_context(self, architecture): if architecture == "x86": return { "instruction_pointer": "Eip", "stack_pointer": "Esp", "base_pointer": "Ebp", "accumulator": "Eax", "counter": "Ecx", "data": "Edx", "base": "Ebx", "source": "Esi", "destination": "Edi" } elif architecture == "x64": return { "instruction_pointer": "Rip", "stack_pointer": "Rsp", "base_pointer": "Rbp", "accumulator": "Rax", "counter": "Rcx", "data": "Rdx", "base": "Rbx", "source": "Rsi", "destination": "Rdi", "r8": "R8", "r9": "R9", "r10": "R10", "r11": "R11", "r12": "R12", "r13": "R13", "r14": "R14", "r15": "R15" } elif architecture == "arm64": return { "instruction_pointer": "Pc", "stack_pointer": "Sp", "frame_pointer": "Fp", "link_register": "Lr", "x0": "X0", "x1": "X1", "x2": "X2", "x3": "X3", "x4": "X4", "x5": "X5", "x6": "X6", "x7": "X7", "x8": "X8", "x9": "X9", "x10": "X10", "x11": "X11", "x12": "X12", "x13": "X13", "x14": "X14", "x15": "X15", "x16": "X16", "x17": "X17", "x18": "X18", "x19": "X19", "x20": "X20", "x21": "X21", "x22": "X22", "x23": "X23", "x24": "X24", "x25": "X25", "x26": "X26", "x27": "X27", "x28": "X28", "x29": "X29", "x30": "X30" } else: return {} def get_calling_convention(self, architecture): if architecture == "x86": return { "name": "stdcall", "parameter_registers": [], "return_register": "Eax", "stack_cleanup": "callee", "parameter_order": "right_to_left" } elif architecture == "x64": return { "name": "microsoft_x64", "parameter_registers": ["Rcx", "Rdx", "R8", "R9"], "return_register": "Rax", "stack_cleanup": "caller", "parameter_order": "left_to_right", "shadow_space": 32 } elif architecture == "arm64": return { "name": "aapcs64", "parameter_registers": ["X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7"], "return_register": "X0", "stack_cleanup": "caller", "parameter_order": "left_to_right" } else: return {} def get_syscall_convention(self, architecture): if architecture == "x86": return { "syscall_instruction": "int 0x2e", "syscall_number_register": "Eax", "parameter_registers": ["Edx", "Ecx", "Ebx", "Esi", "Edi", "Ebp"], "return_register": "Eax" } elif architecture == "x64": return { "syscall_instruction": "syscall", "syscall_number_register": "Rax", "parameter_registers": ["Rcx", "Rdx", "R8", "R9"], "return_register": "Rax" } elif architecture == "arm64": return { "syscall_instruction": "svc #0", "syscall_number_register": "X8", "parameter_registers": ["X0", "X1", "X2", "X3", "X4", "X5"], "return_register": "X0" } else: return {} def get_nop_instruction(self, architecture): nops = { "x86": b"\x90", "x64": b"\x90", "arm64": b"\x1F\x20\x03\xD5" } return nops.get(architecture, b"\x90") def get_ret_instruction(self, architecture): rets = { "x86": b"\xC3", "x64": b"\xC3", "arm64": b"\xC0\x03\x5F\xD6" } return rets.get(architecture, b"\xC3") def pack_pointer(self, value, architecture): pointer_size = self.get_pointer_size(architecture) if pointer_size == 4: return struct.pack("