Skip to content

Commit

Permalink
Remove the size limit for memory read and write
Browse files Browse the repository at this point in the history
Eliminate the maximum size restriction for uc_mem_read and uc_mem_write. This
change is required to support applications, such as LLVM CFI, that map or unmap
memory blocks with sizes equal to or greater than INT_MAX.
  • Loading branch information
secretnonempty committed Mar 14, 2023
1 parent 7b8c63d commit 7c0520f
Show file tree
Hide file tree
Showing 35 changed files with 317 additions and 248 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
namespace UnicornManaged.Binding
namespace UnicornEngine.Binding

open System
open System.Runtime.InteropServices

module NativeBinding =

[<AutoOpen>]
module private Imported =
module private Imported =

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_version(UIntPtr major, UIntPtr minor)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_open(UInt32 arch, UInt32 mode, UIntPtr[] engine)
extern Int32 uc_open(UInt32 arch, UInt32 mode, UIntPtr[] engine)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_close(UIntPtr eng)
extern Int32 uc_close(UIntPtr eng)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_map(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perm)
extern Int32 uc_mem_map(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perm)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_map_ptr(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perm, UIntPtr ptr)
extern Int32 uc_mem_map_ptr(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perm, UIntPtr ptr)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_unmap(UIntPtr eng, UInt64 address, UIntPtr size)
extern Int32 uc_mem_unmap(UIntPtr eng, UInt64 address, UInt64 size)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_protect(UIntPtr eng, UInt64 address, UIntPtr size, UInt32 perms)
extern Int32 uc_mem_protect(UIntPtr eng, UInt64 address, UInt64 size, UInt32 perms)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_write(UIntPtr eng, UInt64 address, Byte[] value, UIntPtr size)
extern Int32 uc_mem_write(UIntPtr eng, UInt64 address, Byte[] value, UInt64 size)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_mem_read(UIntPtr eng, UInt64 address, Byte[] value, UIntPtr size)
extern Int32 uc_mem_read(UIntPtr eng, UInt64 address, Byte[] value, UInt64 size)

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)>]
extern Int32 uc_reg_write(UIntPtr eng, Int32 regId, Byte[] value)
Expand Down Expand Up @@ -67,7 +67,7 @@ module NativeBinding =

[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl, EntryPoint = "uc_hook_add")>]
extern Int32 uc_hook_add_arg0_arg1(UIntPtr eng, UIntPtr hh, Int32 callbackType, UIntPtr callback, IntPtr userData, UInt64 hookbegin, UInt64 hookend, UInt64 arg0, UInt64 arg1)

let instance =
{new IBinding with
member thi.Version(major, minor) = uc_version(major, minor)
Expand All @@ -90,4 +90,4 @@ module NativeBinding =
member thi.HookAddNoarg(eng, hh, callbackType, callback, userData, hookBegin, hookEnd) = uc_hook_add_noarg(eng, hh, callbackType, callback, userData, hookBegin, hookEnd)
member thi.HookAddArg0(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0) = uc_hook_add_arg0(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0)
member thi.HookAddArg0Arg1(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0, arg1) = uc_hook_add_arg0_arg1(eng, hh, callbackType, callback, userData, hookBegin, hookEnd, arg0, arg1)
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 6 additions & 6 deletions bindings/go/unicorn/unicorn.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@ func (u *uc) MemWrite(addr uint64, data []byte) error {
if len(data) == 0 {
return nil
}
return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.size_t(len(data))))
return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.uint64_t(len(data))))
}

func (u *uc) MemReadInto(dst []byte, addr uint64) error {
if len(dst) == 0 {
return nil
}
return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.size_t(len(dst))))
return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.uint64_t(len(dst))))
}

func (u *uc) MemRead(addr, size uint64) ([]byte, error) {
Expand All @@ -206,23 +206,23 @@ func (u *uc) MemRead(addr, size uint64) ([]byte, error) {
}

func (u *uc) MemMapProt(addr, size uint64, prot int) error {
return errReturn(C.uc_mem_map(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot)))
return errReturn(C.uc_mem_map(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot)))
}

