Final touches
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Unicorn Python bindings by elicn
|
# New and improved Unicorn Python bindings by elicn
|
||||||
# based on Nguyen Anh Quynnh's work
|
# based on Nguyen Anh Quynnh's work
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -6,11 +6,13 @@ from typing import Any, Callable, Iterator, Mapping, MutableMapping, Optional, S
|
|||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import weakref
|
import weakref
|
||||||
# import functools
|
|
||||||
|
|
||||||
from . import unicorn_const as uc
|
from . import unicorn_const as uc
|
||||||
from .arch.types import *
|
from .arch.types import *
|
||||||
|
|
||||||
|
__version__ = f'{uc.UC_VERSION_MAJOR}.{uc.UC_VERSION_MINOR}.{uc.UC_VERSION_PATCH}'
|
||||||
|
|
||||||
|
|
||||||
class _uc_mem_region(ctypes.Structure):
|
class _uc_mem_region(ctypes.Structure):
|
||||||
_fields_ = (
|
_fields_ = (
|
||||||
('begin', ctypes.c_uint64),
|
('begin', ctypes.c_uint64),
|
||||||
@@ -177,8 +179,6 @@ def __set_lib_prototypes(lib: ctypes.CDLL) -> None:
|
|||||||
uclib = __load_uc_lib()
|
uclib = __load_uc_lib()
|
||||||
__set_lib_prototypes(uclib)
|
__set_lib_prototypes(uclib)
|
||||||
|
|
||||||
__version__ = f'{uc.UC_VERSION_MAJOR}.{uc.UC_VERSION_MINOR}.{uc.UC_VERSION_PATCH}'
|
|
||||||
|
|
||||||
|
|
||||||
# native hook callback signatures
|
# native hook callback signatures
|
||||||
HOOK_INTR_CFUNC = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint32, ctypes.c_void_p)
|
HOOK_INTR_CFUNC = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint32, ctypes.c_void_p)
|
||||||
@@ -289,6 +289,7 @@ class UcCleanupManager:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._refs = {}
|
self._refs = {}
|
||||||
|
|
||||||
|
|
||||||
def register(self, obj: Uc):
|
def register(self, obj: Uc):
|
||||||
ref = UcRef(obj, self._finalizer)
|
ref = UcRef(obj, self._finalizer)
|
||||||
ref._uch = obj._uch
|
ref._uch = obj._uch
|
||||||
@@ -296,6 +297,7 @@ class UcCleanupManager:
|
|||||||
|
|
||||||
self._refs[id(ref)] = ref
|
self._refs[id(ref)] = ref
|
||||||
|
|
||||||
|
|
||||||
def _finalizer(self, ref: UcRef) -> None:
|
def _finalizer(self, ref: UcRef) -> None:
|
||||||
# note: this method must be completely self-contained and cannot have any references
|
# note: this method must be completely self-contained and cannot have any references
|
||||||
# to anything else in this module.
|
# to anything else in this module.
|
||||||
@@ -482,6 +484,13 @@ class Uc(RegStateManager):
|
|||||||
|
|
||||||
|
|
||||||
def __init__(self, arch: int, mode: int) -> None:
|
def __init__(self, arch: int, mode: int) -> None:
|
||||||
|
"""Initialize a Unicorn engine instance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arch: emulated architecture identifier (see UC_ARCH_* constants)
|
||||||
|
mode: emulated processor mode (see UC_MODE_* constants)
|
||||||
|
"""
|
||||||
|
|
||||||
self._arch = arch
|
self._arch = arch
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
|
|
||||||
@@ -493,7 +502,7 @@ class Uc(RegStateManager):
|
|||||||
self._uch = None
|
self._uch = None
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
|
||||||
# we have to keep a reference to the callbacks so they do not het gc-ed
|
# we have to keep a reference to the callbacks so they do not get gc-ed
|
||||||
# see: https://docs.python.org/3/library/ctypes.html#callback-functions
|
# see: https://docs.python.org/3/library/ctypes.html#callback-functions
|
||||||
self._callbacks: MutableMapping[int, ctypes._FuncPointer] = {}
|
self._callbacks: MutableMapping[int, ctypes._FuncPointer] = {}
|
||||||
self._mmio_callbacks: MutableMapping[Tuple[int, int], Tuple[Optional[ctypes._FuncPointer], Optional[ctypes._FuncPointer]]] = {}
|
self._mmio_callbacks: MutableMapping[Tuple[int, int], Tuple[Optional[ctypes._FuncPointer], Optional[ctypes._FuncPointer]]] = {}
|
||||||
@@ -527,7 +536,7 @@ class Uc(RegStateManager):
|
|||||||
begin : emulation starting address
|
begin : emulation starting address
|
||||||
until : emulation ending address
|
until : emulation ending address
|
||||||
timeout : limit emulation to a certain amount of time (milliseconds)
|
timeout : limit emulation to a certain amount of time (milliseconds)
|
||||||
count : limit emulation to a certain amount of intstructions
|
count : limit emulation to a certain amount of instructions
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
`UcError` : in case emulation could not be started properly
|
`UcError` : in case emulation could not be started properly
|
||||||
@@ -562,6 +571,7 @@ class Uc(RegStateManager):
|
|||||||
|
|
||||||
def _do_reg_read(self, reg_id: int, reg_obj) -> int:
|
def _do_reg_read(self, reg_id: int, reg_obj) -> int:
|
||||||
"""Private register read implementation.
|
"""Private register read implementation.
|
||||||
|
Do not call directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return uclib.uc_reg_read(self._uch, reg_id, reg_obj)
|
return uclib.uc_reg_read(self._uch, reg_id, reg_obj)
|
||||||
@@ -569,6 +579,7 @@ class Uc(RegStateManager):
|
|||||||
|
|
||||||
def _do_reg_write(self, reg_id: int, reg_obj) -> int:
|
def _do_reg_write(self, reg_id: int, reg_obj) -> int:
|
||||||
"""Private register write implementation.
|
"""Private register write implementation.
|
||||||
|
Do not call directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return uclib.uc_reg_write(self._uch, reg_id, reg_obj)
|
return uclib.uc_reg_write(self._uch, reg_id, reg_obj)
|
||||||
@@ -782,7 +793,7 @@ class Uc(RegStateManager):
|
|||||||
"""Hook emulated events of a certain type.
|
"""Hook emulated events of a certain type.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
htype : event type(s) to hook
|
htype : event type(s) to hook (see UC_HOOK_* constants)
|
||||||
callback : a method to call each time the hooked event occurs
|
callback : a method to call each time the hooked event occurs
|
||||||
user_data : an additional context to pass to the callback when it is called
|
user_data : an additional context to pass to the callback when it is called
|
||||||
begin : address where hook scope starts
|
begin : address where hook scope starts
|
||||||
@@ -1057,7 +1068,7 @@ class Uc(RegStateManager):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def ctl_get_exits(self):
|
def ctl_get_exits(self) -> Sequence[int]:
|
||||||
l = self.ctl_get_exits_cnt()
|
l = self.ctl_get_exits_cnt()
|
||||||
arr = (ctypes.c_uint64 * l)()
|
arr = (ctypes.c_uint64 * l)()
|
||||||
|
|
||||||
@@ -1156,6 +1167,7 @@ class UcContext(RegStateManager):
|
|||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return bytes(self), self.size, self.arch, self.mode
|
return bytes(self), self.size, self.arch, self.mode
|
||||||
|
|
||||||
|
|
||||||
def __setstate__(self, state) -> None:
|
def __setstate__(self, state) -> None:
|
||||||
context, size, arch, mode = state
|
context, size, arch, mode = state
|
||||||
|
|
||||||
@@ -1171,6 +1183,7 @@ class UcContext(RegStateManager):
|
|||||||
def __bytes__(self) -> bytes:
|
def __bytes__(self) -> bytes:
|
||||||
return ctypes.string_at(self.context, self.size)
|
return ctypes.string_at(self.context, self.size)
|
||||||
|
|
||||||
|
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
# We need this property since we shouldn't free it if the object is constructed from pickled bytes.
|
# We need this property since we shouldn't free it if the object is constructed from pickled bytes.
|
||||||
if self._to_free:
|
if self._to_free:
|
||||||
|
|||||||
Reference in New Issue
Block a user