Merge branch 'python-code-cleanup' of https://github.com/jbremer/unicorn into jbremer-python-code-cleanup

This commit is contained in:
Nguyen Anh Quynh 2016-03-30 09:55:42 +08:00
commit e79345bfb5

View file

@ -1,42 +1,55 @@
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com> # Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
import ctypes
import ctypes.util
import distutils.sysconfig
import inspect
import os.path
import platform
import sys import sys
from . import x86_const, unicorn_const as uc
if not hasattr(sys.modules[__name__], "__file__"):
__file__ = inspect.getfile(inspect.currentframe())
_python2 = sys.version_info[0] < 3 _python2 = sys.version_info[0] < 3
if _python2: if _python2:
range = xrange range = xrange
from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const
from .unicorn_const import *
import ctypes, ctypes.util, sys _lib_path = os.path.split(__file__)[0]
from platform import system _all_libs = (
from os.path import split, join, dirname, exists "unicorn.dll",
import distutils.sysconfig "libunicorn.so",
"libunicorn.dylib",
)
import inspect
if not hasattr(sys.modules[__name__], '__file__'):
__file__ = inspect.getfile(inspect.currentframe())
_lib_path = split(__file__)[0]
_all_libs = ('unicorn.dll', 'libunicorn.so', 'libunicorn.dylib')
# Windows DLL in dependency order # Windows DLL in dependency order
_all_windows_dlls = ("libwinpthread-1.dll", "libgcc_s_seh-1.dll", "libgcc_s_dw2-1.dll", "libiconv-2.dll", "libintl-8.dll", "libglib-2.0-0.dll") _all_windows_dlls = (
"libwinpthread-1.dll",
"libgcc_s_seh-1.dll",
"libgcc_s_dw2-1.dll",
"libiconv-2.dll",
"libintl-8.dll",
"libglib-2.0-0.dll",
)
_found = False _found = False
for _lib in _all_libs: for _lib in _all_libs:
try: try:
if _lib == 'unicorn.dll': if _lib == "unicorn.dll":
for dll in _all_windows_dlls: # load all the rest DLLs first for dll in _all_windows_dlls: # load all the rest DLLs first
_lib_file = join(_lib_path, dll) _lib_file = os.path.join(_lib_path, dll)
if exists(_lib_file): if os.path.exists(_lib_file):
ctypes.cdll.LoadLibrary(_lib_file) ctypes.cdll.LoadLibrary(_lib_file)
_lib_file = join(_lib_path, _lib) _lib_file = os.path.join(_lib_path, _lib)
_uc = ctypes.cdll.LoadLibrary(_lib_file) _uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True _found = True
break break
except OSError: except OSError:
pass pass
if _found == False: if not _found:
# try loading from default paths # try loading from default paths
for _lib in _all_libs: for _lib in _all_libs:
try: try:
@ -46,17 +59,17 @@ if _found == False:
except OSError: except OSError:
pass pass
if _found == False: if not _found:
# last try: loading from python lib directory # last try: loading from python lib directory
_lib_path = distutils.sysconfig.get_python_lib() _lib_path = distutils.sysconfig.get_python_lib()
for _lib in _all_libs: for _lib in _all_libs:
try: try:
if _lib == 'unicorn.dll': if _lib == "unicorn.dll":
for dll in _all_windows_dlls: # load all the rest DLLs first for dll in _all_windows_dlls: # load all the rest DLLs first
_lib_file = join(_lib_path, 'unicorn', dll) _lib_file = os.path.join(_lib_path, "unicorn", dll)
if exists(_lib_file): if os.path.exists(_lib_file):
ctypes.cdll.LoadLibrary(_lib_file) ctypes.cdll.LoadLibrary(_lib_file)
_lib_file = join(_lib_path, 'unicorn', _lib) _lib_file = os.path.join(_lib_path, "unicorn", _lib)
_uc = ctypes.cdll.LoadLibrary(_lib_file) _uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True _found = True
break break
@ -65,11 +78,11 @@ if _found == False:
# Attempt Darwin specific load (10.11 specific), # Attempt Darwin specific load (10.11 specific),
# since LD_LIBRARY_PATH is not guaranteed to exist # since LD_LIBRARY_PATH is not guaranteed to exist
if (_found == False) and (system() == 'Darwin'): if not _found and platform.system() == "Darwin":
_lib_path = '/usr/local/lib/' _lib_path = "/usr/local/lib/"
for _lib in _all_libs: for _lib in _all_libs:
try: try:
_lib_file = join(_lib_path, _lib) _lib_file = os.path.join(_lib_path, _lib)
# print "Trying to load:", _lib_file # print "Trying to load:", _lib_file
_uc = ctypes.cdll.LoadLibrary(_lib_file) _uc = ctypes.cdll.LoadLibrary(_lib_file)
_found = True _found = True
@ -77,11 +90,11 @@ if (_found == False) and (system() == 'Darwin'):
except OSError: except OSError:
pass pass
if _found == False: if not _found:
raise ImportError("ERROR: fail to load the dynamic library.") raise ImportError("ERROR: fail to load the dynamic library.")
__version__ = "%s.%s" %(UC_API_MAJOR, UC_API_MINOR) __version__ = "%s.%s" % (uc.UC_API_MAJOR, uc.UC_API_MINOR)
# setup all the function prototype # setup all the function prototype
def _setup_prototype(lib, fname, restype, *argtypes): def _setup_prototype(lib, fname, restype, *argtypes):
@ -112,20 +125,28 @@ _setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctype
_setup_prototype(_uc, "uc_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t)) _setup_prototype(_uc, "uc_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t))
# uc_hook_add is special due to variable number of arguments # uc_hook_add is special due to variable number of arguments
_uc.uc_hook_add = getattr(_uc, "uc_hook_add") _uc.uc_hook_add = _uc.uc_hook_add
_uc.uc_hook_add.restype = ucerr _uc.uc_hook_add.restype = ucerr
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_int, \ UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) ctypes.c_bool, uc_engine, ctypes.c_int,
UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_int, \ ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) )
UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint32, \ UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(
ctypes.c_void_p) None, uc_engine, ctypes.c_int,
UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, \ ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p
ctypes.c_int, ctypes.c_void_p) )
UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint32, \ UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p) None, uc_engine, ctypes.c_uint32, ctypes.c_void_p
)
UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(
ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_int, ctypes.c_void_p
)
UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
None, uc_engine, ctypes.c_uint32,
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
)
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p) UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
@ -148,7 +169,10 @@ def uc_version():
# return the binding's version # return the binding's version
def version_bind(): def version_bind():
return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR) return (
uc.UC_API_MAJOR, uc.UC_API_MINOR,
(uc.UC_API_MAJOR << 8) + uc.UC_API_MINOR,
)
# check to see if this engine supports a particular arch # check to see if this engine supports a particular arch
@ -157,36 +181,36 @@ def uc_arch_supported(query):
class uc_x86_mmr(ctypes.Structure): class uc_x86_mmr(ctypes.Structure):
'''Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.''' """Memory-Management Register for instructions IDTR, GDTR, LDTR, TR."""
_fields_ = [ _fields_ = [
("selector", ctypes.c_uint16), # not used by GDTR and IDTR ("selector", ctypes.c_uint16), # not used by GDTR and IDTR
("base", ctypes.c_uint64), # handle 32 or 64 bit CPUs ("base", ctypes.c_uint64), # handle 32 or 64 bit CPUs
("limit", ctypes.c_uint32), ("limit", ctypes.c_uint32),
("flags", ctypes.c_uint32), # not used by GDTR and IDTR ("flags", ctypes.c_uint32), # not used by GDTR and IDTR
] ]
class uc_x86_float80(ctypes.Structure): class uc_x86_float80(ctypes.Structure):
'''Float80''' """Float80"""
_fields_ = [ _fields_ = [
("mantissa", ctypes.c_uint64), ("mantissa", ctypes.c_uint64),
("exponent", ctypes.c_uint16), ("exponent", ctypes.c_uint16),
] ]
class Uc(object): class Uc(object):
def __init__(self, arch, mode): def __init__(self, arch, mode):
# verify version compatibility with the core before doing anything # verify version compatibility with the core before doing anything
(major, minor, _combined) = uc_version() (major, minor, _combined) = uc_version()
if major != UC_API_MAJOR or minor != UC_API_MINOR: if major != uc.UC_API_MAJOR or minor != uc.UC_API_MINOR:
self._uch = None self._uch = None
# our binding version is different from the core's API version # our binding version is different from the core's API version
raise UcError(UC_ERR_VERSION) raise UcError(uc.UC_ERR_VERSION)
self._arch, self._mode = arch, mode self._arch, self._mode = arch, mode
self._uch = ctypes.c_void_p() self._uch = ctypes.c_void_p()
status = _uc.uc_open(arch, mode, ctypes.byref(self._uch)) status = _uc.uc_open(arch, mode, ctypes.byref(self._uch))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
self._uch = None self._uch = None
raise UcError(status) raise UcError(status)
# internal mapping table to save callback & userdata # internal mapping table to save callback & userdata
@ -194,177 +218,158 @@ class Uc(object):
self._ctype_cbs = {} self._ctype_cbs = {}
self._callback_count = 0 self._callback_count = 0
# destructor to be called automatically when object is destroyed. # destructor to be called automatically when object is destroyed.
def __del__(self): def __del__(self):
if self._uch: if self._uch:
try: try:
status = _uc.uc_close(self._uch) status = _uc.uc_close(self._uch)
self._uch = None self._uch = None
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
except: # _uc might be pulled from under our feet except: # _uc might be pulled from under our feet
pass pass
# emulate from @begin, and stop when reaching address @until # emulate from @begin, and stop when reaching address @until
def emu_start(self, begin, until, timeout=0, count=0): def emu_start(self, begin, until, timeout=0, count=0):
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count) status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# stop emulation # stop emulation
def emu_stop(self): def emu_stop(self):
status = _uc.uc_emu_stop(self._uch) status = _uc.uc_emu_stop(self._uch)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# return the value of a register # return the value of a register
def reg_read(self, reg_id): def reg_read(self, reg_id):
if self._arch == UC_ARCH_X86: if self._arch == uc.UC_ARCH_X86:
if reg_id in [ x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]: if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
reg = uc_x86_mmr() reg = uc_x86_mmr()
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return (reg.selector,reg.base, reg.limit, reg.flags) return reg.selector, reg.base, reg.limit, reg.flags
if reg_id in range(x86_const.UC_X86_REG_FP0,x86_const.UC_X86_REG_FP0+8): if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
reg = uc_x86_float80() reg = uc_x86_float80()
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return (reg.mantissa, reg.exponent) return reg.mantissa, reg.exponent
# read to 64bit number to be safe # read to 64bit number to be safe
reg = ctypes.c_int64(0) reg = ctypes.c_int64(0)
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return reg.value return reg.value
# write to a register # write to a register
def reg_write(self, reg_id, value): def reg_write(self, reg_id, value):
reg = None reg = None
if self._arch == UC_ARCH_X86: if self._arch == uc.UC_ARCH_X86:
if reg_id in [ x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]: if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
assert isinstance(value, tuple) and len(value)==4 assert isinstance(value, tuple) and len(value) == 4
reg = uc_x86_mmr() reg = uc_x86_mmr()
reg.selector=value[0] reg.selector = value[0]
reg.base=value[1] reg.base = value[1]
reg.limit=value[2] reg.limit = value[2]
reg.flags=value[3] reg.flags = value[3]
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8): if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
reg = uc_x86_float80() reg = uc_x86_float80()
reg.mantissa = value[0] reg.mantissa = value[0]
reg.exponent = value[1] reg.exponent = value[1]
if reg is None: if reg is None:
# convert to 64bit number to be safe # convert to 64bit number to be safe
reg = ctypes.c_int64(value) reg = ctypes.c_int64(value)
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg)) status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# read data from memory # read data from memory
def mem_read(self, address, size): def mem_read(self, address, size):
data = ctypes.create_string_buffer(size) data = ctypes.create_string_buffer(size)
status = _uc.uc_mem_read(self._uch, address, data, size) status = _uc.uc_mem_read(self._uch, address, data, size)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return bytearray(data) return bytearray(data)
# write to memory # write to memory
def mem_write(self, address, data): def mem_write(self, address, data):
status = _uc.uc_mem_write(self._uch, address, data, len(data)) status = _uc.uc_mem_write(self._uch, address, data, len(data))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# map a range of memory # map a range of memory
def mem_map(self, address, size, perms=UC_PROT_ALL): def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
status = _uc.uc_mem_map(self._uch, address, size, perms) status = _uc.uc_mem_map(self._uch, address, size, perms)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# map a range of memory from a raw host memory address # map a range of memory from a raw host memory address
def mem_map_ptr(self, address, size, perms, ptr): def mem_map_ptr(self, address, size, perms, ptr):
status = _uc.uc_mem_map_ptr(self._uch, address, size, perms, ptr) status = _uc.uc_mem_map_ptr(self._uch, address, size, perms, ptr)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# unmap a range of memory # unmap a range of memory
def mem_unmap(self, address, size): def mem_unmap(self, address, size):
status = _uc.uc_mem_unmap(self._uch, address, size) status = _uc.uc_mem_unmap(self._uch, address, size)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# protect a range of memory # protect a range of memory
def mem_protect(self, address, size, perms=UC_PROT_ALL): def mem_protect(self, address, size, perms=uc.UC_PROT_ALL):
status = _uc.uc_mem_protect(self._uch, address, size, perms) status = _uc.uc_mem_protect(self._uch, address, size, perms)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
# return CPU mode at runtime # return CPU mode at runtime
def query(self, query_mode): def query(self, query_mode):
result = ctypes.c_size_t(0) result = ctypes.c_size_t(0)
status = _uc.uc_query(self._uch, query_mode, ctypes.byref(result)) status = _uc.uc_query(self._uch, query_mode, ctypes.byref(result))
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return result.value return result.value
def _hookcode_cb(self, handle, address, size, user_data): def _hookcode_cb(self, handle, address, size, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
cb(self, address, size, data) cb(self, address, size, data)
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data): def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
return cb(self, access, address, size, value, data) return cb(self, access, address, size, value, data)
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data): def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
cb(self, access, address, size, value, data) cb(self, access, address, size, value, data)
def _hook_intr_cb(self, handle, intno, user_data): def _hook_intr_cb(self, handle, intno, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
cb(self, intno, data) cb(self, intno, data)
def _hook_insn_in_cb(self, handle, port, size, user_data): def _hook_insn_in_cb(self, handle, port, size, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
return cb(self, port, size, data) return cb(self, port, size, data)
def _hook_insn_out_cb(self, handle, port, size, value, user_data): def _hook_insn_out_cb(self, handle, port, size, value, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
cb(self, port, size, value, data) cb(self, port, size, value, data)
def _hook_insn_syscall_cb(self, handle, user_data): def _hook_insn_syscall_cb(self, handle, user_data):
# call user's callback with self object # call user's callback with self object
(cb, data) = self._callbacks[user_data] (cb, data) = self._callbacks[user_data]
cb(self, data) cb(self, data)
# add a hook # add a hook
def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0): def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0):
_h2 = uc_hook_h() _h2 = uc_hook_h()
@ -374,61 +379,83 @@ class Uc(object):
self._callbacks[self._callback_count] = (callback, user_data) self._callbacks[self._callback_count] = (callback, user_data)
cb = None cb = None
if htype == UC_HOOK_INSN: if htype == uc.UC_HOOK_INSN:
insn = ctypes.c_int(arg1) insn = ctypes.c_int(arg1)
if arg1 == x86_const.UC_X86_INS_IN: # IN instruction if arg1 == x86_const.UC_X86_INS_IN: # IN instruction
cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB) cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB)
if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB) cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB) cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ status = _uc.uc_hook_add(
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end), insn) self._uch, ctypes.byref(_h2), htype, cb,
elif htype == UC_HOOK_INTR: ctypes.cast(self._callback_count, ctypes.c_void_p),
ctypes.c_uint64(begin), ctypes.c_uint64(end), insn
)
elif htype == uc.UC_HOOK_INTR:
cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB) cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ status = _uc.uc_hook_add(
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) self._uch, ctypes.byref(_h2), htype, cb,
ctypes.cast(self._callback_count, ctypes.c_void_p),
ctypes.c_uint64(begin), ctypes.c_uint64(end)
)
else: else:
if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): if htype in (uc.UC_HOOK_BLOCK, uc.UC_HOOK_CODE):
# set callback with wrapper, so it can be called # set callback with wrapper, so it can be called
# with this object as param # with this object as param
cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ status = _uc.uc_hook_add(
ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) self._uch, ctypes.byref(_h2), htype, cb,
elif htype & UC_HOOK_MEM_READ_UNMAPPED or htype & UC_HOOK_MEM_WRITE_UNMAPPED or \ ctypes.cast(self._callback_count, ctypes.c_void_p),
htype & UC_HOOK_MEM_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \ ctypes.c_uint64(begin), ctypes.c_uint64(end)
htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: )
elif htype & (uc.UC_HOOK_MEM_READ_UNMAPPED |
uc.UC_HOOK_MEM_WRITE_UNMAPPED |
uc.UC_HOOK_MEM_FETCH_UNMAPPED |
uc.UC_HOOK_MEM_READ_PROT |
uc.UC_HOOK_MEM_WRITE_PROT |
uc.UC_HOOK_MEM_FETCH_PROT):
cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ status = _uc.uc_hook_add(
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) self._uch, ctypes.byref(_h2), htype, cb,
ctypes.cast(self._callback_count, ctypes.c_void_p),
ctypes.c_uint64(begin), ctypes.c_uint64(end)
)
else: else:
cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB) cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB)
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ status = _uc.uc_hook_add(
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) self._uch, ctypes.byref(_h2), htype, cb,
ctypes.cast(self._callback_count, ctypes.c_void_p),
ctypes.c_uint64(begin), ctypes.c_uint64(end)
)
# save the ctype function so gc will leave it alone. # save the ctype function so gc will leave it alone.
self._ctype_cbs[self._callback_count] = cb self._ctype_cbs[self._callback_count] = cb
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
return _h2.value return _h2.value
# delete a hook # delete a hook
def hook_del(self, h): def hook_del(self, h):
_h = uc_hook_h(h) _h = uc_hook_h(h)
status = _uc.uc_hook_del(self._uch, _h) status = _uc.uc_hook_del(self._uch, _h)
if status != UC_ERR_OK: if status != uc.UC_ERR_OK:
raise UcError(status) raise UcError(status)
h = 0 h = 0
# print out debugging info # print out debugging info
def debug(): def debug():
archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \ archs = {
"mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \ "arm": uc.UC_ARCH_ARM,
"m68k": UC_ARCH_M68K, "x86": UC_ARCH_X86 } "arm64": uc.UC_ARCH_ARM64,
"mips": uc.UC_ARCH_MIPS,
"sparc": uc.UC_ARCH_SPARC,
"m68k": uc.UC_ARCH_M68K,
"x86": uc.UC_ARCH_X86,
}
all_archs = "" all_archs = ""
keys = archs.keys() keys = archs.keys()
@ -436,7 +463,8 @@ def debug():
if uc_arch_supported(archs[k]): if uc_arch_supported(archs[k]):
all_archs += "-%s" % k all_archs += "-%s" % k
(major, minor, _combined) = uc_version() major, minor, _combined = uc_version()
return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR) return "python-%s-c%u.%u-b%u.%u" % (
all_archs, major, minor, uc.UC_API_MAJOR, uc.UC_API_MINOR
)