func (u *uc) MemMap(addr, size uint64) error {
return u.MemMapProt(addr, size, PROT_ALL)
}

func (u *uc) MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error {
return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot), ptr))
return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot), ptr))
}

func (u *uc) MemProtect(addr, size uint64, prot int) error {
return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot)))
return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot)))
}

func (u *uc) MemUnmap(addr, size uint64) error {
return errReturn(C.uc_mem_unmap(u.handle, C.uint64_t(addr), C.size_t(size)))
return errReturn(C.uc_mem_unmap(u.handle, C.uint64_t(addr), C.uint64_t(size)))
}

func (u *uc) Query(queryType int) (uint64, error) {
Expand Down
12 changes: 6 additions & 6 deletions bindings/java/unicorn_Unicorn.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write
uc_engine *eng = getEngine(env, self);
jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL);
jsize size = (*env)->GetArrayLength(env, bytes);
uc_err err = uc_mem_write(eng, (uint64_t)address, array, (size_t)size);
uc_err err = uc_mem_write(eng, (uint64_t)address, array, (uint64_t)size);

if (err != UC_ERR_OK) {
throwException(env, err);
Expand All @@ -467,7 +467,7 @@ JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read

jbyteArray bytes = (*env)->NewByteArray(env, (jsize)size);
jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL);
uc_err err = uc_mem_read(eng, (uint64_t)address, array, (size_t)size);
uc_err err = uc_mem_read(eng, (uint64_t)address, array, (uint64_t)size);
if (err != UC_ERR_OK) {
throwException(env, err);
}
Expand Down Expand Up @@ -634,7 +634,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms) {
uc_engine *eng = getEngine(env, self);

uc_err err = uc_mem_map(eng, (uint64_t)address, (size_t)size, (uint32_t)perms);
uc_err err = uc_mem_map(eng, (uint64_t)address, (uint64_t)size, (uint32_t)perms);
if (err != UC_ERR_OK) {
throwException(env, err);
}
Expand All @@ -649,7 +649,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map_1ptr
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms, jbyteArray block) {
uc_engine *eng = getEngine(env, self);
jbyte *array = (*env)->GetByteArrayElements(env, block, NULL);
uc_err err = uc_mem_map_ptr(eng, (uint64_t)address, (size_t)size, (uint32_t)perms, (void*)array);
uc_err err = uc_mem_map_ptr(eng, (uint64_t)address, (uint64_t)size, (uint32_t)perms, (void*)array);
if (err != UC_ERR_OK) {
throwException(env, err);
}
Expand All @@ -667,7 +667,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1unmap
(JNIEnv *env, jobject self, jlong address, jlong size) {
uc_engine *eng = getEngine(env, self);

uc_err err = uc_mem_unmap(eng, (uint64_t)address, (size_t)size);
uc_err err = uc_mem_unmap(eng, (uint64_t)address, (uint64_t)size);
if (err != UC_ERR_OK) {
throwException(env, err);
}
Expand All @@ -685,7 +685,7 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1protect
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms) {
uc_engine *eng = getEngine(env, self);

uc_err err = uc_mem_protect(eng, (uint64_t)address, (size_t)size, (uint32_t)perms);
uc_err err = uc_mem_protect(eng, (uint64_t)address, (uint64_t)size, (uint32_t)perms);
if (err != UC_ERR_OK) {
throwException(env, err);
}
Expand Down
12 changes: 6 additions & 6 deletions bindings/pascal/unicorn/Unicorn_dyn.pas
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ uc_mem_region = record
for detailed error).
*)
uc_mem_write_ : function (uc : uc_engine; address : UInt64; const bytes : Pointer;
size : Cardinal) : uc_err; cdecl;
size : UInt64) : uc_err; cdecl;

(*
Read a range of bytes in memory.
Expand All @@ -307,7 +307,7 @@ uc_mem_region = record
for detailed error).
*)
uc_mem_read_ : function (uc : uc_engine; address : UInt64; bytes : Pointer;
size : Cardinal) : uc_err; cdecl;
size : UInt64) : uc_err; cdecl;

