From da46071c7d5528deb6832d0d82e6237688ebd4ec Mon Sep 17 00:00:00 2001 From: Jonathon Reinhart Date: Thu, 3 Sep 2015 22:15:49 -0400 Subject: [PATCH] bring new code and samples up-to-date with API changes --- include/unicorn/unicorn.h | 4 +-- qemu/softmmu_template.h | 4 +-- samples/mem_exec.c | 57 ++++++++++++++++++------------------- samples/mem_protect.c | 59 ++++++++++++++++++++------------------- samples/mem_unmap.c | 59 ++++++++++++++++++++------------------- uc.c | 42 ++++++++++------------------ 6 files changed, 108 insertions(+), 117 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index ad373ab..f3b4c1f 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -433,7 +433,7 @@ uc_err uc_mem_map(ucengine *uc, uint64_t address, size_t size, uint32_t perms); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size); +uc_err uc_mem_unmap(ucengine *uc, uint64_t address, size_t size); /* Set memory permissions for emulation memory. @@ -452,7 +452,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms); +uc_err uc_mem_protect(ucengine *uc, uint64_t address, size_t size, uint32_t perms); #ifdef __cplusplus } diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index ade85c8..3c85168 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -185,7 +185,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on fetch from NX 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)( - (uch)uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0, + uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_idx].user_data)) { env->invalid_error = UC_ERR_OK; } else { @@ -343,7 +343,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on fetch from NX 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)( - (uch)uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0, + uc, UC_MEM_EXEC_PROT, addr, DATA_SIZE, 0, uc->hook_callbacks[uc->hook_mem_idx].user_data)) { env->invalid_error = UC_ERR_OK; } else { diff --git a/samples/mem_exec.c b/samples/mem_exec.c index 19153b4..075a5a4 100644 --- a/samples/mem_exec.c +++ b/samples/mem_exec.c @@ -78,11 +78,11 @@ static int log_num = 1; #define CODE_SIZE 0x1000 // callback for tracing instruction -static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) +static void hook_code(ucengine *uc, uint64_t addr, uint32_t size, void *user_data) { uint8_t opcode; - if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } @@ -90,7 +90,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) switch (opcode) { case 0xf4: //hlt printf("# Handling HLT\n"); - if (uc_emu_stop(handle) != UC_ERR_OK) { + if (uc_emu_stop(uc) != UC_ERR_OK) { printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); _exit(-1); } else { @@ -104,14 +104,14 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) } // callback for tracing memory access (READ or WRITE) -static void hook_mem_write(uch handle, uc_mem_type type, +static void hook_mem_write(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); } // callback for tracing invalid memory access (READ or WRITE) -static bool hook_mem_invalid(uch handle, uc_mem_type type, +static bool hook_mem_invalid(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { switch(type) { @@ -122,7 +122,7 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr); //make page executable - if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) { + if (uc_mem_protect(uc, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) { printf("not ok %d - uc_mem_protect fail for address: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("ok %d - uc_mem_protect success at 0x%" PRIx64 "\n", log_num++, addr); @@ -131,7 +131,7 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, 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); - if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { + if (uc_mem_protect(uc, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("ok %d - uc_mem_protect success\n", log_num++); @@ -142,7 +142,8 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, int main(int argc, char **argv, char **envp) { - uch handle, trace1, trace2; + ucengine *uc; + uc_hook_h trace1, trace2; uc_err err; uint32_t esp, eip; int32_t buf1[1024], buf2[1024], readbuf[1024]; @@ -158,7 +159,7 @@ int main(int argc, char **argv, char **envp) printf("# Memory protect test\n"); // Initialize emulator in X86-32bit mode - err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err) { printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); return 1; @@ -166,15 +167,15 @@ int main(int argc, char **argv, char **envp) printf("ok %d - uc_open() success\n", log_num++); } - uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC); - uc_mem_map(handle, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE); - uc_mem_map(handle, 0x300000, 0x2000, UC_PROT_READ); - uc_mem_map(handle, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC); + uc_mem_map(uc, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x300000, 0x2000, UC_PROT_READ); + uc_mem_map(uc, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); esp = 0xf00000 + 0x1000; // Setup stack pointer - if (uc_reg_write(handle, UC_X86_REG_ESP, &esp)) { + if (uc_reg_write(uc, UC_X86_REG_ESP, &esp)) { printf("not ok %d - Failed to set esp. quit!\n", log_num++); return 2; } else { @@ -182,14 +183,14 @@ int main(int argc, char **argv, char **envp) } // fill in sections that shouldn't get touched - if (uc_mem_write(handle, 0x1ff000, (uint8_t*)buf1, 4096)) { + if (uc_mem_write(uc, 0x1ff000, (uint8_t*)buf1, 4096)) { printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); return 3; } else { printf("ok %d - Random buffer 1 written to memory\n", log_num++); } - if (uc_mem_write(handle, 0x301000, (uint8_t*)buf2, 4096)) { + if (uc_mem_write(uc, 0x301000, (uint8_t*)buf2, 4096)) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); return 4; } else { @@ -197,31 +198,31 @@ int main(int argc, char **argv, char **envp) } // write machine code to be emulated to memory - if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) { + if (uc_mem_write(uc, 0x100000, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 5; } else { printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++); return 6; } else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++); } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++); return 7; } else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); } // intercept invalid memory events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++); return 8; } else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); @@ -229,7 +230,7 @@ int main(int argc, char **argv, char **envp) // emulate machine code until told to stop by hook_code printf("# BEGIN execution\n"); - err = uc_emu_start(handle, 0x100000, 0x400000, 0, 0); + err = uc_emu_start(uc, 0x100000, 0x400000, 0, 0); if (err != UC_ERR_OK) { printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); return 9; @@ -239,7 +240,7 @@ int main(int argc, char **argv, char **envp) printf("# END execution\n"); // get ending EIP - if (uc_reg_read(handle, UC_X86_REG_EIP, &eip)) { + if (uc_reg_read(uc, UC_X86_REG_EIP, &eip)) { printf("not ok %d - Failed to read eip.\n", log_num++); } else { printf("ok %d - Ending EIP 0x%x\n", log_num++, eip); @@ -247,7 +248,7 @@ int main(int argc, char **argv, char **envp) //make sure that random blocks didn't get nuked // fill in sections that shouldn't get touched - if (uc_mem_read(handle, 0x1ff000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x1ff000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); } else { printf("ok %d - Random buffer 1 read from memory\n", log_num++); @@ -258,7 +259,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_mem_read(handle, 0x301000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x301000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); } else { printf("ok %d - Random buffer 2 read from memory\n", log_num++); @@ -269,7 +270,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_close(&handle) == UC_ERR_OK) { + if (uc_close(uc) == UC_ERR_OK) { printf("ok %d - uc_close complete\n", log_num++); } else { printf("not ok %d - uc_close complete\n", log_num++); diff --git a/samples/mem_protect.c b/samples/mem_protect.c index d9644d5..f147659 100644 --- a/samples/mem_protect.c +++ b/samples/mem_protect.c @@ -77,18 +77,18 @@ static int log_num = 1; #define CODE_SIZE 0x1000 // callback for tracing instruction -static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) +static void hook_code(ucengine *uc, uint64_t addr, uint32_t size, void *user_data) { uint8_t opcode; uint32_t testval; - if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr); switch (opcode) { case 0x90: //nop printf("# Handling NOP\n"); - if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { + if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); } else { printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); @@ -102,7 +102,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) printf("# Received: 0x%x\n", testval); } } - if (uc_mem_protect(handle, 0x200000 + test_num * 0x100000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { + if (uc_mem_protect(uc, 0x200000 + test_num * 0x100000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { printf("not ok %d - uc_mem_protect fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); } else { printf("ok %d - uc_mem_protect success\n", log_num++); @@ -111,7 +111,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) break; case 0xf4: //hlt printf("# Handling HLT\n"); - if (uc_emu_stop(handle) != UC_ERR_OK) { + if (uc_emu_stop(uc) != UC_ERR_OK) { printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); _exit(-1); } else { @@ -125,14 +125,14 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) } // callback for tracing memory access (READ or WRITE) -static void hook_mem_write(uch handle, uc_mem_type type, +static void hook_mem_write(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); } // callback for tracing invalid memory access (READ or WRITE) -static bool hook_mem_invalid(uch handle, uc_mem_type type, +static bool hook_mem_invalid(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { uint32_t testval; @@ -143,13 +143,13 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, 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); - if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("ok %d - uc_mem_read success after mem_protect at test %d\n", log_num++, test_num - 1); } - if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { + if (uc_mem_protect(uc, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("ok %d - uc_mem_protect success\n", log_num++); @@ -160,7 +160,8 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, int main(int argc, char **argv, char **envp) { - uch handle, trace1, trace2; + ucengine *uc; + uc_hook_h trace1, trace2; uc_err err; uint32_t addr, testval; int32_t buf1[1024], buf2[1024], readbuf[1024]; @@ -176,7 +177,7 @@ int main(int argc, char **argv, char **envp) printf("# Memory protect test\n"); // Initialize emulator in X86-32bit mode - err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err) { printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); return 1; @@ -184,20 +185,20 @@ int main(int argc, char **argv, char **envp) printf("ok %d - uc_open() success\n", log_num++); } - uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); - uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); - uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); - uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); + uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); // fill in sections that shouldn't get touched - if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { + if (uc_mem_write(uc, 0x3ff000, (uint8_t*)buf1, 4096)) { printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); return 2; } else { printf("ok %d - Random buffer 1 written to memory\n", log_num++); } - if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { + if (uc_mem_write(uc, 0x401000, (uint8_t*)buf2, 4096)) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); return 3; } else { @@ -205,31 +206,31 @@ int main(int argc, char **argv, char **envp) } // write machine code to be emulated to memory - if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { + if (uc_mem_write(uc, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 4; } else { printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++); return 5; } else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++); } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++); return 6; } else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); } // intercept invalid memory events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++); return 7; } else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); @@ -237,7 +238,7 @@ int main(int argc, char **argv, char **envp) // emulate machine code until told to stop by hook_code printf("# BEGIN execution\n"); - err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); + err = uc_emu_start(uc, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); if (err != UC_ERR_OK) { printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); return 8; @@ -250,7 +251,7 @@ int main(int argc, char **argv, char **envp) testval = 0x42424242; for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { uint32_t val; - if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr); } else { printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); @@ -269,7 +270,7 @@ int main(int argc, char **argv, char **envp) //make sure that random blocks didn't get nuked // fill in sections that shouldn't get touched - if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x3ff000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); } else { printf("ok %d - Random buffer 1 read from memory\n", log_num++); @@ -280,7 +281,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x401000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); } else { printf("ok %d - Random buffer 2 read from memory\n", log_num++); @@ -291,7 +292,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_close(&handle) == UC_ERR_OK) { + if (uc_close(uc) == UC_ERR_OK) { printf("ok %d - uc_close complete\n", log_num++); } else { printf("not ok %d - uc_close complete\n", log_num++); diff --git a/samples/mem_unmap.c b/samples/mem_unmap.c index e35b95b..4486653 100644 --- a/samples/mem_unmap.c +++ b/samples/mem_unmap.c @@ -72,18 +72,18 @@ static int log_num = 1; #define CODE_SIZE 0x1000 // callback for tracing instruction -static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) +static void hook_code(ucengine *uc, uint64_t addr, uint32_t size, void *user_data) { uint8_t opcode; uint32_t testval; - if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr); switch (opcode) { case 0x90: //nop printf("# Handling NOP\n"); - if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { + if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); } else { printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); @@ -97,7 +97,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) printf("# Received: 0x%x\n", testval); } } - if (uc_mem_unmap(handle, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) { + if (uc_mem_unmap(uc, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) { printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); } else { printf("ok %d - uc_mem_unmap success\n", log_num++); @@ -106,7 +106,7 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) break; case 0xf4: //hlt printf("# Handling HLT\n"); - if (uc_emu_stop(handle) != UC_ERR_OK) { + if (uc_emu_stop(uc) != UC_ERR_OK) { printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); _exit(-1); } else { @@ -120,14 +120,14 @@ static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) } // callback for tracing memory access (READ or WRITE) -static void hook_mem_write(uch handle, uc_mem_type type, +static void hook_mem_write(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); } // callback for tracing invalid memory access (READ or WRITE) -static bool hook_mem_invalid(uch handle, uc_mem_type type, +static bool hook_mem_invalid(ucengine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { uint32_t testval; @@ -138,13 +138,13 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, case UC_MEM_WRITE: printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); - if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { printf("ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("not ok %d - uc_mem_read success after unmap at test %d\n", log_num++, test_num - 1); } - if (uc_mem_map(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { + if (uc_mem_map(uc, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { printf("not ok %d - uc_mem_map fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); } else { printf("ok %d - uc_mem_map success\n", log_num++); @@ -155,7 +155,8 @@ static bool hook_mem_invalid(uch handle, uc_mem_type type, int main(int argc, char **argv, char **envp) { - uch handle, trace1, trace2; + ucengine *uc; + uc_hook_h trace1, trace2; uc_err err; uint32_t addr, testval; int32_t buf1[1024], buf2[1024], readbuf[1024]; @@ -171,7 +172,7 @@ int main(int argc, char **argv, char **envp) printf("# Memory unmapping test\n"); // Initialize emulator in X86-32bit mode - err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err) { printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); return 1; @@ -179,20 +180,20 @@ int main(int argc, char **argv, char **envp) printf("ok %d - uc_open() success\n", log_num++); } - uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); - uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); - uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); - uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); + uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(uc, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); // fill in sections that shouldn't get touched - if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { + if (uc_mem_write(uc, 0x3ff000, (uint8_t*)buf1, 4096)) { printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); return 2; } else { printf("ok %d - Random buffer 1 written to memory\n", log_num++); } - if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { + if (uc_mem_write(uc, 0x401000, (uint8_t*)buf2, 4096)) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); return 3; } else { @@ -200,31 +201,31 @@ int main(int argc, char **argv, char **envp) } // write machine code to be emulated to memory - if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { + if (uc_mem_write(uc, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 4; } else { printf("ok %d - Program written to memory\n", log_num++); } - if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++); return 5; } else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++); } // intercept memory write events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++); return 6; } else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); } // intercept invalid memory events - if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { - printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); + if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { + printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID ucr\n", log_num++); return 7; } else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); @@ -232,7 +233,7 @@ int main(int argc, char **argv, char **envp) // emulate machine code until told to stop by hook_code printf("# BEGIN execution\n"); - err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); + err = uc_emu_start(uc, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); if (err != UC_ERR_OK) { printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); return 8; @@ -245,7 +246,7 @@ int main(int argc, char **argv, char **envp) testval = 0x42424242; for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { uint32_t val; - if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { + if (uc_mem_read(uc, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr); } else { printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); @@ -260,7 +261,7 @@ int main(int argc, char **argv, char **envp) //make sure that random blocks didn't get nuked // fill in sections that shouldn't get touched - if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x3ff000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); } else { printf("ok %d - Random buffer 1 read from memory\n", log_num++); @@ -271,7 +272,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { + if (uc_mem_read(uc, 0x401000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); } else { printf("ok %d - Random buffer 2 read from memory\n", log_num++); @@ -282,7 +283,7 @@ int main(int argc, char **argv, char **envp) } } - if (uc_close(&handle) == UC_ERR_OK) { + if (uc_close(uc) == UC_ERR_OK) { printf("ok %d - uc_close complete\n", log_num++); } else { printf("not ok %d - uc_close complete\n", log_num++); diff --git a/uc.c b/uc.c index 49d29cf..6001e61 100644 --- a/uc.c +++ b/uc.c @@ -31,8 +31,6 @@ #include "qemu/include/hw/boards.h" -static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr); -static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t address, size_t size, bool do_delete); UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) @@ -589,11 +587,11 @@ uc_err uc_mem_map(ucengine *uc, uint64_t address, size_t size, uint32_t perms) // Create a backup copy of the indicated MemoryRegion. // Generally used in prepartion for splitting a MemoryRegion. -static uint8_t *copy_region(uch handle, MemoryRegion *mr) +static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) { uint8_t *block = (uint8_t *)malloc(int128_get64(mr->size)); if (block != NULL) { - uc_err err = uc_mem_read(handle, mr->addr, block, int128_get64(mr->size)); + uc_err err = uc_mem_read(uc, mr->addr, block, int128_get64(mr->size)); if (err != UC_ERR_OK) { free(block); block = NULL; @@ -618,7 +616,7 @@ static uint8_t *copy_region(uch handle, MemoryRegion *mr) */ // TODO: investigate whether qemu region manipulation functions already offered // this capability -static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, +static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t address, size_t size, bool do_delete) { uint8_t *backup; @@ -641,7 +639,7 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, // impossible case return false; - backup = copy_region(handle, mr); + backup = copy_region(uc, mr); if (backup == NULL) return false; @@ -651,7 +649,7 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, end = mr->end; // unmap this region first, then do split it later - if (uc_mem_unmap(handle, mr->addr, int128_get64(mr->size)) != UC_ERR_OK) + if (uc_mem_unmap(uc, mr->addr, int128_get64(mr->size)) != UC_ERR_OK) goto error; /* overlapping cases @@ -677,23 +675,23 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, // allocation just failed so no guarantee that we can recover the original // allocation at this point if (l_size > 0) { - if (uc_mem_map(handle, begin, l_size, perms) != UC_ERR_OK) + if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) goto error; - if (uc_mem_write(handle, begin, backup, l_size) != UC_ERR_OK) + if (uc_mem_write(uc, begin, backup, l_size) != UC_ERR_OK) goto error; } if (m_size > 0 && !do_delete) { - if (uc_mem_map(handle, address, m_size, perms) != UC_ERR_OK) + if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) goto error; - if (uc_mem_write(handle, address, backup + l_size, m_size) != UC_ERR_OK) + if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) goto error; } if (r_size > 0) { - if (uc_mem_map(handle, chunk_end, r_size, perms) != UC_ERR_OK) + if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) goto error; - if (uc_mem_write(handle, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) + if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) goto error; } @@ -705,17 +703,12 @@ error: } UNICORN_EXPORT -uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms) +uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms) { - struct uc_struct* uc = (struct uc_struct *)handle; MemoryRegion *mr; uint64_t addr = address; size_t count, len; - if (handle == 0) - // invalid handle - return UC_ERR_UCH; - if (size == 0) // trivial case, no change return UC_ERR_OK; @@ -743,7 +736,7 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms) while(count < size) { mr = memory_mapping(uc, addr); len = MIN(size - count, mr->end - addr); - if (!split_region(handle, mr, addr, len, false)) + if (!split_region(uc, mr, addr, len, false)) return UC_ERR_NOMEM; mr = memory_mapping(uc, addr); @@ -757,17 +750,12 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms) } UNICORN_EXPORT -uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size) +uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) { MemoryRegion *mr; - struct uc_struct* uc = (struct uc_struct *)handle; uint64_t addr; size_t count, len; - if (handle == 0) - // invalid handle - return UC_ERR_UCH; - if (size == 0) // nothing to unmap return UC_ERR_OK; @@ -791,7 +779,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size) while(count < size) { mr = memory_mapping(uc, addr); len = MIN(size - count, mr->end - addr); - if (!split_region(handle, mr, addr, len, true)) + if (!split_region(uc, mr, addr, len, true)) return UC_ERR_NOMEM; // if we can retrieve the mapping, then no splitting took place // so unmap here