diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index ef9004e6..0152df03 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -63,6 +63,8 @@ module Common = let UC_ERR_FETCH_UNALIGNED = 18 let UC_ERR_HOOK_EXIST = 19 let UC_ERR_RESOURCE = 20 + let UC_ERR_OPT_INVALID = 21 + let UC_OPT_WINDOWS_TIB = 1 let UC_MEM_READ = 16 let UC_MEM_WRITE = 17 let UC_MEM_FETCH = 18 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 01b62fca..80accb8a 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -58,6 +58,8 @@ const ( ERR_FETCH_UNALIGNED = 18 ERR_HOOK_EXIST = 19 ERR_RESOURCE = 20 + ERR_OPT_INVALID = 21 + OPT_WINDOWS_TIB = 1 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 033267ae..158ea08e 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -60,6 +60,8 @@ public interface UnicornConst { public static final int UC_ERR_FETCH_UNALIGNED = 18; public static final int UC_ERR_HOOK_EXIST = 19; public static final int UC_ERR_RESOURCE = 20; + public static final int UC_ERR_OPT_INVALID = 21; + public static final int UC_OPT_WINDOWS_TIB = 1; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index dc1a2ac9..e52bdf0b 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -110,6 +110,7 @@ _setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctype _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_query", ucerr, uc_engine, ctypes.c_uint32, ctypes.POINTER(ctypes.c_size_t)) +_setup_prototype(_ks, "uc_option", ucerr, uc_engine, c_int, c_void_p) # uc_hook_add is special due to variable number of arguments _uc.uc_hook_add = getattr(_uc, "uc_hook_add") @@ -322,6 +323,19 @@ class Uc(object): raise UcError(status) return result.value + # return Windows TIB + @property + def windows_tib(self): + return self._windows_tib + + # Windows TIB setter + @windows_tib.setter + def windows_tib(self, base_addr): + status = _uc.uc_option(self._uch, UC_OPT_WINDOWS_TIB, base_addr) + if status != UC_ERR_OK: + raise UcError(status) + # save this address + self._windows_tib = base_addr def _hookcode_cb(self, handle, address, size, user_data): # call user's callback with self object diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 89ccd919..2580feec 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -56,6 +56,8 @@ UC_ERR_WRITE_UNALIGNED = 17 UC_ERR_FETCH_UNALIGNED = 18 UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 +UC_ERR_OPT_INVALID = 21 +UC_OPT_WINDOWS_TIB = 1 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/include/uc_priv.h b/include/uc_priv.h index e36a8c84..d091c9ca 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -68,6 +68,8 @@ typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long); typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr); +typedef uc_err (*uc_args_uc_int_size_t)(struct uc_struct*, uc_opt_type, size_t); + typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms); typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms, void *ptr); @@ -172,6 +174,8 @@ struct uc_struct { uc_mem_unmap_t memory_unmap; uc_readonly_mem_t readonly_mem; uc_mem_redirect_t mem_redirect; + uc_args_uc_int_size_t option; + // list of cpu void* cpu; diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 65d6aa53..8b76781a 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -138,8 +138,14 @@ typedef enum uc_err { UC_ERR_FETCH_UNALIGNED, // Unaligned fetch UC_ERR_HOOK_EXIST, // hook for this event already existed UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() + UC_ERR_OPT_INVALID, // Invalid option type: uc_option() } uc_err; +// Runtime option for the Unicorn engine +typedef enum uc_opt_type { + UC_OPT_WINDOWS_TIB = 1, // Setup Windows Thread Information Block +} uc_opt_type; + /* Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) @@ -588,6 +594,20 @@ uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t per UNICORN_EXPORT uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count); +/* + Set option for Unicorn engine at runtime + + @uc: handle returned by uc_open() + @type: type of option to be set + @value: option value corresponding with @type + + @return: UC_ERR_OK on success, or other value on failure. + Refer to uc_err enum for detailed error. +*/ +UNICORN_EXPORT +uc_err uc_option(uc_engine *uc, uc_opt_type type, size_t value); + + #ifdef __cplusplus } #endif diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index 302f04c9..6f5435d2 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -1121,6 +1121,19 @@ static bool x86_stop_interrupt(int intno) } } +static uc_err x86_option(struct uc_struct *uc, uc_opt_type type, size_t value) +{ + CPUState *mycpu = first_cpu; + + if (type != UC_OPT_WINDOWS_TIB) + return UC_ERR_OPT_INVALID; + + // TODO: setup limit? + X86_CPU(uc, mycpu)->env.segs[R_FS].base = value; + + return UC_ERR_OK; +} + void pc_machine_init(struct uc_struct *uc); __attribute__ ((visibility ("default"))) @@ -1138,5 +1151,8 @@ void x86_uc_init(struct uc_struct* uc) uc->release = x86_release; uc->set_pc = x86_set_pc; uc->stop_interrupt = x86_stop_interrupt; + uc->option = x86_option; uc_common_init(uc); } + + diff --git a/uc.c b/uc.c index ce9f121d..c1b2f454 100644 --- a/uc.c +++ b/uc.c @@ -1108,3 +1108,12 @@ uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) return UC_ERR_OK; } + +UNICORN_EXPORT +uc_err uc_option(uc_engine *uc, uc_opt_type type, size_t value) +{ + if (uc->option) + return uc->option(uc, type, value); + else + return UC_ERR_OPT_INVALID; +}