Make special regs definitions generic
This commit is contained in:
@@ -9,13 +9,12 @@ import ctypes
|
|||||||
from .. import Uc
|
from .. import Uc
|
||||||
from .. import arm_const as const
|
from .. import arm_const as const
|
||||||
|
|
||||||
from .types import UcReg128
|
from .types import UcTupledReg, UcReg128
|
||||||
|
|
||||||
ARMCPReg = Tuple[int, int, int, int, int, int, int]
|
ARMCPReg = Tuple[int, int, int, int, int, int, int, int]
|
||||||
ARMCPRegValue = 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
|
"""ARM coprocessors registers for instructions MRC, MCR, MRRC, MCRR
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -34,12 +33,6 @@ class UcRegCP(ctypes.Structure):
|
|||||||
def value(self) -> int:
|
def value(self) -> int:
|
||||||
return self.val
|
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):
|
class UcAArch32(Uc):
|
||||||
"""Unicorn subclass for ARM architecture.
|
"""Unicorn subclass for ARM architecture.
|
||||||
|
|||||||
@@ -11,15 +11,14 @@ from .. import arm64_const as const
|
|||||||
|
|
||||||
from ..unicorn import uccallback
|
from ..unicorn import uccallback
|
||||||
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
|
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]
|
ARM64CPReg = Tuple[int, int, int, int, int, int]
|
||||||
ARM64CPRegValue = 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)
|
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
|
"""ARM64 coprocessors registers for instructions MRS, MSR
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -36,12 +35,6 @@ class UcRegCP(ctypes.Structure):
|
|||||||
def value(self) -> int:
|
def value(self) -> int:
|
||||||
return self.val
|
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):
|
class UcAArch64(Uc):
|
||||||
"""Unicorn subclass for ARM64 architecture.
|
"""Unicorn subclass for ARM64 architecture.
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ from .. import x86_const as const
|
|||||||
|
|
||||||
from ..unicorn import uccallback
|
from ..unicorn import uccallback
|
||||||
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
|
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]
|
X86MMRReg = Tuple[int, int, int, int]
|
||||||
|
X86MSRReg = Tuple[int, int]
|
||||||
X86FPReg = 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)
|
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)
|
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.
|
"""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
|
('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
|
class UcRegMSR(UcTupledReg[X86MSRReg]):
|
||||||
def from_param(cls, param: X86MMRReg):
|
|
||||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
|
||||||
|
|
||||||
return cls(*param)
|
|
||||||
|
|
||||||
|
|
||||||
class UcRegMSR(ctypes.Structure):
|
|
||||||
_fields_ = (
|
_fields_ = (
|
||||||
('rid', ctypes.c_uint32),
|
('rid', ctypes.c_uint32),
|
||||||
('val', ctypes.c_uint64)
|
('val', ctypes.c_uint64)
|
||||||
@@ -54,29 +45,13 @@ class UcRegMSR(ctypes.Structure):
|
|||||||
def value(self) -> int:
|
def value(self) -> int:
|
||||||
return self.val
|
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(UcTupledReg[X86FPReg]):
|
||||||
|
|
||||||
|
|
||||||
class UcRegFPR(ctypes.Structure):
|
|
||||||
_fields_ = (
|
_fields_ = (
|
||||||
('mantissa', ctypes.c_uint64),
|
('mantissa', ctypes.c_uint64),
|
||||||
('exponent', ctypes.c_uint16)
|
('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):
|
class UcIntel(Uc):
|
||||||
"""Unicorn subclass for Intel architecture.
|
"""Unicorn subclass for Intel architecture.
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
#
|
#
|
||||||
# @author elicn
|
# @author elicn
|
||||||
|
|
||||||
|
from abc import abstractmethod
|
||||||
|
from typing import Generic, Tuple, TypeVar
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
||||||
uc_err = ctypes.c_int
|
uc_err = ctypes.c_int
|
||||||
@@ -12,7 +15,51 @@ uc_context = ctypes.c_void_p
|
|||||||
uc_hook_h = ctypes.c_size_t
|
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
|
"""A base class for large registers that are internally represented as
|
||||||
an array of multiple qwords.
|
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))
|
return sum(qword << (64 * i) for i, qword in enumerate(self.qwords))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_param(cls, param: int):
|
def from_value(cls, value: int):
|
||||||
assert type(param) is int
|
assert type(value) is int
|
||||||
|
|
||||||
mask = (1 << 64) - 1
|
mask = (1 << 64) - 1
|
||||||
size = cls._fields_[0][1]._length_
|
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):
|
class UcReg128(UcLargeReg):
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ class RegStateManager:
|
|||||||
"""Register write helper method.
|
"""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))
|
status = self._do_reg_write(reg_id, ctypes.byref(reg))
|
||||||
|
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
|
|||||||
Reference in New Issue
Block a user