(*
Emulate machine code in a specific duration of time.
Expand Down Expand Up @@ -400,7 +400,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer;
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
*)
uc_mem_map : function (uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32) : uc_err; cdecl;
uc_mem_map : function (uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32) : uc_err; cdecl;


(*
Expand All @@ -422,7 +422,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer;
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error).
*)
uc_mem_map_ptr : function(uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32; ptr : Pointer) : uc_err; cdecl;
uc_mem_map_ptr : function(uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32; ptr : Pointer) : uc_err; cdecl;


(*
Expand All @@ -438,7 +438,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer;
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum \
for detailed error).
*)
uc_mem_unmap : function (uc : uc_engine; address : UInt64; size : Cardinal) : uc_err; cdecl ;
uc_mem_unmap : function (uc : uc_engine; address : UInt64; size : UInt64) : uc_err; cdecl ;

(*
Set memory permissions for emulation memory.
Expand All @@ -456,7 +456,7 @@ function (uc : uc_engine; var hh : uc_hook; _type : integer;
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum \
for detailed error).
*)
uc_mem_protect : function (uc : uc_engine; address : UInt64; size : Cardinal; perms : UInt32) : uc_err; cdecl ;
uc_mem_protect : function (uc : uc_engine; address : UInt64; size : UInt64; perms : UInt32) : uc_err; cdecl ;

