Make special regs definitions generic

This commit is contained in:
elicn 2022-10-20 14:16:53 +03:00
parent 0e63841628
commit 647832b01b
5 changed files with 63 additions and 55 deletions

View File

@ -9,13 +9,12 @@ import ctypes
from .. import Uc
from .. import arm_const as const
from .types import UcReg128
from .types import UcTupledReg, UcReg128
ARMCPReg = Tuple[int, int, int, int, int, int, int]
ARMCPRegValue = Tuple[int, int, int, int, int, int, int, int]
ARMCPReg = Tuple[int, int, int, int, int, int, int, int]
class UcRegCP(ctypes.Structure):
class UcRegCP(UcTupledReg[ARMCPReg]):
"""ARM coprocessors registers for instructions MRC, MCR, MRRC, MCRR
"""
@ -34,12 +33,6 @@ class UcRegCP(ctypes.Structure):
def value(self) -> int:
return self.val
@classmethod
def from_param(cls, param: ARMCPRegValue):
assert type(param) is tuple and len(param) == len(cls._fields_)
return cls(*param)
class UcAArch32(Uc):
"""Unicorn subclass for ARM architecture.

View File

@ -11,15 +11,14 @@ from .. import arm64_const as const
from ..unicorn import uccallback
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
from .types import uc_engine, UcReg128
from .types import uc_engine, UcTupledReg, UcReg128
ARM64CPReg = Tuple[int, int, int, int, int]
ARM64CPRegValue = Tuple[int, int, int, int, int, int]
ARM64CPReg = Tuple[int, int, int, int, int, int]
HOOK_INSN_SYS_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p)
class UcRegCP(ctypes.Structure):
class UcRegCP(UcTupledReg[ARM64CPReg]):
"""ARM64 coprocessors registers for instructions MRS, MSR
"""
@ -36,12 +35,6 @@ class UcRegCP(ctypes.Structure):
def value(self) -> int:
return self.val
@classmethod
def from_param(cls, param: ARM64CPRegValue):
assert type(param) is tuple and len(param) == len(cls._fields_)
return cls(*param)
class UcAArch64(Uc):
"""Unicorn subclass for ARM64 architecture.

View File

@ -11,9 +11,10 @@ from .. import x86_const as const
from ..unicorn import uccallback
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
from .types import uc_engine, UcReg128, UcReg256, UcReg512
from .types import uc_engine, UcTupledReg, UcReg128, UcReg256, UcReg512
X86MMRReg = Tuple[int, int, int, int]
X86MSRReg = Tuple[int, int]
X86FPReg = Tuple[int, int]
HOOK_INSN_IN_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_int, ctypes.c_void_p)
@ -22,7 +23,7 @@ HOOK_INSN_SYSCALL_CFUNC = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
HOOK_INSN_CPUID_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_void_p)
class UcRegMMR(ctypes.Structure):
class UcRegMMR(UcTupledReg[X86MMRReg]):
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.
"""
@ -33,18 +34,8 @@ class UcRegMMR(ctypes.Structure):
('flags', ctypes.c_uint32) # not used by GDTR and IDTR
)
@property
def value(self) -> X86MMRReg:
return tuple(getattr(self, fname) for fname, _ in self._fields_)
@classmethod
def from_param(cls, param: X86MMRReg):
assert type(param) is tuple and len(param) == len(cls._fields_)
return cls(*param)
class UcRegMSR(ctypes.Structure):
class UcRegMSR(UcTupledReg[X86MSRReg]):
_fields_ = (
('rid', ctypes.c_uint32),
('val', ctypes.c_uint64)
@ -54,29 +45,13 @@ class UcRegMSR(ctypes.Structure):
def value(self) -> int:
return self.val
@classmethod
def from_param(cls, param: Tuple[int, int]):
assert type(param) is tuple and len(param) == len(cls._fields_)
return cls(*param)
class UcRegFPR(ctypes.Structure):
class UcRegFPR(UcTupledReg[X86FPReg]):
_fields_ = (
('mantissa', ctypes.c_uint64),
('exponent', ctypes.c_uint16)
)
@property
def value(self) -> X86FPReg:
return tuple(getattr(self, fname) for fname, _ in self._fields_)
@classmethod
def from_param(cls, param: X86FPReg):
assert type(param) is tuple and len(param) == len(cls._fields_)
return cls(*param)
class UcIntel(Uc):
"""Unicorn subclass for Intel architecture.

View File

@ -2,6 +2,9 @@
#
# @author elicn
from abc import abstractmethod
from typing import Generic, Tuple, TypeVar
import ctypes
uc_err = ctypes.c_int
@ -12,7 +15,51 @@ uc_context = ctypes.c_void_p
uc_hook_h = ctypes.c_size_t
class UcLargeReg(ctypes.Structure):
VT = TypeVar('VT', bound=Tuple[int, ...])
class UcReg(ctypes.Structure):
"""A base class for composite registers.
This class is meant to be inherited, not instantiated directly.
"""
@property
@abstractmethod
def value(self):
"""Get register value.
"""
pass
@classmethod
@abstractmethod
def from_value(cls, value):
"""Create a register instance from a given value.
"""
pass
class UcTupledReg(UcReg, Generic[VT]):
"""A base class for registers whose values are represented as a set
of fields.
This class is meant to be inherited, not instantiated directly.
"""
@property
def value(self) -> VT:
return tuple(getattr(self, fname) for fname, *_ in self.__class__._fields_) # type: ignore
@classmethod
def from_value(cls, value: VT):
assert type(value) is tuple and len(value) == len(cls._fields_)
return cls(*value)
class UcLargeReg(UcReg):
"""A base class for large registers that are internally represented as
an array of multiple qwords.
@ -26,13 +73,13 @@ class UcLargeReg(ctypes.Structure):
return sum(qword << (64 * i) for i, qword in enumerate(self.qwords))
@classmethod
def from_param(cls, param: int):
assert type(param) is int
def from_value(cls, value: int):
assert type(value) is int
mask = (1 << 64) - 1
size = cls._fields_[0][1]._length_
return cls(tuple((param >> (64 * i)) & mask for i in range(size)))
return cls(tuple((value >> (64 * i)) & mask for i in range(size)))
class UcReg128(UcLargeReg):

View File

@ -338,7 +338,7 @@ class RegStateManager:
"""Register write helper method.
"""
reg = regtype.from_param(value) if issubclass(regtype, ctypes.Structure) else regtype(value)
reg = regtype.from_value(value) if issubclass(regtype, UcReg) else regtype(value)
status = self._do_reg_write(reg_id, ctypes.byref(reg))
if status != uc.UC_ERR_OK: