diff --git a/.gitignore b/.gitignore index 271960ff..50b09750 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,7 @@ tmp/ bindings/python/build/ config.log + +regress/map_crash +regress/sigill +regress/sigill2 diff --git a/CREDITS.TXT b/CREDITS.TXT index c9999944..a529cc49 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -23,10 +23,10 @@ Darel Griffin, NCC Group Anton Cherepanov Mohamed Saher (halsten) Tyler Colgan -Jonathon Reinhart, jonathon.reinhart at gmail.com +Jonathon Reinhart Blue Skeye Chris Maixner -Pancake "radare" +Sergi Alvarez, aka pancake (author of radare) Ryan Hileman Tim "diff" Strazzere WanderingGlitch of the Zero Day Initiative diff --git a/include/uc_priv.h b/include/uc_priv.h index efff0e7e..c9e19f95 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -28,7 +28,7 @@ typedef int (*reg_access_t)(uch handle, unsigned int regid, void *value); typedef void (*reg_reset_t)(uch handle); -typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int len); +typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len); typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int len); diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 0063ba5a..d5bb350a 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -303,7 +303,7 @@ uc_err uc_reg_read(uch handle, int regid, void *value); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_write(uch handle, uint64_t address, uint8_t *bytes, size_t size); +uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size); /* Read a range of bytes in memory. diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index b3111cb0..8235c0e5 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -938,6 +938,16 @@ int x86_uc_machine_init(struct uc_struct *uc) return machine_initialize(uc); } +static bool x86_stop_interrupt(int intno) +{ + switch(intno) { + default: + return false; + case EXCP06_ILLOP: + return true; + } +} + void pc_machine_init(struct uc_struct *uc); __attribute__ ((visibility ("default"))) @@ -954,5 +964,6 @@ void x86_uc_init(struct uc_struct* uc) uc->reg_reset = x86_reg_reset; uc->release = x86_release; uc->set_pc = x86_set_pc; + uc->stop_interrupt = x86_stop_interrupt; uc_common_init(uc); } diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 2a6a0668..93f1c5f4 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -14,7 +14,7 @@ static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, } static inline bool cpu_physical_mem_write(AddressSpace *as, hwaddr addr, - uint8_t *buf, int len) + const uint8_t *buf, int len) { return !cpu_physical_memory_rw(as, addr, (void *)buf, len, 1); } diff --git a/regress/Makefile b/regress/Makefile new file mode 100644 index 00000000..d0becfea --- /dev/null +++ b/regress/Makefile @@ -0,0 +1,11 @@ +CFLAGS += -I../include +LDFLAGS = -L.. -lunicorn + +TESTS = map_crash sigill sigill2 + +all: $(TESTS) + +clean: + rm -f $(TESTS) + +.PHONY: all clean diff --git a/regress/map_crash.c b/regress/map_crash.c new file mode 100644 index 00000000..4d6bc8fe --- /dev/null +++ b/regress/map_crash.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#define UC_BUG_WRITE_SIZE 13000 +#define UC_BUG_WRITE_ADDR 0x1000 // fix this by change this to 0x2000 + +int main() { + int size; + uint8_t *buf; + uch uh; + uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh); + if (err) { + fprintf (stderr, "Cannot initialize unicorn\n"); + return 1; + } + size = UC_BUG_WRITE_SIZE; + buf = malloc (size); + if (!buf) { + fprintf (stderr, "Cannot allocate\n"); + return 1; + } + memset (buf, 0, size); + if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) { + uc_mem_write (uh, UC_BUG_WRITE_ADDR, buf, size); + } + uc_close (&uh); + return 0; +} diff --git a/regress/sigill.c b/regress/sigill.c new file mode 100644 index 00000000..099bbec3 --- /dev/null +++ b/regress/sigill.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +#define UC_BUG_WRITE_SIZE 128 +#define UC_BUG_WRITE_ADDR 0x1000 // fix this by change this to 0x2000 + +int got_sigill = 0; + +void _interrupt(uch handle, uint32_t intno, void *user_data) { + if (intno == 6) { + uc_emu_stop (handle); + got_sigill = 1; + } +} + +int main() { + int size; + uint8_t *buf; + uch uh; + uch uh_trap; + uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh); + if (err) { + fprintf (stderr, "Cannot initialize unicorn\n"); + return 1; + } + size = UC_BUG_WRITE_SIZE; + buf = malloc (size); + if (!buf) { + fprintf (stderr, "Cannot allocate\n"); + return 1; + } + memset (buf, 0, size); + if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) { + uc_mem_write (uh, UC_BUG_WRITE_ADDR, + (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); + } + uc_hook_add (uh, &uh_trap, UC_HOOK_INTR, _interrupt, NULL); + uc_emu_start (uh, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); + uc_close (&uh); + printf ("Correct: %s\n", got_sigill? "YES": "NO"); + return got_sigill? 0: 1; +} diff --git a/regress/sigill2.c b/regress/sigill2.c new file mode 100644 index 00000000..97cd7199 --- /dev/null +++ b/regress/sigill2.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#define UC_BUG_WRITE_SIZE 128 +#define UC_BUG_WRITE_ADDR 0x2000 + +int main() +{ + int size; + uint8_t *buf; + uch uh; + uch uh_trap; + uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh); + if (err) { + fprintf (stderr, "Cannot initialize unicorn\n"); + return 1; + } + size = UC_BUG_WRITE_SIZE; + if (!uc_mem_map (uh, UC_BUG_WRITE_ADDR, size)) { + uc_mem_write (uh, UC_BUG_WRITE_ADDR, + (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); + } + err = uc_emu_start (uh, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); + uc_close (&uh); + printf ("Error = %u (%s)\n", err, uc_strerror(err)); + return err? -1: 0; +} diff --git a/samples/Makefile b/samples/Makefile index 5cc32ee7..1ebb891f 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -75,7 +75,7 @@ endif .PHONY: all clean -UNICORN_ARCHS := $(shell if [ -a ../config.log ]; then cat ../config.log;\ +UNICORN_ARCHS := $(shell if [ -e ../config.log ]; then cat ../config.log;\ else printf "$(UNICORN_ARCHS)"; fi) SOURCES = diff --git a/uc.c b/uc.c index ec337d36..c1d6479c 100755 --- a/uc.c +++ b/uc.c @@ -356,7 +356,7 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size) UNICORN_EXPORT -uc_err uc_mem_write(uch handle, uint64_t address, uint8_t *bytes, size_t size) +uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size) { struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle; @@ -410,6 +410,11 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout // invalid handle return UC_ERR_UCH; + // reset the counter + uc->emu_counter = 0; + uc->stop_request = false; + uc->invalid_error = UC_ERR_OK; + switch(uc->arch) { default: break; @@ -474,11 +479,6 @@ uc_err uc_emu_start(uch handle, uint64_t begin, uint64_t until, uint64_t timeout // emulation is done uc->emulation_done = true; - // reset the counter - uc->emu_counter = 0; - uc->stop_request = false; - uc->invalid_error = UC_ERR_OK; - return uc->invalid_error; }