// callback for tracing invalid memory access (READ or WRITE) static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { switch(type) { default: printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr); return false; case UC_MEM_FETCH_PROT: printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr); //make page executable 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); } return true; 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(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++); } return true; } }
// callback for tracing instructions, detect HLT and terminate emulation static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data) { uint8_t opcode; unsigned char buf[256]; insts_executed++; if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) { printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); if (uc_emu_stop(uc) != UC_ERR_OK) { printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); _exit(-1); } } opcode = buf[0]; switch (opcode) { case 0x41: // inc ecx if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); _exit(-1); } break; case 0x42: // inc edx if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) { printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); _exit(-1); } break; case 0xf4: // hlt if (uc_emu_stop(uc) != UC_ERR_OK) { printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); _exit(-1); } break; default: // all others break; } }