Merge branch 'hook'

This commit is contained in:
Nguyen Anh Quynh 2016-02-17 09:37:17 +08:00
commit 871cdb692f
23 changed files with 109 additions and 103 deletions

View File

@ -6,9 +6,9 @@ open System
[<AutoOpen>] [<AutoOpen>]
module Common = module Common =
let UC_API_MAJOR = 1
let UC_API_MAJOR = 0 let UC_API_MINOR = 0
let UC_API_MINOR = 9
let UC_SECOND_SCALE = 1000000 let UC_SECOND_SCALE = 1000000
let UC_MILISECOND_SCALE = 1000 let UC_MILISECOND_SCALE = 1000
let UC_ARCH_ARM = 1 let UC_ARCH_ARM = 1

View File

@ -1,9 +1,9 @@
package unicorn package unicorn
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go] // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
const ( const (
API_MAJOR = 1
API_MAJOR = 0 API_MINOR = 0
API_MINOR = 9
SECOND_SCALE = 1000000 SECOND_SCALE = 1000000
MILISECOND_SCALE = 1000 MILISECOND_SCALE = 1000
ARCH_ARM = 1 ARCH_ARM = 1

View File

@ -3,9 +3,9 @@
package unicorn; package unicorn;
public interface UnicornConst { 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 = 0;
public static final int UC_API_MINOR = 9;
public static final int UC_SECOND_SCALE = 1000000; public static final int UC_SECOND_SCALE = 1000000;
public static final int UC_MILISECOND_SCALE = 1000; public static final int UC_MILISECOND_SCALE = 1000;
public static final int UC_ARCH_ARM = 1; public static final int UC_ARCH_ARM = 1;

View File

@ -291,8 +291,8 @@ def test_i386_inout():
mu.hook_add(UC_HOOK_CODE, hook_code) mu.hook_add(UC_HOOK_CODE, hook_code)
# handle IN & OUT instruction # handle IN & OUT instruction
mu.hook_add(UC_HOOK_INSN, hook_in, None, UC_X86_INS_IN) mu.hook_add(UC_HOOK_INSN, hook_in, None, 1, 0, UC_X86_INS_IN)
mu.hook_add(UC_HOOK_INSN, hook_out, None, UC_X86_INS_OUT) mu.hook_add(UC_HOOK_INSN, hook_out, None, 1, 0, UC_X86_INS_OUT)
# emulate machine code in infinite time # emulate machine code in infinite time
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_INOUT)) 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) print('ERROR: was not expecting rax=%d in syscall' % rax)
# hook interrupts for syscall # 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 # syscall handler is expecting rax=0x100
mu.reg_write(UC_X86_REG_RAX, 0x100) mu.reg_write(UC_X86_REG_RAX, 0x100)

View File

@ -97,7 +97,7 @@ def test_i386(mode, code):
mu.hook_add(UC_HOOK_INTR, hook_intr) mu.hook_add(UC_HOOK_INTR, hook_intr)
# handle SYSCALL # 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 # emulate machine code in infinite time
mu.emu_start(ADDRESS, ADDRESS + len(code)) mu.emu_start(ADDRESS, ADDRESS + len(code))

View File

@ -315,7 +315,7 @@ class Uc(object):
# add a hook # 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() _h2 = uc_hook_h()
# save callback & user_data # 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 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(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: elif htype == 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(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: else:
begin = ctypes.c_uint64(arg1)
end = ctypes.c_uint64(arg2)
if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): if htype in (UC_HOOK_BLOCK, 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(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 \ 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_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \
htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: 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) 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(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: 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(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. # save the ctype function so gc will leave it alone.
self._ctype_cbs[self._callback_count] = cb self._ctype_cbs[self._callback_count] = cb

View File

@ -1,7 +1,7 @@
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py] # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py]
UC_API_MAJOR = 1
UC_API_MAJOR = 0 UC_API_MINOR = 0
UC_API_MINOR = 9
UC_SECOND_SCALE = 1000000 UC_SECOND_SCALE = 1000000
UC_MILISECOND_SCALE = 1000 UC_MILISECOND_SCALE = 1000
UC_ARCH_ARM = 1 UC_ARCH_ARM = 1

View File

@ -57,8 +57,8 @@ typedef size_t uc_hook;
#endif #endif
// Unicorn API version // Unicorn API version
#define UC_API_MAJOR 0 #define UC_API_MAJOR 1
#define UC_API_MINOR 9 #define UC_API_MINOR 0
/* /*
Macro to create combined version which can be compared to 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 @callback: callback to be run when instruction is hit
@user_data: user-defined data. This will be passed to callback function in its @user_data: user-defined data. This will be passed to callback function in its
last argument @user_data 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) @...: 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 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
for detailed error). for detailed error).
*/ */
UNICORN_EXPORT 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. Unregister (remove) a hook callback.

View File

@ -2,8 +2,8 @@
# To be used to generate unicorn.pc for pkg-config # To be used to generate unicorn.pc for pkg-config
# version major & minor # version major & minor
PKG_MAJOR = 0 PKG_MAJOR = 1
PKG_MINOR = 9 PKG_MINOR = 0
# version bugfix level. Example: PKG_EXTRA = 1 # version bugfix level. Example: PKG_EXTRA = 1
PKG_EXTRA = PKG_EXTRA =

View File

@ -168,9 +168,9 @@ static void do_nx_demo(bool cause_fault)
} }
// intercept code and invalid memory events // 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, 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"); printf("not ok - Failed to install hooks\n");
return; return;
} }
@ -248,10 +248,10 @@ static void do_perms_demo(bool change_perms)
} }
// intercept code and invalid memory events // 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_add(uc, &trace1,
UC_HOOK_MEM_INVALID, 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"); printf("not ok - Failed to install hooks\n");
return; return;
} }
@ -326,10 +326,10 @@ static void do_unmap_demo(bool do_unmap)
} }
// intercept code and invalid memory events // 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_add(uc, &trace1,
UC_HOOK_MEM_INVALID, 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"); printf("not ok - Failed to install hooks\n");
return; return;
} }