(*
Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr()
Expand Down
50 changes: 25 additions & 25 deletions bindings/python/unicorn/unicorn.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def _load_lib(path, lib_name):
for _path in _path_list:
if _path is None:
continue

_uc = _load_lib(_path, "libunicorn.so")
if _uc is not None:
# In this case, show a warning for users
Expand Down Expand Up @@ -153,16 +153,16 @@ class uc_tb(ctypes.Structure):
_setup_prototype(_uc, "uc_errno", ucerr, uc_engine)
_setup_prototype(_uc, "uc_reg_read", ucerr, uc_engine, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_reg_write", ucerr, uc_engine, ctypes.c_int, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_read", ucerr, uc_engine, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_mem_write", ucerr, uc_engine, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
_setup_prototype(_uc, "uc_mem_read", ucerr, uc_engine, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_uint64)
_setup_prototype(_uc, "uc_mem_write", ucerr, uc_engine, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_uint64)
_setup_prototype(_uc, "uc_emu_start", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
_setup_prototype(_uc, "uc_emu_stop", ucerr, uc_engine)
_setup_prototype(_uc, "uc_hook_del", ucerr, uc_engine, uc_hook_h)
_setup_prototype(_uc, "uc_mmio_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
_setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
_setup_prototype(_uc, "uc_mmio_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint32)
_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint32, ctypes.c_void_p)
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64)
_setup_prototype(_uc, "uc_mem_protect", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint32)
_setup_prototype(_uc, "uc_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t))
_setup_prototype(_uc, "uc_context_alloc", ucerr, uc_engine, ctypes.POINTER(uc_context))
_setup_prototype(_uc, "uc_free", ucerr, ctypes.c_void_p)
Expand Down Expand Up @@ -593,7 +593,7 @@ def _mmio_map_write_cb(self, handle, offset, size, value, user_data):
(cb, data) = self._callbacks[user_data]
cb(self, offset, size, value, data)

def mmio_map(self, address: int, size: int,
def mmio_map(self, address: int, size: int,
read_cb: UC_MMIO_READ_TYPE, user_data_read: Any,
write_cb: UC_MMIO_WRITE_TYPE, user_data_write: Any):
internal_read_cb = ctypes.cast(UC_MMIO_READ_CB(self._mmio_map_read_cb), UC_MMIO_READ_CB)
Expand All @@ -609,7 +609,7 @@ def mmio_map(self, address: int, size: int,
status = _uc.uc_mmio_map(self._uch, address, size, internal_read_cb, read_count, internal_write_cb, write_count)
if status != uc.UC_ERR_OK:
raise UcError(status)

# https://docs.python.org/3/library/ctypes.html#callback-functions
self._ctype_cbs.append(internal_read_cb)
self._ctype_cbs.append(internal_write_cb)
Expand Down Expand Up @@ -731,12 +731,12 @@ def __ctl(self, ctl, nr, rw):

def __ctl_r(self, ctl, nr):
return self.__ctl(ctl, nr, uc.UC_CTL_IO_READ)

def __ctl_w(self, ctl, nr):
return self.__ctl(ctl, nr, uc.UC_CTL_IO_WRITE)

def __ctl_rw(self, ctl, nr):
return self.__ctl(ctl, nr, uc.UC_CTL_IO_READ_WRITE)
return self.__ctl(ctl, nr, uc.UC_CTL_IO_READ_WRITE)

def __ctl_r_1_arg(self, ctl, ctp):
arg = ctp()
Expand All @@ -746,7 +746,7 @@ def __ctl_r_1_arg(self, ctl, ctp):
def __ctl_w_1_arg(self, ctl, val, ctp):
arg = ctp(val)
self.ctl(self.__ctl_w(ctl, 1), arg)

def __ctl_w_2_arg(self, ctl, val1, val2, ctp1, ctp2):
arg1 = ctp1(val1)
arg2 = ctp2(val2)
Expand All @@ -763,7 +763,7 @@ def ctl_get_mode(self):

def ctl_get_page_size(self):
return self.__ctl_r_1_arg(uc.UC_CTL_UC_PAGE_SIZE, ctypes.c_uint32)

def ctl_set_page_size(self, val: int):
self.__ctl_w_1_arg(uc.UC_CTL_UC_PAGE_SIZE, val, ctypes.c_uint32)

Expand All @@ -772,10 +772,10 @@ def ctl_get_arch(self):

def ctl_get_timeout(self):
return self.__ctl_r_1_arg(uc.UC_CTL_UC_TIMEOUT, ctypes.c_uint64)

def ctl_exits_enabled(self, val: bool):
self.__ctl_w_1_arg(uc.UC_CTL_UC_USE_EXITS, val, ctypes.c_int)

def ctl_get_exits_cnt(self):
return self.__ctl_r_1_arg(uc.UC_CTL_UC_EXITS_CNT, ctypes.c_size_t)

Expand All @@ -793,7 +793,7 @@ def ctl_set_exits(self, exits: List[int]):

def ctl_get_cpu_model(self):
return self.__ctl_r_1_arg(uc.UC_CTL_CPU_MODEL, ctypes.c_int)

def ctl_set_cpu_model(self, val: int):
self.__ctl_w_1_arg(uc.UC_CTL_CPU_MODEL, val, ctypes.c_int)

Expand All @@ -802,7 +802,7 @@ def ctl_remove_cache(self, addr: int, end: int):

def ctl_request_cache(self, addr: int):
return self.__ctl_rw_1_1_arg(uc.UC_CTL_TB_REQUEST_CACHE, addr, ctypes.c_uint64, uc_tb)

def ctl_flush_tb(self):
self.ctl(self.__ctl_w(uc.UC_CTL_TB_FLUSH, 0))

Expand Down Expand Up @@ -963,7 +963,7 @@ def size(self):
@property
def arch(self):
return self._arch

@property
def mode(self):
return self._mode
Expand Down Expand Up @@ -1012,11 +1012,11 @@ def __del__(self):
UC_HOOK_TCG_OPCODE_TYPE = Callable[[Uc, int, int, int, Any], None]

UC_HOOK_CALLBACK_TYPE = Union[
UC_HOOK_CODE_TYPE,
UC_HOOK_INSN_INVALID_TYPE,
UC_HOOK_MEM_INVALID_TYPE,
UC_HOOK_MEM_ACCESS_TYPE,
UC_HOOK_INSN_IN_TYPE,
UC_HOOK_CODE_TYPE,
UC_HOOK_INSN_INVALID_TYPE,
UC_HOOK_MEM_INVALID_TYPE,
UC_HOOK_MEM_ACCESS_TYPE,
UC_HOOK_INSN_IN_TYPE,
UC_HOOK_INSN_OUT_TYPE,
UC_HOOK_INSN_SYSCALL_TYPE,
UC_HOOK_INSN_SYS_TYPE,
Expand Down

0 comments on commit 7c0520f

Please sign in to comment.