This commit continues the PR #111
- Allow to register handler separately for invalid memory access - Add new memory events for hooking: - UC_MEM_READ_INVALID, UC_MEM_WRITE_INVALID, UC_MEM_FETCH_INVALID - UC_HOOK_MEM_READ_PROT, UC_HOOK_MEM_WRITE_PROT, UC_HOOK_MEM_FETCH_PROT - Rename UC_ERR_EXEC_PROT to UC_ERR_FETCH_PROT - Change API uc_hook_add() so event type @type can be combined from hooking types
This commit is contained in:
parent
e479f72403
commit
90eb8f2e72
@ -48,26 +48,33 @@ const (
|
|||||||
ERR_MAP = 12
|
ERR_MAP = 12
|
||||||
ERR_WRITE_PROT = 13
|
ERR_WRITE_PROT = 13
|
||||||
ERR_READ_PROT = 14
|
ERR_READ_PROT = 14
|
||||||
ERR_EXEC_PROT = 15
|
ERR_FETCH_PROT = 15
|
||||||
ERR_ARG = 16
|
ERR_ARG = 16
|
||||||
ERR_READ_UNALIGNED = 17
|
ERR_READ_UNALIGNED = 17
|
||||||
ERR_WRITE_UNALIGNED = 18
|
ERR_WRITE_UNALIGNED = 18
|
||||||
ERR_FETCH_UNALIGNED = 19
|
ERR_FETCH_UNALIGNED = 19
|
||||||
MEM_READ = 16
|
MEM_READ = 16
|
||||||
MEM_WRITE = 17
|
MEM_WRITE = 17
|
||||||
MEM_READ_WRITE = 18
|
MEM_FETCH = 18
|
||||||
MEM_FETCH = 19
|
MEM_READ_INVALID = 19
|
||||||
MEM_WRITE_PROT = 20
|
MEM_WRITE_INVALID = 20
|
||||||
MEM_READ_PROT = 21
|
MEM_FETCH_INVALID = 21
|
||||||
MEM_EXEC_PROT = 22
|
MEM_WRITE_PROT = 22
|
||||||
HOOK_INTR = 32
|
MEM_READ_PROT = 23
|
||||||
HOOK_INSN = 33
|
MEM_FETCH_PROT = 24
|
||||||
HOOK_CODE = 34
|
HOOK_INTR = 1
|
||||||
HOOK_BLOCK = 35
|
HOOK_INSN = 2
|
||||||
HOOK_MEM_INVALID = 36
|
HOOK_CODE = 4
|
||||||
HOOK_MEM_READ = 37
|
HOOK_BLOCK = 8
|
||||||
HOOK_MEM_WRITE = 38
|
HOOK_MEM_READ_INVALID = 16
|
||||||
HOOK_MEM_READ_WRITE = 39
|
HOOK_MEM_WRITE_INVALID = 32
|
||||||
|
HOOK_MEM_FETCH_INVALID = 64
|
||||||
|
HOOK_MEM_READ_PROT = 128
|
||||||
|
HOOK_MEM_WRITE_PROT = 256
|
||||||
|
HOOK_MEM_FETCH_PROT = 512
|
||||||
|
HOOK_MEM_READ = 1024
|
||||||
|
HOOK_MEM_WRITE = 2048
|
||||||
|
HOOK_MEM_FETCH = 4096
|
||||||
|
|
||||||
PROT_NONE = 0
|
PROT_NONE = 0
|
||||||
PROT_READ = 1
|
PROT_READ = 1
|
||||||
|
@ -33,7 +33,7 @@ def hook_code(uc, address, size, user_data):
|
|||||||
|
|
||||||
# callback for tracing invalid memory access (READ or WRITE)
|
# callback for tracing invalid memory access (READ or WRITE)
|
||||||
def hook_mem_invalid(uc, access, address, size, value, user_data):
|
def hook_mem_invalid(uc, access, address, size, value, user_data):
|
||||||
if access == UC_MEM_WRITE:
|
if access == UC_MEM_WRITE_INVALID:
|
||||||
print(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x" \
|
print(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x" \
|
||||||
%(address, size, value))
|
%(address, size, value))
|
||||||
# map this memory in with 2MB in size
|
# map this memory in with 2MB in size
|
||||||
@ -231,7 +231,7 @@ def test_i386_invalid_mem_write():
|
|||||||
#mu.hook_add(UC_HOOK_CODE, hook_code)
|
#mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||||
|
|
||||||
# intercept invalid memory events
|
# intercept invalid memory events
|
||||||
mu.hook_add(UC_HOOK_MEM_INVALID, hook_mem_invalid)
|
mu.hook_add(UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# emulate machine code in infinite time
|
# emulate machine code in infinite time
|
||||||
@ -349,7 +349,7 @@ def test_x86_64():
|
|||||||
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_access)
|
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_access)
|
||||||
mu.hook_add(UC_HOOK_MEM_READ, hook_mem_access)
|
mu.hook_add(UC_HOOK_MEM_READ, hook_mem_access)
|
||||||
# actually you can also use READ_WRITE to trace all memory access
|
# actually you can also use READ_WRITE to trace all memory access
|
||||||
#mu.hook_add(UC_HOOK_MEM_READ_WRITE, hook_mem_access)
|
#mu.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, hook_mem_access)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# emulate machine code in infinite time
|
# emulate machine code in infinite time
|
||||||
|
@ -272,11 +272,13 @@ class Uc(object):
|
|||||||
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), begin, end)
|
||||||
elif htype == UC_HOOK_MEM_INVALID:
|
elif htype & UC_HOOK_MEM_READ_INVALID or htype & UC_HOOK_MEM_WRITE_INVALID or \
|
||||||
|
htype & UC_HOOK_MEM_FETCH_INVALID 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)
|
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))
|
||||||
elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE):
|
elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE):
|
||||||
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))
|
||||||
|
@ -46,7 +46,7 @@ UC_ERR_INSN_INVALID = 11
|
|||||||
UC_ERR_MAP = 12
|
UC_ERR_MAP = 12
|
||||||
UC_ERR_WRITE_PROT = 13
|
UC_ERR_WRITE_PROT = 13
|
||||||
UC_ERR_READ_PROT = 14
|
UC_ERR_READ_PROT = 14
|
||||||
UC_ERR_EXEC_PROT = 15
|
UC_ERR_FETCH_PROT = 15
|
||||||
UC_ERR_ARG = 16
|
UC_ERR_ARG = 16
|
||||||
UC_ERR_READ_UNALIGNED = 17
|
UC_ERR_READ_UNALIGNED = 17
|
||||||
UC_ERR_WRITE_UNALIGNED = 18
|
UC_ERR_WRITE_UNALIGNED = 18
|
||||||
@ -54,19 +54,25 @@ UC_ERR_FETCH_UNALIGNED = 19
|
|||||||
UC_MEM_READ = 16
|
UC_MEM_READ = 16
|
||||||
UC_MEM_WRITE = 17
|
UC_MEM_WRITE = 17
|
||||||
UC_MEM_FETCH = 18
|
UC_MEM_FETCH = 18
|
||||||
UC_MEM_WRITE_PROT = 19
|
UC_MEM_READ_INVALID = 19
|
||||||
UC_MEM_READ_PROT = 20
|
UC_MEM_WRITE_INVALID = 20
|
||||||
UC_MEM_FETCH_PROT = 21
|
UC_MEM_FETCH_INVALID = 21
|
||||||
UC_HOOK_INTR = 32
|
UC_MEM_WRITE_PROT = 22
|
||||||
UC_HOOK_INSN = 33
|
UC_MEM_READ_PROT = 23
|
||||||
UC_HOOK_CODE = 34
|
UC_MEM_FETCH_PROT = 24
|
||||||
UC_HOOK_BLOCK = 35
|
UC_HOOK_INTR = 1
|
||||||
UC_HOOK_MEM_INVALID_READ = 36
|
UC_HOOK_INSN = 2
|
||||||
UC_HOOK_MEM_INVALID_WRITE = 37
|
UC_HOOK_CODE = 4
|
||||||
UC_HOOK_MEM_INVALID_FETCH = 38
|
UC_HOOK_BLOCK = 8
|
||||||
UC_HOOK_MEM_READ = 39
|
UC_HOOK_MEM_READ_INVALID = 16
|
||||||
UC_HOOK_MEM_WRITE = 40
|
UC_HOOK_MEM_WRITE_INVALID = 32
|
||||||
UC_HOOK_MEM_FETCH = 41
|
UC_HOOK_MEM_FETCH_INVALID = 64
|
||||||
|
UC_HOOK_MEM_READ_PROT = 128
|
||||||
|
UC_HOOK_MEM_WRITE_PROT = 256
|
||||||
|
UC_HOOK_MEM_FETCH_PROT = 512
|
||||||
|
UC_HOOK_MEM_READ = 1024
|
||||||
|
UC_HOOK_MEM_WRITE = 2048
|
||||||
|
UC_HOOK_MEM_FETCH = 4096
|
||||||
|
|
||||||
UC_PROT_NONE = 0
|
UC_PROT_NONE = 0
|
||||||
UC_PROT_READ = 1
|
UC_PROT_READ = 1
|
||||||
|
30
hook.c
30
hook.c
@ -73,7 +73,7 @@ size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, vo
|
|||||||
if (begin > end)
|
if (begin > end)
|
||||||
uc->hook_write_idx = i;
|
uc->hook_write_idx = i;
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_MEM_READ_WRITE:
|
case UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE:
|
||||||
uc->hook_mem_read = true;
|
uc->hook_mem_read = true;
|
||||||
uc->hook_mem_write = true;
|
uc->hook_mem_write = true;
|
||||||
if (begin > end) {
|
if (begin > end) {
|
||||||
@ -109,8 +109,28 @@ uc_err hook_del(struct uc_struct *uc, uc_hook hh)
|
|||||||
uc->hook_write_idx = 0;
|
uc->hook_write_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hh == uc->hook_mem_idx) {
|
if (hh == uc->hook_mem_read_idx) {
|
||||||
uc->hook_mem_idx = 0;
|
uc->hook_mem_read_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh == uc->hook_mem_write_idx) {
|
||||||
|
uc->hook_mem_write_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh == uc->hook_mem_fetch_idx) {
|
||||||
|
uc->hook_mem_fetch_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh == uc->hook_mem_read_prot_idx) {
|
||||||
|
uc->hook_mem_read_prot_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh == uc->hook_mem_write_prot_idx) {
|
||||||
|
uc->hook_mem_write_prot_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh == uc->hook_mem_fetch_prot_idx) {
|
||||||
|
uc->hook_mem_fetch_prot_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hh == uc->hook_intr_idx) {
|
if (hh == uc->hook_intr_idx) {
|
||||||
@ -176,13 +196,13 @@ static struct hook_struct *_hook_find(struct uc_struct *uc, int type, uint64_t a
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_MEM_READ:
|
case UC_HOOK_MEM_READ:
|
||||||
if (uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ || uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ_WRITE) {
|
if (uc->hook_callbacks[i].hook_type & UC_HOOK_MEM_READ) {
|
||||||
if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end)
|
if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end)
|
||||||
return &uc->hook_callbacks[i];
|
return &uc->hook_callbacks[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_MEM_WRITE:
|
case UC_HOOK_MEM_WRITE:
|
||||||
if (uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_WRITE || uc->hook_callbacks[i].hook_type == UC_HOOK_MEM_READ_WRITE) {
|
if (uc->hook_callbacks[i].hook_type & UC_HOOK_MEM_WRITE) {
|
||||||
if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end)
|
if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end)
|
||||||
return &uc->hook_callbacks[i];
|
return &uc->hook_callbacks[i];
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,13 @@ struct uc_struct {
|
|||||||
bool hook_block, hook_insn, hook_mem_read, hook_mem_write;
|
bool hook_block, hook_insn, hook_mem_read, hook_mem_write;
|
||||||
uint64_t block_addr; // save the last block address we hooked
|
uint64_t block_addr; // save the last block address we hooked
|
||||||
// indexes to event callbacks
|
// indexes to event callbacks
|
||||||
int hook_mem_idx; // for handling invalid memory access
|
int hook_mem_read_idx; // for handling invalid memory read access on unmapped memory
|
||||||
|
int hook_mem_write_idx; // for handling invalid memory write access on unmapped memory
|
||||||
|
int hook_mem_fetch_idx; // for handling invalid memory fetch access on unmapped memory
|
||||||
|
int hook_mem_read_prot_idx; // for handling invalid memory read access on read-protected memory
|
||||||
|
int hook_mem_write_prot_idx; // for handling invalid memory write access on write-protected memory
|
||||||
|
int hook_mem_fetch_prot_idx; // for handling invalid memory fetch access on non-executable memory
|
||||||
|
|
||||||
int hook_intr_idx; // for handling interrupt
|
int hook_intr_idx; // for handling interrupt
|
||||||
int hook_out_idx; // for handling OUT instruction (X86)
|
int hook_out_idx; // for handling OUT instruction (X86)
|
||||||
int hook_in_idx; // for handling IN instruction (X86)
|
int hook_in_idx; // for handling IN instruction (X86)
|
||||||
|
@ -120,7 +120,7 @@ typedef enum uc_err {
|
|||||||
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
||||||
UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
|
UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
|
||||||
UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
|
UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
|
||||||
UC_ERR_EXEC_PROT, // Quit emulation due to UC_MEM_EXEC_PROT violation: uc_emu_start()
|
UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start()
|
||||||
UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API)
|
UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API)
|
||||||
UC_ERR_READ_UNALIGNED, // Unaligned read
|
UC_ERR_READ_UNALIGNED, // Unaligned read
|
||||||
UC_ERR_WRITE_UNALIGNED, // Unaligned write
|
UC_ERR_WRITE_UNALIGNED, // Unaligned write
|
||||||
@ -153,9 +153,12 @@ typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_
|
|||||||
|
|
||||||
// All type of memory accesses for UC_HOOK_MEM_*
|
// All type of memory accesses for UC_HOOK_MEM_*
|
||||||
typedef enum uc_mem_type {
|
typedef enum uc_mem_type {
|
||||||
UC_MEM_READ = 16, // Unmapped memory is read from
|
UC_MEM_READ = 16, // Memory is read from
|
||||||
UC_MEM_WRITE, // Unmapped memory is written to
|
UC_MEM_WRITE, // Memory is written to
|
||||||
UC_MEM_FETCH, // Unmapped memory is fetched
|
UC_MEM_FETCH, // Memory is fetched
|
||||||
|
UC_MEM_READ_INVALID, // Unmapped memory is read from
|
||||||
|
UC_MEM_WRITE_INVALID, // Unmapped memory is written to
|
||||||
|
UC_MEM_FETCH_INVALID, // Unmapped memory is fetched
|
||||||
UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory
|
UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory
|
||||||
UC_MEM_READ_PROT, // Read from read protected, but mapped, memory
|
UC_MEM_READ_PROT, // Read from read protected, but mapped, memory
|
||||||
UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory
|
UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory
|
||||||
@ -163,16 +166,19 @@ typedef enum uc_mem_type {
|
|||||||
|
|
||||||
// All type of hooks for uc_hook_add() API.
|
// All type of hooks for uc_hook_add() API.
|
||||||
typedef enum uc_hook_type {
|
typedef enum uc_hook_type {
|
||||||
UC_HOOK_INTR = 32, // Hook all interrupt events
|
UC_HOOK_INTR = 1 << 0, // Hook all interrupt events
|
||||||
UC_HOOK_INSN, // Hook a particular instruction
|
UC_HOOK_INSN = 1 << 1, // Hook a particular instruction
|
||||||
UC_HOOK_CODE, // Hook a range of code
|
UC_HOOK_CODE = 1 << 2, // Hook a range of code
|
||||||
UC_HOOK_BLOCK, // Hook basic blocks
|
UC_HOOK_BLOCK = 1 << 3, // Hook basic blocks
|
||||||
UC_HOOK_MEM_READ_INVALID, // Hook for invalid memory read events
|
UC_HOOK_MEM_READ_INVALID = 1 << 4, // Hook for invalid memory read events
|
||||||
UC_HOOK_MEM_WRITE_INVALID, // Hook for invalid memory write events
|
UC_HOOK_MEM_WRITE_INVALID = 1 << 5, // Hook for invalid memory write events
|
||||||
UC_HOOK_MEM_FETCH_INVALID, // Hook for invalid memory fetch for execution events
|
UC_HOOK_MEM_FETCH_INVALID = 1 << 6, // Hook for invalid memory fetch for execution events
|
||||||
UC_HOOK_MEM_READ, // Hook all memory read events.
|
UC_HOOK_MEM_READ_PROT = 1 << 7, // Hook for memory read on read-protected memory
|
||||||
UC_HOOK_MEM_WRITE, // Hook all memory write events.
|
UC_HOOK_MEM_WRITE_PROT = 1 << 8, // Hook for memory write on write-protected memory
|
||||||
UC_HOOK_MEM_FETCH, // Hook all memory fetch for execution events
|
UC_HOOK_MEM_FETCH_PROT = 1 << 9, // Hook for memory fetch on non-executable memory
|
||||||
|
UC_HOOK_MEM_READ = 1 << 10, // Hook memory read events.
|
||||||
|
UC_HOOK_MEM_WRITE = 1 << 11, // Hook memory write events.
|
||||||
|
UC_HOOK_MEM_FETCH = 1 << 12, // Hook memory fetch for execution events
|
||||||
} uc_hook_type;
|
} uc_hook_type;
|
||||||
|
|
||||||
// Callback function for hooking memory (UC_HOOK_MEM_*)
|
// Callback function for hooking memory (UC_HOOK_MEM_*)
|
||||||
@ -381,7 +387,7 @@ uc_err uc_emu_stop(uc_engine *uc);
|
|||||||
for detailed error).
|
for detailed error).
|
||||||
*/
|
*/
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, uc_hook_type type, void *callback, void *user_data, ...);
|
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Unregister (remove) a hook callback.
|
Unregister (remove) a hook callback.
|
||||||
|
@ -300,7 +300,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
|||||||
(addr & TARGET_PAGE_MASK))) {
|
(addr & TARGET_PAGE_MASK))) {
|
||||||
cpu_ldub_code(env1, addr);
|
cpu_ldub_code(env1, addr);
|
||||||
//check for NX related error from softmmu
|
//check for NX related error from softmmu
|
||||||
if (env1->invalid_error == UC_ERR_EXEC_PROT) {
|
if (env1->invalid_error == UC_ERR_FETCH_PROT) {
|
||||||
env1->invalid_error = UC_ERR_CODE_INVALID;
|
env1->invalid_error = UC_ERR_CODE_INVALID;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
|
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
|
||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
int mem_access, error_code;
|
int error_code;
|
||||||
|
|
||||||
struct uc_struct *uc = env->uc;
|
struct uc_struct *uc = env->uc;
|
||||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
@ -185,15 +185,16 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
// memory can be unmapped while reading or fetching
|
// memory can be unmapped while reading or fetching
|
||||||
if (mr == NULL) {
|
if (mr == NULL) {
|
||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
mem_access = UC_MEM_FETCH;
|
|
||||||
error_code = UC_ERR_FETCH_INVALID;
|
error_code = UC_ERR_FETCH_INVALID;
|
||||||
|
if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)(
|
||||||
|
uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0,
|
||||||
|
uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) {
|
||||||
#else
|
#else
|
||||||
mem_access = UC_MEM_READ;
|
|
||||||
error_code = UC_ERR_READ_INVALID;
|
error_code = UC_ERR_READ_INVALID;
|
||||||
|
if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)(
|
||||||
|
uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0,
|
||||||
|
uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) {
|
||||||
#endif
|
#endif
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
|
||||||
uc, mem_access, addr, DATA_SIZE, 0,
|
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
||||||
} else {
|
} else {
|
||||||
@ -208,13 +209,13 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
// Unicorn: callback on fetch from NX
|
// Unicorn: callback on fetch from NX
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
|
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)(
|
||||||
uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_EXEC_PROT;
|
env->invalid_error = UC_ERR_FETCH_PROT;
|
||||||
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return 0;
|
return 0;
|
||||||
@ -233,9 +234,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
|
|
||||||
// Unicorn: callback on non-readable memory
|
// Unicorn: callback on non-readable memory
|
||||||
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)(
|
||||||
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -367,7 +368,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
|
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
|
||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
int mem_access, error_code;
|
int error_code;
|
||||||
|
|
||||||
struct uc_struct *uc = env->uc;
|
struct uc_struct *uc = env->uc;
|
||||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
@ -375,15 +376,16 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
// memory can be unmapped while reading or fetching
|
// memory can be unmapped while reading or fetching
|
||||||
if (mr == NULL) {
|
if (mr == NULL) {
|
||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
mem_access = UC_MEM_FETCH;
|
|
||||||
error_code = UC_ERR_FETCH_INVALID;
|
error_code = UC_ERR_FETCH_INVALID;
|
||||||
|
if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)(
|
||||||
|
uc, UC_MEM_FETCH_INVALID, addr, DATA_SIZE, 0,
|
||||||
|
uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) {
|
||||||
#else
|
#else
|
||||||
mem_access = UC_MEM_READ;
|
|
||||||
error_code = UC_ERR_READ_INVALID;
|
error_code = UC_ERR_READ_INVALID;
|
||||||
|
if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)(
|
||||||
|
uc, UC_MEM_READ_INVALID, addr, DATA_SIZE, 0,
|
||||||
|
uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) {
|
||||||
#endif
|
#endif
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
|
||||||
uc, mem_access, addr, DATA_SIZE, 0,
|
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
||||||
} else {
|
} else {
|
||||||
@ -398,13 +400,13 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
#if defined(SOFTMMU_CODE_ACCESS)
|
#if defined(SOFTMMU_CODE_ACCESS)
|
||||||
// Unicorn: callback on fetch from NX
|
// Unicorn: callback on fetch from NX
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
|
if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)(
|
||||||
uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_EXEC_PROT;
|
env->invalid_error = UC_ERR_FETCH_PROT;
|
||||||
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return 0;
|
return 0;
|
||||||
@ -423,9 +425,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
|
|
||||||
// Unicorn: callback on non-readable memory
|
// Unicorn: callback on non-readable memory
|
||||||
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)(
|
||||||
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
@ -608,10 +610,10 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (uc->hook_mem_idx && mr == NULL) {
|
if (uc->hook_mem_write_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)(
|
||||||
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) {
|
||||||
// save error & quit
|
// save error & quit
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||||
@ -620,14 +622,15 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
|
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on non-writable memory
|
// Unicorn: callback on non-writable memory
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
|
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)(
|
||||||
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -754,10 +757,10 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (uc->hook_mem_idx && mr == NULL) {
|
if (uc->hook_mem_write_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)(
|
||||||
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE_INVALID, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) {
|
||||||
// save error & quit
|
// save error & quit
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_WRITE_INVALID;
|
env->invalid_error = UC_ERR_WRITE_INVALID;
|
||||||
@ -766,14 +769,15 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
|
mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on non-writable memory
|
// Unicorn: callback on non-writable memory
|
||||||
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
|
if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable
|
||||||
if (uc->hook_mem_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)(
|
||||||
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val,
|
||||||
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) {
|
||||||
env->invalid_error = UC_ERR_OK;
|
env->invalid_error = UC_ERR_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -79,13 +79,13 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
|||||||
default:
|
default:
|
||||||
printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr);
|
printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_READ:
|
case UC_MEM_READ_INVALID:
|
||||||
printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size);
|
printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE:
|
case UC_MEM_WRITE_INVALID:
|
||||||
printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_EXEC_PROT:
|
case UC_MEM_FETCH_PROT:
|
||||||
printf("not ok - Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
|
printf("not ok - Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE_PROT:
|
case UC_MEM_WRITE_PROT:
|
||||||
@ -147,7 +147,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, (uint64_t)1, (uint64_t)0) != UC_ERR_OK ||
|
||||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
uc_hook_add(uc, &trace1,
|
||||||
|
UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_FETCH_INVALID | UC_HOOK_MEM_FETCH_PROT | UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_READ_PROT,
|
||||||
|
hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok - Failed to install hooks\n");
|
printf("not ok - Failed to install hooks\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -226,7 +228,9 @@ 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, (uint64_t)1, (uint64_t)0) != UC_ERR_OK ||
|
||||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
uc_hook_add(uc, &trace1,
|
||||||
|
UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_FETCH_INVALID | UC_HOOK_MEM_FETCH_PROT | UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_READ_PROT,
|
||||||
|
hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok - Failed to install hooks\n");
|
printf("not ok - Failed to install hooks\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -302,7 +306,9 @@ 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, (uint64_t)1, (uint64_t)0) != UC_ERR_OK ||
|
||||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
uc_hook_add(uc, &trace1,
|
||||||
|
UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_FETCH_INVALID | UC_HOOK_MEM_FETCH_PROT | UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_READ_PROT,
|
||||||
|
hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok - Failed to install hooks\n");
|
printf("not ok - Failed to install hooks\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
|||||||
default:
|
default:
|
||||||
// return false to indicate we want to stop emulation
|
// return false to indicate we want to stop emulation
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE:
|
case UC_MEM_WRITE_INVALID:
|
||||||
printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
||||||
address, size, value);
|
address, size, value);
|
||||||
// map this memory in with 2MB in size
|
// map this memory in with 2MB in size
|
||||||
@ -421,7 +421,7 @@ static void test_i386_invalid_mem_write(void)
|
|||||||
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, (uint64_t)1, (uint64_t)0);
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
uc_hook_add(uc, &trace3, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_INVALID | UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid, NULL);
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
CFLAGS += -I../include
|
CFLAGS += -I../include
|
||||||
LDFLAGS += ../libunicorn.a $(shell pkg-config --libs glib-2.0) -lpthread -lm
|
LDFLAGS += ../../libunicorn.a $(shell pkg-config --libs glib-2.0) -lpthread -lm
|
||||||
|
|
||||||
TESTS = map_crash map_write
|
TESTS = map_crash map_write
|
||||||
TESTS += sigill sigill2
|
TESTS += sigill sigill2
|
||||||
|
@ -116,9 +116,9 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
|||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
default:
|
default:
|
||||||
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_EXEC_PROT:
|
case UC_MEM_FETCH_PROT:
|
||||||
printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
|
printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
|
||||||
|
|
||||||
//make page executable
|
//make page executable
|
||||||
@ -221,11 +221,11 @@ int main(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++);
|
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
|
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emulate machine code until told to stop by hook_code
|
// emulate machine code until told to stop by hook_code
|
||||||
|
@ -138,7 +138,7 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
|||||||
uint32_t testval;
|
uint32_t testval;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
default:
|
default:
|
||||||
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE_PROT:
|
case UC_MEM_WRITE_PROT:
|
||||||
printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
||||||
@ -229,11 +229,11 @@ int main(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++);
|
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||||
return 7;
|
return 7;
|
||||||
} else {
|
} else {
|
||||||
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
|
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emulate machine code until told to stop by hook_code
|
// emulate machine code until told to stop by hook_code
|
||||||
|
@ -133,7 +133,7 @@ static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
|||||||
uint32_t testval;
|
uint32_t testval;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
default:
|
default:
|
||||||
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||||
return false;
|
return false;
|
||||||
case UC_MEM_WRITE:
|
case UC_MEM_WRITE:
|
||||||
printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
||||||
@ -224,11 +224,11 @@ int main(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
|
||||||
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++);
|
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||||
return 7;
|
return 7;
|
||||||
} else {
|
} else {
|
||||||
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
|
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emulate machine code until told to stop by hook_code
|
// emulate machine code until told to stop by hook_code
|
||||||
|
@ -86,7 +86,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
uc_hook_add(uc, &trace1, UC_MEM_READ_PROT, hook_mem_invalid, NULL);
|
||||||
|
|
||||||
// emulate machine code in infinite time
|
// emulate machine code in infinite time
|
||||||
printf("BEGIN execution\n");
|
printf("BEGIN execution\n");
|
||||||
|
@ -24,7 +24,7 @@ class RegWriteSignExt(regress.RegressTest):
|
|||||||
# jmp ebx
|
# jmp ebx
|
||||||
mu.mem_write(0x10000000, b'\xff\xe3')
|
mu.mem_write(0x10000000, b'\xff\xe3')
|
||||||
|
|
||||||
mu.hook_add(unicorn.UC_HOOK_MEM_INVALID, hook_mem_invalid)
|
mu.hook_add(unicorn.UC_HOOK_MEM_FETCH_INVALID | unicorn.UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid)
|
||||||
mu.emu_start(0x10000000, 0x10000000 + 2, count=1)
|
mu.emu_start(0x10000000, 0x10000000 + 2, count=1)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
13
tests/regress/regress.sh
Executable file
13
tests/regress/regress.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
|
||||||
|
./map_crash map_write
|
||||||
|
./sigill sigill2
|
||||||
|
./block_test
|
||||||
|
./ro_mem_test nr_mem_test
|
||||||
|
./timeout_segfault
|
||||||
|
./rep_movsb
|
||||||
|
./mem_unmap
|
||||||
|
./mem_protect
|
||||||
|
./mem_exec
|
||||||
|
|
@ -142,7 +142,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
//uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff);
|
||||||
|
|
||||||
// intercept invalid memory events
|
// intercept invalid memory events
|
||||||
uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL);
|
uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_INVALID | UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL);
|
||||||
|
|
||||||
// emulate machine code in infinite time
|
// emulate machine code in infinite time
|
||||||
printf("BEGIN execution - 1\n");
|
printf("BEGIN execution - 1\n");
|
||||||
|
@ -11,7 +11,7 @@ all: ${ALL_TESTS}
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm ${ALL_TESTS}
|
rm -rf ${ALL_TESTS}
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: export LD_LIBRARY_PATH=../../
|
test: export LD_LIBRARY_PATH=../../
|
||||||
|
47
uc.c
47
uc.c
@ -87,8 +87,8 @@ const char *uc_strerror(uc_err code)
|
|||||||
return "Write to write-protected memory (UC_ERR_WRITE_PROT)";
|
return "Write to write-protected memory (UC_ERR_WRITE_PROT)";
|
||||||
case UC_ERR_READ_PROT:
|
case UC_ERR_READ_PROT:
|
||||||
return "Read from non-readable memory (UC_ERR_READ_PROT)";
|
return "Read from non-readable memory (UC_ERR_READ_PROT)";
|
||||||
case UC_ERR_EXEC_PROT:
|
case UC_ERR_FETCH_PROT:
|
||||||
return "Fetch from non-executable memory (UC_ERR_EXEC_PROT)";
|
return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)";
|
||||||
case UC_ERR_ARG:
|
case UC_ERR_ARG:
|
||||||
return "Invalid argumet (UC_ERR_ARG)";
|
return "Invalid argumet (UC_ERR_ARG)";
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
static uc_err _hook_mem_invalid(struct uc_struct* uc, int type, uc_cb_eventmem_t callback,
|
||||||
void *user_data, uc_hook *evh)
|
void *user_data, uc_hook *evh)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -842,7 +842,18 @@ static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
|||||||
uc->hook_callbacks[i].callback = callback;
|
uc->hook_callbacks[i].callback = callback;
|
||||||
uc->hook_callbacks[i].user_data = user_data;
|
uc->hook_callbacks[i].user_data = user_data;
|
||||||
*evh = i;
|
*evh = i;
|
||||||
uc->hook_mem_idx = i;
|
if (type & UC_HOOK_MEM_READ_INVALID)
|
||||||
|
uc->hook_mem_read_idx = i;
|
||||||
|
if (type & UC_HOOK_MEM_READ_PROT)
|
||||||
|
uc->hook_mem_read_prot_idx = i;
|
||||||
|
if (type & UC_HOOK_MEM_WRITE_INVALID)
|
||||||
|
uc->hook_mem_write_idx = i;
|
||||||
|
if (type & UC_HOOK_MEM_WRITE_PROT)
|
||||||
|
uc->hook_mem_write_prot_idx = i;
|
||||||
|
if (type & UC_HOOK_MEM_FETCH_INVALID)
|
||||||
|
uc->hook_mem_fetch_idx = i;
|
||||||
|
if (type & UC_HOOK_MEM_FETCH_PROT)
|
||||||
|
uc->hook_mem_fetch_prot_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
@ -920,7 +931,7 @@ static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, uc_hook_type type, void *callback, void *user_data, ...)
|
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...)
|
||||||
{
|
{
|
||||||
va_list valist;
|
va_list valist;
|
||||||
int ret = UC_ERR_OK;
|
int ret = UC_ERR_OK;
|
||||||
@ -929,9 +940,26 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, uc_hook_type type, void *callback
|
|||||||
|
|
||||||
va_start(valist, user_data);
|
va_start(valist, user_data);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_READ_INVALID)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_INVALID, callback, user_data, hh);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_WRITE_INVALID)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_INVALID, callback, user_data, hh);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_FETCH_INVALID)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_INVALID, callback, user_data, hh);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_READ_PROT)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_PROT, callback, user_data, hh);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_WRITE_PROT)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_PROT, callback, user_data, hh);
|
||||||
|
|
||||||
|
if (type & UC_HOOK_MEM_FETCH_PROT)
|
||||||
|
ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_PROT, callback, user_data, hh);
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
default:
|
default:
|
||||||
ret = UC_ERR_HOOK;
|
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_INTR:
|
case UC_HOOK_INTR:
|
||||||
ret = _hook_intr(uc, callback, user_data, hh);
|
ret = _hook_intr(uc, callback, user_data, hh);
|
||||||
@ -950,9 +978,6 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, uc_hook_type type, void *callback
|
|||||||
end = va_arg(valist, uint64_t);
|
end = va_arg(valist, uint64_t);
|
||||||
ret = _hook_code(uc, UC_HOOK_BLOCK, begin, end, callback, user_data, hh);
|
ret = _hook_code(uc, UC_HOOK_BLOCK, begin, end, callback, user_data, hh);
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_MEM_INVALID:
|
|
||||||
ret = _hook_mem_invalid(uc, callback, user_data, hh);
|
|
||||||
break;
|
|
||||||
case UC_HOOK_MEM_READ:
|
case UC_HOOK_MEM_READ:
|
||||||
begin = va_arg(valist, uint64_t);
|
begin = va_arg(valist, uint64_t);
|
||||||
end = va_arg(valist, uint64_t);
|
end = va_arg(valist, uint64_t);
|
||||||
@ -963,10 +988,10 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, uc_hook_type type, void *callback
|
|||||||
end = va_arg(valist, uint64_t);
|
end = va_arg(valist, uint64_t);
|
||||||
ret = _hook_mem_access(uc, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh);
|
ret = _hook_mem_access(uc, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh);
|
||||||
break;
|
break;
|
||||||
case UC_HOOK_MEM_READ_WRITE:
|
case UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE:
|
||||||
begin = va_arg(valist, uint64_t);
|
begin = va_arg(valist, uint64_t);
|
||||||
end = va_arg(valist, uint64_t);
|
end = va_arg(valist, uint64_t);
|
||||||
ret = _hook_mem_access(uc, UC_HOOK_MEM_READ_WRITE, begin, end, callback, user_data, hh);
|
ret = _hook_mem_access(uc, UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user