diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 6f106a3e..0f42d3d7 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -6,9 +6,9 @@ open System [] module Common = + let UC_API_MAJOR = 1 - let UC_API_MAJOR = 0 - let UC_API_MINOR = 9 + let UC_API_MINOR = 0 let UC_SECOND_SCALE = 1000000 let UC_MILISECOND_SCALE = 1000 let UC_ARCH_ARM = 1 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 8d634be9..1faff075 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -1,9 +1,9 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go] const ( + API_MAJOR = 1 - API_MAJOR = 0 - API_MINOR = 9 + API_MINOR = 0 SECOND_SCALE = 1000000 MILISECOND_SCALE = 1000 ARCH_ARM = 1 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 0fe4f193..64b52236 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -3,9 +3,9 @@ package unicorn; public interface UnicornConst { + public static final int UC_API_MAJOR = 1; - public static final int UC_API_MAJOR = 0; - public static final int UC_API_MINOR = 9; + public static final int UC_API_MINOR = 0; public static final int UC_SECOND_SCALE = 1000000; public static final int UC_MILISECOND_SCALE = 1000; public static final int UC_ARCH_ARM = 1; diff --git a/bindings/python/sample_x86.py b/bindings/python/sample_x86.py index b470f4ce..32947a3c 100755 --- a/bindings/python/sample_x86.py +++ b/bindings/python/sample_x86.py @@ -291,8 +291,8 @@ def test_i386_inout(): mu.hook_add(UC_HOOK_CODE, hook_code) # handle IN & OUT instruction - mu.hook_add(UC_HOOK_INSN, hook_in, None, UC_X86_INS_IN) - mu.hook_add(UC_HOOK_INSN, hook_out, None, UC_X86_INS_OUT) + mu.hook_add(UC_HOOK_INSN, hook_in, None, 1, 0, UC_X86_INS_IN) + mu.hook_add(UC_HOOK_INSN, hook_out, None, 1, 0, UC_X86_INS_OUT) # emulate machine code in infinite time mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_INOUT)) @@ -417,7 +417,7 @@ def test_x86_64_syscall(): print('ERROR: was not expecting rax=%d in syscall' % rax) # hook interrupts for syscall - mu.hook_add(UC_HOOK_INSN, hook_syscall, None, UC_X86_INS_SYSCALL) + mu.hook_add(UC_HOOK_INSN, hook_syscall, None, 1, 0, UC_X86_INS_SYSCALL) # syscall handler is expecting rax=0x100 mu.reg_write(UC_X86_REG_RAX, 0x100) diff --git a/bindings/python/shellcode.py b/bindings/python/shellcode.py index a4a473b0..898ada7b 100755 --- a/bindings/python/shellcode.py +++ b/bindings/python/shellcode.py @@ -97,7 +97,7 @@ def test_i386(mode, code): mu.hook_add(UC_HOOK_INTR, hook_intr) # handle SYSCALL - mu.hook_add(UC_HOOK_INSN, hook_syscall, None, UC_X86_INS_SYSCALL) + mu.hook_add(UC_HOOK_INSN, hook_syscall, None, 1, 0, UC_X86_INS_SYSCALL) # emulate machine code in infinite time mu.emu_start(ADDRESS, ADDRESS + len(code)) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 476ac552..3d784368 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -315,7 +315,7 @@ class Uc(object): # add a hook - def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0): + def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0): _h2 = uc_hook_h() # save callback & user_data @@ -332,30 +332,28 @@ class Uc(object): 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) status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn) + cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end), insn) elif htype == UC_HOOK_INTR: 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, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) else: - begin = ctypes.c_uint64(arg1) - end = ctypes.c_uint64(arg2) if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): # set callback with wrapper, so it can be called # with this object as param 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, \ - ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) + ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) elif htype & UC_HOOK_MEM_READ_UNMAPPED or htype & UC_HOOK_MEM_WRITE_UNMAPPED or \ htype & UC_HOOK_MEM_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \ htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: 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, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + cb, ctypes.cast(self._callback_count, ctypes.c_void_p), ctypes.c_uint64(begin), ctypes.c_uint64(end)) else: 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, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + 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. self._ctype_cbs[self._callback_count] = cb diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 4e942ef5..bdb8ed01 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -1,7 +1,7 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py] +UC_API_MAJOR = 1 -UC_API_MAJOR = 0 -UC_API_MINOR = 9 +UC_API_MINOR = 0 UC_SECOND_SCALE = 1000000 UC_MILISECOND_SCALE = 1000 UC_ARCH_ARM = 1 diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index ae8cd736..35e745ca 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -57,8 +57,8 @@ typedef size_t uc_hook; #endif // Unicorn API version -#define UC_API_MAJOR 0 -#define UC_API_MINOR 9 +#define UC_API_MAJOR 1 +#define UC_API_MINOR 0 /* Macro to create combined version which can be compared to @@ -457,13 +457,19 @@ uc_err uc_emu_stop(uc_engine *uc); @callback: callback to be run when instruction is hit @user_data: user-defined data. This will be passed to callback function in its last argument @user_data + @begin: start address of the area where the callback is effect (inclusive) + @begin: end address of the area where the callback is effect (inclusive) + NOTE 1: the callback is called only if related address is in range [@begin, @end] + NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered @...: variable arguments (depending on @type) + NOTE: if @type = UC_HOOK_INSN, this is the instruction ID (ex: UC_X86_INS_OUT) @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT -uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...); +uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, + void *user_data, uint64_t begin, uint64_t end, ...); /* Unregister (remove) a hook callback. diff --git a/pkgconfig.mk b/pkgconfig.mk index 125322eb..e4374b15 100644 --- a/pkgconfig.mk +++ b/pkgconfig.mk @@ -2,8 +2,8 @@ # To be used to generate unicorn.pc for pkg-config # version major & minor -PKG_MAJOR = 0 -PKG_MINOR = 9 +PKG_MAJOR = 1 +PKG_MINOR = 0 # version bugfix level. Example: PKG_EXTRA = 1 PKG_EXTRA = diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 008f077d..dc1c2481 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -168,9 +168,9 @@ static void do_nx_demo(bool cause_fault) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -248,10 +248,10 @@ static void do_perms_demo(bool change_perms) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -326,10 +326,10 @@ static void do_unmap_demo(bool do_unmap) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } diff --git a/samples/sample_arm.c b/samples/sample_arm.c index 8a5067db..2c69ce6a 100644 --- a/samples/sample_arm.c +++ b/samples/sample_arm.c @@ -77,10 +77,10 @@ static void test_arm(void) uc_reg_write(uc, UC_ARM_REG_R3, &r3); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. @@ -128,10 +128,10 @@ static void test_thumb(void) uc_reg_write(uc, UC_ARM_REG_SP, &sp); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 39d500aa..785708d0 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -75,10 +75,10 @@ static void test_arm64(void) uc_reg_write(uc, UC_ARM64_REG_X15, &x15); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_m68k.c b/samples/sample_m68k.c index efda5294..4bbf1cce 100644 --- a/samples/sample_m68k.c +++ b/samples/sample_m68k.c @@ -108,10 +108,10 @@ static void test_m68k(void) uc_reg_write(uc, UC_M68K_REG_SR, &sr); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instruction - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_mips.c b/samples/sample_mips.c index b27a02b1..994047c2 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -72,10 +72,10 @@ static void test_mips_eb(void) uc_reg_write(uc, UC_MIPS_REG_1, &r1); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. @@ -122,10 +122,10 @@ static void test_mips_el(void) uc_reg_write(uc, UC_MIPS_REG_1, &r1); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing one instruction at ADDRESS with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index e6276b14..649a6dec 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -76,10 +76,10 @@ static void test_sparc(void) uc_reg_write(uc, UC_SPARC_REG_G3, &g3); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions with customized callback - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. diff --git a/samples/sample_x86.c b/samples/sample_x86.c index c57043d2..264015f2 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -219,10 +219,10 @@ static void test_i386(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instruction by having @begin > @end - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); @@ -289,10 +289,10 @@ static void test_i386_map_ptr(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instruction by having @begin > @end - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); @@ -345,10 +345,10 @@ static void test_i386_jump(void) } // tracing 1 basic block with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, ADDRESS, ADDRESS); // tracing 1 instruction at ADDRESS - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); @@ -447,10 +447,10 @@ static void test_i386_invalid_mem_read(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instruction by having @begin > @end - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0); @@ -505,13 +505,13 @@ static void test_i386_invalid_mem_write(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instruction by having @begin > @end - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // intercept invalid memory events - uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL); + uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0); @@ -576,10 +576,10 @@ static void test_i386_jump_invalid(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions by having @begin > @end - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); @@ -632,15 +632,15 @@ static void test_i386_inout(void) uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // uc IN instruction - uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, UC_X86_INS_IN); + uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, 1, 0, UC_X86_INS_IN); // uc OUT instruction - uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, UC_X86_INS_OUT); + uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, UC_X86_INS_OUT); // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); @@ -721,16 +721,16 @@ static void test_x86_64(void) uc_reg_write(uc, UC_X86_REG_R15, &r15); // tracing all basic blocks with customized callback - uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions in the range [ADDRESS, ADDRESS+20] - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20)); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, ADDRESS+20); // tracing all memory WRITE access (with @begin > @end) - uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, 1, 0); // tracing all memory READ access (with @begin > @end) - uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, 1, 0); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. @@ -804,7 +804,7 @@ static void test_x86_64_syscall(void) } // hook interrupts for syscall - uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, UC_X86_INS_SYSCALL); + uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL); // initialize machine registers uc_reg_write(uc, UC_X86_REG_RAX, &rax); diff --git a/samples/shellcode.c b/samples/shellcode.c index a6fd5221..8ad0c69b 100644 --- a/samples/shellcode.c +++ b/samples/shellcode.c @@ -138,7 +138,7 @@ static void test_i386(void) uc_hook_add(uc, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0); // handle interrupt ourself - uc_hook_add(uc, &trace2, UC_HOOK_INTR, hook_intr, NULL); + uc_hook_add(uc, &trace2, UC_HOOK_INTR, hook_intr, NULL, 1, 0); printf("\n>>> Start tracing this Linux code\n"); diff --git a/tests/unit/test_mem_high.c b/tests/unit/test_mem_high.c index 5e2244e5..c8e58288 100644 --- a/tests/unit/test_mem_high.c +++ b/tests/unit/test_mem_high.c @@ -79,7 +79,7 @@ static void test_high_address_reads(void **state) uint8_t code[] = {0x48,0x8b,0x00,0x90,0x90,0x90,0x90}; // mov rax, [rax], nops uc_assert_success(uc_mem_map(uc, base_addr, 4096, UC_PROT_ALL)); uc_assert_success(uc_mem_write(uc, base_addr, code, 7)); - uc_assert_success(uc_hook_add(uc, &trace2, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0)); + uc_assert_success(uc_hook_add(uc, &trace2, UC_HOOK_MEM_READ, hook_mem64, NULL, 1, 0)); uc_assert_success(uc_emu_start(uc, base_addr, base_addr + 3, 0, 0)); if(number_of_memory_reads != 1) { fail_msg("wrong number of memory reads for instruction %i", number_of_memory_reads); diff --git a/tests/unit/test_multihook.c b/tests/unit/test_multihook.c index eb831865..c131481d 100644 --- a/tests/unit/test_multihook.c +++ b/tests/unit/test_multihook.c @@ -96,8 +96,8 @@ static void test_basic_blocks(void **state) OK(uc_mem_write(uc, address, code, sizeof(code))); // trace all basic blocks - OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, (uint64_t)1, (uint64_t)0)); - OK(uc_hook_add(uc, &trace2, UC_HOOK_BLOCK, test_basic_blocks_hook2, &bbtest, (uint64_t)1, (uint64_t)0)); + OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, 1, 0)); + OK(uc_hook_add(uc, &trace2, UC_HOOK_BLOCK, test_basic_blocks_hook2, &bbtest, 1, 0)); OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); } diff --git a/tests/unit/test_pc_change.c b/tests/unit/test_pc_change.c index 7994e772..c2ec73a8 100644 --- a/tests/unit/test_pc_change.c +++ b/tests/unit/test_pc_change.c @@ -83,7 +83,7 @@ static void test_pc_change(void **state) printf("ECX = %u, EDX = %u\n", r_ecx, r_edx); // trace all instructions - OK(uc_hook_add(uc, &trace1, UC_HOOK_CODE, test_code_hook, NULL, (uint64_t)1, (uint64_t)0)); + OK(uc_hook_add(uc, &trace1, UC_HOOK_CODE, test_code_hook, NULL, 1, 0)); OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index bf691e8b..1d6ba7a0 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -273,16 +273,16 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) UC_HOOK_CODE, hook_code32, NULL, - (uint64_t)1, - (uint64_t)0)); + 1, + 0)); uc_assert_success(uc_hook_add(uc, &trace2, UC_HOOK_MEM_VALID, hook_mem32, NULL, - (uint64_t)1, - (uint64_t)0)); + 1, + 0)); uc_assert_success(uc_emu_start(uc, #ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 04441123..348cd5cd 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -85,7 +85,7 @@ static void test_basic_blocks(void **state) OK(uc_mem_write(uc, address, code, sizeof(code))); // trace all basic blocks - OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, (uint64_t)1, (uint64_t)0)); + OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, 1, 0)); OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); } @@ -144,11 +144,11 @@ static void test_i386(void **state) uc_assert_success(err); // tracing all basic blocks with customized callback - err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); uc_assert_success(err); // tracing all instruction by having @begin > @end - err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); uc_assert_success(err); // emulate machine code in infinite time @@ -194,11 +194,11 @@ static void test_i386_jump(void **state) uc_assert_success(err); // tracing 1 basic block with customized callback - err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)address, (uint64_t)address); + err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, address, address); uc_assert_success(err); // tracing 1 instruction at address - err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)address, (uint64_t)address); + err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, address, address); uc_assert_success(err); // emulate machine code in infinite time @@ -302,19 +302,19 @@ static void test_i386_inout(void **state) uc_assert_success(err); // tracing all basic blocks with customized callback - err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); uc_assert_success(err); // tracing all instructions - err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); uc_assert_success(err); // uc IN instruction - err = uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, UC_X86_INS_IN); + err = uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, 1, 0, UC_X86_INS_IN); uc_assert_success(err); // uc OUT instruction - err = uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, UC_X86_INS_OUT); + err = uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, UC_X86_INS_OUT); uc_assert_success(err); // emulate machine code in infinite time @@ -566,19 +566,19 @@ static void test_x86_64(void **state) uc_assert_success(uc_reg_write(uc, UC_X86_REG_R15, &r15)); // tracing all basic blocks with customized callback - err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); uc_assert_success(err); // tracing all instructions in the range [address, address+20] - err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)address, (uint64_t)(address+20)); + err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, address, address+20); uc_assert_success(err); // tracing all memory WRITE access (with @begin > @end) - err = uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, 1, 0); uc_assert_success(err); // tracing all memory READ access (with @begin > @end) - err = uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, 1, 0); uc_assert_success(err); // emulate machine code in infinite time (last param = 0), or when @@ -662,7 +662,7 @@ static void test_x86_64_syscall(void **state) uc_assert_success(err); // hook interrupts for syscall - err = uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, UC_X86_INS_SYSCALL); + err = uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL); uc_assert_success(err); // initialize machine registers diff --git a/uc.c b/uc.c index 4eb04f8f..298d21e0 100644 --- a/uc.c +++ b/uc.c @@ -551,7 +551,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time } // set up count hook to count instructions. if (count > 0 && uc->count_hook == 0) { - uc_err err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL); + uc_err err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0); if (err != UC_ERR_OK) { return err; } @@ -565,6 +565,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time if (timeout) enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds + uc->pause_all_vcpus(uc); // emulation is done uc->emulation_done = true; @@ -964,41 +965,42 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) } UNICORN_EXPORT -uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...) +uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, + void *user_data, uint64_t begin, uint64_t end, ...) { - va_list valist; int ret = UC_ERR_OK; - - va_start(valist, user_data); + int i = 0; struct hook *hook = calloc(1, sizeof(struct hook)); if (hook == NULL) { return UC_ERR_NOMEM; } + + hook->begin = begin; + hook->end = end; hook->type = type; hook->callback = callback; hook->user_data = user_data; hook->refs = 0; *hh = (uc_hook)hook; - // everybody but HOOK_INSN gets begin/end, so exit early here. + // UC_HOOK_INSN has an extra argument for instruction ID if (type & UC_HOOK_INSN) { + va_list valist; + + va_start(valist, end); hook->insn = va_arg(valist, int); - hook->begin = 1; - hook->end = 0; + va_end(valist); + if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { free(hook); return UC_ERR_NOMEM; } + hook->refs++; return UC_ERR_OK; } - hook->begin = va_arg(valist, uint64_t); - hook->end = va_arg(valist, uint64_t); - va_end(valist); - - int i = 0; while ((type >> i) > 0) { if ((type >> i) & 1) { // TODO: invalid hook error?