View File

@ -77,10 +77,10 @@ static void test_arm(void)
uc_reg_write(uc, UC_ARM_REG_R3, &r3); uc_reg_write(uc, UC_ARM_REG_R3, &r3);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.
@ -128,10 +128,10 @@ static void test_thumb(void)
uc_reg_write(uc, UC_ARM_REG_SP, &sp); uc_reg_write(uc, UC_ARM_REG_SP, &sp);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.

View File

@ -75,10 +75,10 @@ static void test_arm64(void)
uc_reg_write(uc, UC_ARM64_REG_X15, &x15); uc_reg_write(uc, UC_ARM64_REG_X15, &x15);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.

View File

@ -108,10 +108,10 @@ static void test_m68k(void)
uc_reg_write(uc, UC_M68K_REG_SR, &sr); uc_reg_write(uc, UC_M68K_REG_SR, &sr);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.

View File

@ -72,10 +72,10 @@ static void test_mips_eb(void)
uc_reg_write(uc, UC_MIPS_REG_1, &r1); uc_reg_write(uc, UC_MIPS_REG_1, &r1);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.
@ -122,10 +122,10 @@ static void test_mips_el(void)
uc_reg_write(uc, UC_MIPS_REG_1, &r1); uc_reg_write(uc, UC_MIPS_REG_1, &r1);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.

View File

@ -76,10 +76,10 @@ static void test_sparc(void)
uc_reg_write(uc, UC_SPARC_REG_G3, &g3); uc_reg_write(uc, UC_SPARC_REG_G3, &g3);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.

View File

@ -219,10 +219,10 @@ static void test_i386(void)
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); 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 // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// tracing all basic blocks with customized callback // 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 // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
// tracing all basic blocks with customized callback // 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 // 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
// tracing all basic blocks with customized callback // 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 // 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 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 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 // emulate machine code in infinite time
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); 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); uc_reg_write(uc, UC_X86_REG_R15, &r15);
// tracing all basic blocks with customized callback // 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] // 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) // 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) // 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 // emulate machine code in infinite time (last param = 0), or when
// finishing all the code. // finishing all the code.
@ -804,7 +804,7 @@ static void test_x86_64_syscall(void)
} }
// hook interrupts for syscall // 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 // initialize machine registers
uc_reg_write(uc, UC_X86_REG_RAX, &rax); uc_reg_write(uc, UC_X86_REG_RAX, &rax);

View File

@ -138,7 +138,7 @@ static void test_i386(void)
uc_hook_add(uc, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0); uc_hook_add(uc, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0);
// handle interrupt ourself // 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"); printf("\n>>> Start tracing this Linux code\n");

View File

@ -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 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_map(uc, base_addr, 4096, UC_PROT_ALL));
uc_assert_success(uc_mem_write(uc, base_addr, code, 7)); 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)); uc_assert_success(uc_emu_start(uc, base_addr, base_addr + 3, 0, 0));
if(number_of_memory_reads != 1) { if(number_of_memory_reads != 1) {
fail_msg("wrong number of memory reads for instruction %i", number_of_memory_reads); fail_msg("wrong number of memory reads for instruction %i", number_of_memory_reads);

View File

@ -96,8 +96,8 @@ static void test_basic_blocks(void **state)
OK(uc_mem_write(uc, address, code, sizeof(code))); OK(uc_mem_write(uc, address, code, sizeof(code)));
// trace all basic blocks // 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_hook_add(uc, &trace2, UC_HOOK_BLOCK, test_basic_blocks_hook2, &bbtest, (uint64_t)1, (uint64_t)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)); OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0));
} }

View File

@ -83,7 +83,7 @@ static void test_pc_change(void **state)
printf("ECX = %u, EDX = %u\n", r_ecx, r_edx); printf("ECX = %u, EDX = %u\n", r_ecx, r_edx);
// trace all instructions // 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)); OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0));

View File

@ -273,16 +273,16 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state)
UC_HOOK_CODE, UC_HOOK_CODE,
hook_code32, hook_code32,
NULL, NULL,
(uint64_t)1, 1,
(uint64_t)0)); 0));
uc_assert_success(uc_hook_add(uc, uc_assert_success(uc_hook_add(uc,
&trace2, &trace2,
UC_HOOK_MEM_VALID, UC_HOOK_MEM_VALID,
hook_mem32, hook_mem32,
NULL, NULL,
(uint64_t)1, 1,
(uint64_t)0)); 0));
uc_assert_success(uc_emu_start(uc, uc_assert_success(uc_emu_start(uc,
#ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE #ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE

View File

@ -85,7 +85,7 @@ static void test_basic_blocks(void **state)
OK(uc_mem_write(uc, address, code, sizeof(code))); OK(uc_mem_write(uc, address, code, sizeof(code)));
// trace all basic blocks // 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)); 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); uc_assert_success(err);
// tracing all basic blocks with customized callback // 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); uc_assert_success(err);
// tracing all instruction by having @begin > @end // 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); uc_assert_success(err);
// emulate machine code in infinite time // emulate machine code in infinite time
@ -194,11 +194,11 @@ static void test_i386_jump(void **state)
uc_assert_success(err); uc_assert_success(err);
// tracing 1 basic block with customized callback // 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); uc_assert_success(err);
// tracing 1 instruction at address // 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); uc_assert_success(err);
// emulate machine code in infinite time // emulate machine code in infinite time
@ -302,19 +302,19 @@ static void test_i386_inout(void **state)
uc_assert_success(err); uc_assert_success(err);
// tracing all basic blocks with customized callback // 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); uc_assert_success(err);
// tracing all instructions // 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_assert_success(err);
// uc IN instruction // 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_assert_success(err);
// uc OUT instruction // 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); uc_assert_success(err);
// emulate machine code in infinite time // 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)); uc_assert_success(uc_reg_write(uc, UC_X86_REG_R15, &r15));
// tracing all basic blocks with customized callback // 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); uc_assert_success(err);
// tracing all instructions in the range [address, address+20] // 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); uc_assert_success(err);
// tracing all memory WRITE access (with @begin > @end) // 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); uc_assert_success(err);
// tracing all memory READ access (with @begin > @end) // 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); uc_assert_success(err);
// emulate machine code in infinite time (last param = 0), or when // 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); uc_assert_success(err);
// hook interrupts for syscall // 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); uc_assert_success(err);
// initialize machine registers // initialize machine registers

28
uc.c
View File

@ -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. // set up count hook to count instructions.
if (count > 0 && uc->count_hook == 0) { 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) { if (err != UC_ERR_OK) {
return err; 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) if (timeout)
enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds
uc->pause_all_vcpus(uc); uc->pause_all_vcpus(uc);
// emulation is done // emulation is done
uc->emulation_done = true; uc->emulation_done = true;
@ -964,41 +965,42 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
} }
UNICORN_EXPORT 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; int ret = UC_ERR_OK;
int i = 0;
va_start(valist, user_data);
struct hook *hook = calloc(1, sizeof(struct hook)); struct hook *hook = calloc(1, sizeof(struct hook));
if (hook == NULL) { if (hook == NULL) {
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
} }
hook->begin = begin;
hook->end = end;
hook->type = type; hook->type = type;
hook->callback = callback; hook->callback = callback;
hook->user_data = user_data; hook->user_data = user_data;
hook->refs = 0; hook->refs = 0;
*hh = (uc_hook)hook; *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) { if (type & UC_HOOK_INSN) {
va_list valist;
va_start(valist, end);
hook->insn = va_arg(valist, int); hook->insn = va_arg(valist, int);
hook->begin = 1; va_end(valist);
hook->end = 0;
if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) {
free(hook); free(hook);
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
} }
hook->refs++; hook->refs++;
return UC_ERR_OK; 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) { while ((type >> i) > 0) {
if ((type >> i) & 1) { if ((type >> i) & 1) {
// TODO: invalid hook error? // TODO: invalid hook error?