Merge remote-tracking branch 'upstream/master' into hook_mem_constants_documentation

This commit is contained in:
Sean Heelan 2015-09-05 00:41:23 +07:00
commit 84a374e876
22 changed files with 293 additions and 234 deletions

View file

@ -43,11 +43,12 @@ Unicorn requires few dependent packages as followings
The other way of customize Unicorn without having to edit config.mk is to The other way of customize Unicorn without having to edit config.mk is to
pass the desired options on the commandline to ./make.sh. Currently, pass the desired options on the commandline to ./make.sh. Currently,
Unicorn supports 3 options, as followings. Unicorn supports 4 options, as followings.
- UNICORN_ARCHS: specify list of architectures to compiled in. - UNICORN_ARCHS: specify list of architectures to compiled in.
- UNICORN_STATIC: build static library. - UNICORN_STATIC: build static library.
- UNICORN_SHARED: build dynamic (shared) library. - UNICORN_SHARED: build dynamic (shared) library.
- UNICORN_QEMU_FLAGS: specify extra flags for qemu's configure script
To avoid editing config.mk for these customization, we can pass their values to To avoid editing config.mk for these customization, we can pass their values to
make.sh, as followings. make.sh, as followings.

View file

@ -204,11 +204,11 @@ config:
qemu/config-host.h-timestamp: qemu/config-host.h-timestamp:
ifeq ($(UNICORN_DEBUG),yes) ifeq ($(UNICORN_DEBUG),yes)
cd qemu && \ cd qemu && \
./configure --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ./configure --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS}
printf "$(UNICORN_ARCHS)" > config.log printf "$(UNICORN_ARCHS)" > config.log
else else
cd qemu && \ cd qemu && \
./configure --disable-debug-info --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ./configure --disable-debug-info --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS}
printf "$(UNICORN_ARCHS)" > config.log printf "$(UNICORN_ARCHS)" > config.log
endif endif

View file

@ -395,7 +395,7 @@ public class SampleNetworkAuditing {
Unicorn mu = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn mu = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
mu.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); mu.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
mu.mem_write(ADDRESS, code); mu.mem_write(ADDRESS, code);

View file

@ -51,7 +51,7 @@ public class Sample_arm {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM); Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, ARM_CODE); u.mem_write(ADDRESS, ARM_CODE);
@ -93,7 +93,7 @@ public class Sample_arm {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_THUMB); Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_THUMB);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, THUMB_CODE); u.mem_write(ADDRESS, THUMB_CODE);

View file

@ -79,7 +79,7 @@ public class Sample_arm64 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM); Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, ARM_CODE); u.mem_write(ADDRESS, ARM_CODE);

View file

@ -95,7 +95,7 @@ public class Sample_m68k {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN); Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, M68K_CODE); u.mem_write(ADDRESS, M68K_CODE);

View file

@ -78,7 +78,7 @@ public class Sample_mips {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_BIG_ENDIAN); Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, MIPS_CODE_EB); u.mem_write(ADDRESS, MIPS_CODE_EB);
@ -116,7 +116,7 @@ public class Sample_mips {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, MIPS_CODE_EL); u.mem_write(ADDRESS, MIPS_CODE_EL);

View file

@ -79,7 +79,7 @@ public class Sample_sparc {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN); Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, SPARC_CODE); u.mem_write(ADDRESS, SPARC_CODE);

View file

@ -64,8 +64,7 @@ public class Sample_x86 {
// callback for tracing basic blocks // callback for tracing basic blocks
// callback for tracing instruction // callback for tracing instruction
private static class MyBlockHook implements BlockHook { private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) public void hook(Unicorn u, long address, int size, Object user_data) {
{
System.out.printf(">>> Tracing basic block at 0x%x, block size = 0x%x\n", address, size); System.out.printf(">>> Tracing basic block at 0x%x, block size = 0x%x\n", address, size);
} }
} }
@ -91,7 +90,7 @@ public class Sample_x86 {
System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n", System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n",
address, size, value); address, size, value);
// map this memory in with 2MB in size // map this memory in with 2MB in size
u.mem_map(0xaaaa0000, 2 * 1024*1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(0xaaaa0000, 2 * 1024*1024, Unicorn.UC_PROT_ALL);
// return true to indicate we want to continue // return true to indicate we want to continue
return true; return true;
} }
@ -129,8 +128,7 @@ public class Sample_x86 {
// callback for IN instruction (X86). // callback for IN instruction (X86).
// this returns the data read from the port // this returns the data read from the port
private static class MyInHook implements InHook { private static class MyInHook implements InHook {
public int hook(Unicorn u, int port, int size, Object user_data) public int hook(Unicorn u, int port, int size, Object user_data) {
{
byte[] r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4); byte[] r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
System.out.printf("--- reading from port 0x%x, size: %d, address: 0x%x\n", port, size, toInt(r_eip)); System.out.printf("--- reading from port 0x%x, size: %d, address: 0x%x\n", port, size, toInt(r_eip));
@ -176,8 +174,7 @@ public class Sample_x86 {
} }
} }
static void test_i386() static void test_i386() {
{
byte r_ecx[] = {(byte)0x34, (byte)0x12, 0, 0}; //0x1234; // ECX register byte r_ecx[] = {(byte)0x34, (byte)0x12, 0, 0}; //0x1234; // ECX register
byte r_edx[] = {(byte)0x90, (byte)0x78, 0, 0}; //0x7890; // EDX register byte r_edx[] = {(byte)0x90, (byte)0x78, 0, 0}; //0x7890; // EDX register
@ -193,7 +190,7 @@ public class Sample_x86 {
} }
// map 2MB memory for this emulation // map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); uc.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
try { try {
@ -251,7 +248,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_INOUT); u.mem_write(ADDRESS, X86_CODE32_INOUT);
@ -294,7 +291,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_JUMP); u.mem_write(ADDRESS, X86_CODE32_JUMP);
@ -326,7 +323,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_LOOP); u.mem_write(ADDRESS, X86_CODE32_LOOP);
@ -363,7 +360,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_MEM_READ); u.mem_write(ADDRESS, X86_CODE32_MEM_READ);
@ -410,7 +407,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_MEM_WRITE); u.mem_write(ADDRESS, X86_CODE32_MEM_WRITE);
@ -470,7 +467,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_JMP_INVALID); u.mem_write(ADDRESS, X86_CODE32_JMP_INVALID);
@ -528,7 +525,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE64); u.mem_write(ADDRESS, X86_CODE64);
@ -615,7 +612,7 @@ public class Sample_x86 {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_16); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_16);
// map 8KB memory for this emulation // map 8KB memory for this emulation
u.mem_map(0, 8 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(0, 8 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(0, X86_CODE16); u.mem_write(0, X86_CODE16);

View file

@ -121,7 +121,7 @@ public class Shellcode {
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
// map 2MB memory for this emulation // map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_SELF); u.mem_write(ADDRESS, X86_CODE32_SELF);

View file

@ -25,11 +25,7 @@ import java.util.*;
public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const { public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const {
// Scales to calculate timeout on microsecond unit private long eng;
// 1 second = 1000,000 microseconds
public static final int UC_SECOND_SCALE = 1000000;
// 1 milisecond = 1000 nanoseconds
public static final int UC_MILISECOND_SCALE = 1000;
private long blockHandle = 0; private long blockHandle = 0;
private long interruptHandle = 0; private long interruptHandle = 0;
@ -77,13 +73,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_BLOCK * for UC_HOOK_BLOCK
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param address The address of the instruction being executed * @param address The address of the instruction being executed
* @param size The size of the basic block being executed * @param size The size of the basic block being executed
* @see hook_add, unicorn.BlockHook * @see hook_add, unicorn.BlockHook
*/ */
private static void invokeBlockCallbacks(long handle, long address, int size) { private static void invokeBlockCallbacks(long eng, long address, int size) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.blockList) { for (Tuple p : u.blockList) {
BlockHook bh = (BlockHook)p.function; BlockHook bh = (BlockHook)p.function;
@ -97,12 +93,12 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_INTR * for UC_HOOK_INTR
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param intno The interrupt number * @param intno The interrupt number
* @see hook_add, unicorn.InterruptHook * @see hook_add, unicorn.InterruptHook
*/ */
private static void invokeInterruptCallbacks(long handle, int intno) { private static void invokeInterruptCallbacks(long eng, int intno) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.intrList) { for (Tuple p : u.intrList) {
InterruptHook ih = (InterruptHook)p.function; InterruptHook ih = (InterruptHook)p.function;
@ -116,13 +112,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_CODE * for UC_HOOK_CODE
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param address The address of the instruction being executed * @param address The address of the instruction being executed
* @param size The size of the instruction being executed * @param size The size of the instruction being executed
* @see hook_add, unicorn.CodeHook * @see hook_add, unicorn.CodeHook
*/ */
private static void invokeCodeCallbacks(long handle, long address, int size) { private static void invokeCodeCallbacks(long eng, long address, int size) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.codeList) { for (Tuple p : u.codeList) {
CodeHook ch = (CodeHook)p.function; CodeHook ch = (CodeHook)p.function;
@ -136,7 +132,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_MEM_INVALID * for UC_HOOK_MEM_INVALID
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param type This memory is being read (UC_MEM_READ), or written (UC_MEM_WRITE) * @param type This memory is being read (UC_MEM_READ), or written (UC_MEM_WRITE)
* @param address Address of instruction being executed * @param address Address of instruction being executed
* @param size Size of data being read or written * @param size Size of data being read or written
@ -144,8 +140,8 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* @return true to continue, or false to stop program (due to invalid memory). * @return true to continue, or false to stop program (due to invalid memory).
* @see hook_add, unicorn.MemoryInvalidHook * @see hook_add, unicorn.MemoryInvalidHook
*/ */
private static boolean invokeMemInvalidCallbacks(long handle, int type, long address, int size, long value) { private static boolean invokeMemInvalidCallbacks(long eng, int type, long address, int size, long value) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
boolean result = true; boolean result = true;
if (u != null) { if (u != null) {
for (Tuple p : u.memInvalidList) { for (Tuple p : u.memInvalidList) {
@ -161,13 +157,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_MEM_READ * for UC_HOOK_MEM_READ
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param address Address of instruction being executed * @param address Address of instruction being executed
* @param size Size of data being read * @param size Size of data being read
* @see hook_add, unicorn.ReadHook * @see hook_add, unicorn.ReadHook
*/ */
private static void invokeReadCallbacks(long handle, long address, int size) { private static void invokeReadCallbacks(long eng, long address, int size) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.readList) { for (Tuple p : u.readList) {
ReadHook rh = (ReadHook)p.function; ReadHook rh = (ReadHook)p.function;
@ -181,14 +177,14 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_MEM_WRITE * for UC_HOOK_MEM_WRITE
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param address Address of instruction being executed * @param address Address of instruction being executed
* @param size Size of data being read * @param size Size of data being read
* @param value value being written * @param value value being written
* @see hook_add, unicorn.WriteHook * @see hook_add, unicorn.WriteHook
*/ */
private static void invokeWriteCallbacks(long handle, long address, int size, long value) { private static void invokeWriteCallbacks(long eng, long address, int size, long value) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.writeList) { for (Tuple p : u.writeList) {
WriteHook wh = (WriteHook)p.function; WriteHook wh = (WriteHook)p.function;
@ -202,15 +198,15 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_MEM_READ_WRITE * for UC_HOOK_MEM_READ_WRITE
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param type Type of access being performed (UC_MEM_READ, UC_MEM_WRITE, UC_MEM_READ_WRITE) * @param type Type of access being performed (UC_MEM_READ, UC_MEM_WRITE, UC_MEM_READ_WRITE)
* @param address Address of instruction being executed * @param address Address of instruction being executed
* @param size Size of data being read * @param size Size of data being read
* @param value value being written (if applicable) * @param value value being written (if applicable)
* @see hook_add, unicorn.ReadWriteHook * @see hook_add, unicorn.ReadWriteHook
*/ */
private static void invokeReadWriteCallbacks(long handle, int type, long address, int size, long value) { private static void invokeReadWriteCallbacks(long eng, int type, long address, int size, long value) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
if (u != null) { if (u != null) {
for (Tuple p : u.readWriteList) { for (Tuple p : u.readWriteList) {
ReadWriteHook rwh = (ReadWriteHook)p.function; ReadWriteHook rwh = (ReadWriteHook)p.function;
@ -225,14 +221,14 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_INSN * for UC_HOOK_INSN
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param port I/O Port number * @param port I/O Port number
* @param size Data size (1/2/4) to be read from this port * @param size Data size (1/2/4) to be read from this port
* @return Data supplied from the input port * @return Data supplied from the input port
* @see hook_add, unicorn.InHook * @see hook_add, unicorn.InHook
*/ */
private static int invokeInCallbacks(long handle, int port, int size) { private static int invokeInCallbacks(long eng, int port, int size) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
int result = 0; int result = 0;
if (u != null) { if (u != null) {
for (Tuple p : u.inList) { for (Tuple p : u.inList) {
@ -249,13 +245,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_INSN * for UC_HOOK_INSN
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @param port I/O Port number * @param port I/O Port number
* @param size Data size (1/2/4) to be written to this port * @param size Data size (1/2/4) to be written to this port
* @see hook_add, unicorn.OutHook * @see hook_add, unicorn.OutHook
*/ */
private static void invokeOutCallbacks(long handle, int port, int size, int value) { private static void invokeOutCallbacks(long eng, int port, int size, int value) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
int result = 0; int result = 0;
if (u != null) { if (u != null) {
for (Tuple p : u.outList) { for (Tuple p : u.outList) {
@ -271,11 +267,11 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* This function gets invoked from the native C callback registered for * This function gets invoked from the native C callback registered for
* for UC_HOOK_INSN * for UC_HOOK_INSN
* *
* @param handle A Unicorn uch handle returned by uc_open * @param eng A Unicorn ucengine* eng returned by uc_open
* @see hook_add, unicorn.SyscallHook * @see hook_add, unicorn.SyscallHook
*/ */
private static void invokeSyscallCallbacks(long handle) { private static void invokeSyscallCallbacks(long eng) {
Unicorn u = unicorns.get(handle); Unicorn u = unicorns.get(eng);
int result = 0; int result = 0;
if (u != null) { if (u != null) {
for (Tuple p : u.syscallList) { for (Tuple p : u.syscallList) {
@ -293,8 +289,6 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
private native long open(int arch, int mode) throws UnicornException; private native long open(int arch, int mode) throws UnicornException;
private long handle;
/** /**
* Create a new Unicorn object * Create a new Unicorn object
* *
@ -304,8 +298,8 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* *
*/ */
public Unicorn(int arch, int mode) throws UnicornException { public Unicorn(int arch, int mode) throws UnicornException {
handle = open(arch, mode); eng = open(arch, mode);
unicorns.put(handle, this); unicorns.put(eng, this);
allLists.add(blockList); allLists.add(blockList);
allLists.add(intrList); allLists.add(intrList);
allLists.add(codeList); allLists.add(codeList);
@ -323,7 +317,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* *
*/ */
protected void finalize() { protected void finalize() {
unicorns.remove(handle); unicorns.remove(eng);
close(); close();
} }
@ -346,7 +340,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
public native static boolean arch_supported(int arch); public native static boolean arch_supported(int arch);
/** /**
* Close the underlying uch handle associated with this Unicorn object * Close the underlying ucengine* eng associated with this Unicorn object
* *
*/ */
public native void close() throws UnicornException; public native void close() throws UnicornException;
@ -423,32 +417,32 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
/** /**
* Hook registration helper for hook types that require no additional arguments. * Hook registration helper for hook types that require no additional arguments.
* *
* @param handle Internal unicorn uch handle associated with hooking Unicorn object * @param eng Internal unicorn ucengine* eng associated with hooking Unicorn object
* @param type UC_HOOK_* hook type * @param type UC_HOOK_* hook type
* @return Unicorn uch returned for registered hook function * @return Unicorn uch returned for registered hook function
*/ */
private native static long registerHook(long handle, int type); private native static long registerHook(long eng, int type);
/** /**
* Hook registration helper for hook types that require one additional argument. * Hook registration helper for hook types that require one additional argument.
* *
* @param handle Internal unicorn uch handle associated with hooking Unicorn object * @param eng Internal unicorn ucengine* eng associated with hooking Unicorn object
* @param type UC_HOOK_* hook type * @param type UC_HOOK_* hook type
* @param arg1 Additional varargs argument * @param arg1 Additional varargs argument
* @return Unicorn uch returned for registered hook function * @return Unicorn uch returned for registered hook function
*/ */
private native static long registerHook(long handle, int type, int arg1); private native static long registerHook(long eng, int type, int arg1);
/** /**
* Hook registration helper for hook types that require two additional arguments. * Hook registration helper for hook types that require two additional arguments.
* *
* @param handle Internal unicorn uch handle associated with hooking Unicorn object * @param eng Internal unicorn ucengine* eng associated with hooking Unicorn object
* @param type UC_HOOK_* hook type * @param type UC_HOOK_* hook type
* @param arg1 First additional varargs argument * @param arg1 First additional varargs argument
* @param arg2 Second additional varargs argument * @param arg2 Second additional varargs argument
* @return Unicorn uch returned for registered hook function * @return Unicorn uch returned for registered hook function
*/ */
private native static long registerHook(long handle, int type, long arg1, long arg2); private native static long registerHook(long eng, int type, long arg1, long arg2);
/** /**
* Hook registration for UC_HOOK_BLOCK hooks. The registered callback function will be * Hook registration for UC_HOOK_BLOCK hooks. The registered callback function will be
@ -463,7 +457,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(BlockHook callback, long begin, long end, Object user_data) throws UnicornException { public void hook_add(BlockHook callback, long begin, long end, Object user_data) throws UnicornException {
if (blockHandle == 0) { if (blockHandle == 0) {
blockHandle = registerHook(handle, UC_HOOK_BLOCK, begin, end); blockHandle = registerHook(eng, UC_HOOK_BLOCK, begin, end);
} }
blockList.add(new Tuple(callback, user_data)); blockList.add(new Tuple(callback, user_data));
} }
@ -477,7 +471,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(InterruptHook callback, Object user_data) throws UnicornException { public void hook_add(InterruptHook callback, Object user_data) throws UnicornException {
if (interruptHandle == 0) { if (interruptHandle == 0) {
interruptHandle = registerHook(handle, UC_HOOK_INTR); interruptHandle = registerHook(eng, UC_HOOK_INTR);
} }
intrList.add(new Tuple(callback, user_data)); intrList.add(new Tuple(callback, user_data));
} }
@ -494,7 +488,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(CodeHook callback, long begin, long end, Object user_data) throws UnicornException { public void hook_add(CodeHook callback, long begin, long end, Object user_data) throws UnicornException {
if (codeHandle == 0) { if (codeHandle == 0) {
codeHandle = registerHook(handle, UC_HOOK_CODE, begin, end); codeHandle = registerHook(eng, UC_HOOK_CODE, begin, end);
} }
codeList.add(new Tuple(callback, user_data)); codeList.add(new Tuple(callback, user_data));
} }
@ -511,7 +505,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(ReadHook callback, long begin, long end, Object user_data) throws UnicornException { public void hook_add(ReadHook callback, long begin, long end, Object user_data) throws UnicornException {
if (readHandle == 0) { if (readHandle == 0) {
readHandle = registerHook(handle, UC_HOOK_MEM_READ, begin, end); readHandle = registerHook(eng, UC_HOOK_MEM_READ, begin, end);
} }
readList.add(new Tuple(callback, user_data)); readList.add(new Tuple(callback, user_data));
} }
@ -528,7 +522,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(WriteHook callback, long begin, long end, Object user_data) throws UnicornException { public void hook_add(WriteHook callback, long begin, long end, Object user_data) throws UnicornException {
if (writeHandle == 0) { if (writeHandle == 0) {
writeHandle = registerHook(handle, UC_HOOK_MEM_WRITE, begin, end); writeHandle = registerHook(eng, UC_HOOK_MEM_WRITE, begin, end);
} }
writeList.add(new Tuple(callback, user_data)); writeList.add(new Tuple(callback, user_data));
} }
@ -545,7 +539,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(ReadWriteHook callback, long begin, long end, Object user_data) throws UnicornException { public void hook_add(ReadWriteHook callback, long begin, long end, Object user_data) throws UnicornException {
if (readWriteHandle == 0) { if (readWriteHandle == 0) {
readWriteHandle = registerHook(handle, UC_HOOK_MEM_READ_WRITE, begin, end); readWriteHandle = registerHook(eng, UC_HOOK_MEM_READ_WRITE, begin, end);
} }
readWriteList.add(new Tuple(callback, user_data)); readWriteList.add(new Tuple(callback, user_data));
} }
@ -559,7 +553,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(MemoryInvalidHook callback, Object user_data) throws UnicornException { public void hook_add(MemoryInvalidHook callback, Object user_data) throws UnicornException {
if (memInvalidHandle == 0) { if (memInvalidHandle == 0) {
memInvalidHandle = registerHook(handle, UC_HOOK_MEM_INVALID); memInvalidHandle = registerHook(eng, UC_HOOK_MEM_INVALID);
} }
memInvalidList.add(new Tuple(callback, user_data)); memInvalidList.add(new Tuple(callback, user_data));
} }
@ -573,7 +567,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(InHook callback, Object user_data) throws UnicornException { public void hook_add(InHook callback, Object user_data) throws UnicornException {
if (inHandle == 0) { if (inHandle == 0) {
inHandle = registerHook(handle, UC_HOOK_INSN, Unicorn.UC_X86_INS_IN); inHandle = registerHook(eng, UC_HOOK_INSN, Unicorn.UC_X86_INS_IN);
} }
inList.add(new Tuple(callback, user_data)); inList.add(new Tuple(callback, user_data));
} }
@ -587,7 +581,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(OutHook callback, Object user_data) throws UnicornException { public void hook_add(OutHook callback, Object user_data) throws UnicornException {
if (outHandle == 0) { if (outHandle == 0) {
outHandle = registerHook(handle, UC_HOOK_INSN, Unicorn.UC_X86_INS_OUT); outHandle = registerHook(eng, UC_HOOK_INSN, Unicorn.UC_X86_INS_OUT);
} }
outList.add(new Tuple(callback, user_data)); outList.add(new Tuple(callback, user_data));
} }
@ -601,7 +595,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/ */
public void hook_add(SyscallHook callback, Object user_data) throws UnicornException { public void hook_add(SyscallHook callback, Object user_data) throws UnicornException {
if (syscallHandle == 0) { if (syscallHandle == 0) {
syscallHandle = registerHook(handle, UC_HOOK_INSN, Unicorn.UC_X86_INS_SYSCALL); syscallHandle = registerHook(eng, UC_HOOK_INSN, Unicorn.UC_X86_INS_SYSCALL);
} }
syscallList.add(new Tuple(callback, user_data)); syscallList.add(new Tuple(callback, user_data));
} }
@ -622,8 +616,26 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
* *
* @param address Base address of the memory range * @param address Base address of the memory range
* @param size Size of the memory block. * @param size Size of the memory block.
* @param perms Permissions on the memory block. A combination of UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
*/ */
public native void mem_map(long address, long size, int perms) throws UnicornException; public native void mem_map(long address, long size, int perms) throws UnicornException;
/**
* Unmap a range of memory.
*
* @param address Base address of the memory range
* @param size Size of the memory block.
*/
public native void mem_unmap(long address, long size) throws UnicornException;
/**
* Change permissions on a range of memory.
*
* @param address Base address of the memory range
* @param size Size of the memory block.
* @param perms New permissions on the memory block. A combination of UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
*/
public native void mem_protect(long address, long size, int perms) throws UnicornException;
} }

View file

@ -31,31 +31,32 @@ public interface UnicornConst {
public static final int UC_MODE_MIPS32R6 = 64; public static final int UC_MODE_MIPS32R6 = 64;
public static final int UC_MODE_V9 = 16; public static final int UC_MODE_V9 = 16;
public static final int UC_MODE_QPX = 16; public static final int UC_MODE_QPX = 16;
public static final int UC_MODE_BIG_ENDIAN = 0x80000000; public static final int UC_MODE_BIG_ENDIAN = 1073741824;
public static final int UC_MODE_MIPS32 = 4; public static final int UC_MODE_MIPS32 = 4;
public static final int UC_MODE_MIPS64 = 8; public static final int UC_MODE_MIPS64 = 8;
public static final int UC_ERR_OK = 0; public static final int UC_ERR_OK = 0;
public static final int UC_ERR_OOM = 1; public static final int UC_ERR_NOMEM = 1;
public static final int UC_ERR_ARCH = 2; public static final int UC_ERR_ARCH = 2;
public static final int UC_ERR_HANDLE = 3; public static final int UC_ERR_HANDLE = 3;
public static final int UC_ERR_UCH = 4; public static final int UC_ERR_MODE = 4;
public static final int UC_ERR_MODE = 5; public static final int UC_ERR_VERSION = 5;
public static final int UC_ERR_VERSION = 6; public static final int UC_ERR_MEM_READ = 6;
public static final int UC_ERR_MEM_READ = 7; public static final int UC_ERR_MEM_WRITE = 7;
public static final int UC_ERR_MEM_WRITE = 8; public static final int UC_ERR_CODE_INVALID = 8;
public static final int UC_ERR_CODE_INVALID = 9; public static final int UC_ERR_HOOK = 9;
public static final int UC_ERR_HOOK = 10; public static final int UC_ERR_INSN_INVALID = 10;
public static final int UC_ERR_INSN_INVALID = 11; public static final int UC_ERR_MAP = 11;
public static final int UC_ERR_MAP = 12; public static final int UC_ERR_WRITE_PROT = 12;
public static final int UC_ERR_MEM_WRITE_NW = 13; public static final int UC_ERR_READ_PROT = 13;
public static final int UC_ERR_MEM_READ_NR = 14; public static final int UC_ERR_EXEC_PROT = 14;
public static final int UC_ERR_INVAL = 15;
public static final int UC_MEM_READ = 16; public static final int UC_MEM_READ = 16;
public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_WRITE = 17;
public static final int UC_MEM_READ_WRITE = 18; public static final int UC_MEM_READ_WRITE = 18;
public static final int UC_MEM_WRITE_NW = 19; public static final int UC_MEM_WRITE_PROT = 19;
public static final int UC_MEM_READ_NR = 20; public static final int UC_MEM_READ_PROT = 20;
public static final int UC_MEM_NX = 21; public static final int UC_MEM_EXEC_PROT = 21;
public static final int UC_HOOK_INTR = 32; public static final int UC_HOOK_INTR = 32;
public static final int UC_HOOK_INSN = 33; public static final int UC_HOOK_INSN = 33;
public static final int UC_HOOK_CODE = 34; public static final int UC_HOOK_CODE = 34;
@ -64,8 +65,11 @@ public interface UnicornConst {
public static final int UC_HOOK_MEM_READ = 37; public static final int UC_HOOK_MEM_READ = 37;
public static final int UC_HOOK_MEM_WRITE = 38; public static final int UC_HOOK_MEM_WRITE = 38;
public static final int UC_HOOK_MEM_READ_WRITE = 39; public static final int UC_HOOK_MEM_READ_WRITE = 39;
public static final int UC_PROT_NONE = 0;
public static final int UC_PROT_READ = 1; public static final int UC_PROT_READ = 1;
public static final int UC_PROT_WRITE = 2; public static final int UC_PROT_WRITE = 2;
public static final int UC_PROT_EXEC = 4; public static final int UC_PROT_EXEC = 4;
public static final int UC_PROT_ALL = 7;
} }

View file

@ -52,14 +52,14 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
// @address: address where the code is being executed // @address: address where the code is being executed
// @size: size of machine instruction being executed // @size: size of machine instruction being executed
// @user_data: user data passed to tracing APIs. // @user_data: user data passed to tracing APIs.
static void cb_hookcode(uch handle, uint64_t address, uint32_t size, void *user_data) { static void cb_hookcode(ucengine *eng, uint64_t address, uint32_t size, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn"); jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return; return;
} }
(*env)->CallStaticVoidMethod(env, clz, invokeCodeCallbacks, (jlong)handle, (jlong)address, (int)size); (*env)->CallStaticVoidMethod(env, clz, invokeCodeCallbacks, (jlong)eng, (jlong)address, (int)size);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
} }
@ -67,28 +67,28 @@ static void cb_hookcode(uch handle, uint64_t address, uint32_t size, void *user_
// @address: address where the code is being executed // @address: address where the code is being executed
// @size: size of machine instruction being executed // @size: size of machine instruction being executed
// @user_data: user data passed to tracing APIs. // @user_data: user data passed to tracing APIs.
static void cb_hookblock(uch handle, uint64_t address, uint32_t size, void *user_data) { static void cb_hookblock(ucengine *eng, uint64_t address, uint32_t size, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn"); jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return; return;
} }
(*env)->CallStaticVoidMethod(env, clz, invokeBlockCallbacks, (jlong)handle, (jlong)address, (int)size); (*env)->CallStaticVoidMethod(env, clz, invokeBlockCallbacks, (jlong)eng, (jlong)address, (int)size);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
} }
// Callback function for tracing interrupts (for uc_hook_intr()) // Callback function for tracing interrupts (for uc_hook_intr())
// @intno: interrupt number // @intno: interrupt number
// @user_data: user data passed to tracing APIs. // @user_data: user data passed to tracing APIs.
static void cb_hookintr(uch handle, uint32_t intno, void *user_data) { static void cb_hookintr(ucengine *eng, uint32_t intno, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn"); jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return; return;
} }
(*env)->CallStaticVoidMethod(env, clz, invokeInterruptCallbacks, (jlong)handle, (int)intno); (*env)->CallStaticVoidMethod(env, clz, invokeInterruptCallbacks, (jlong)eng, (int)intno);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
} }
@ -96,7 +96,7 @@ static void cb_hookintr(uch handle, uint32_t intno, void *user_data) {
// @port: port number // @port: port number
// @size: data size (1/2/4) to be read from this port // @size: data size (1/2/4) to be read from this port
// @user_data: user data passed to tracing APIs. // @user_data: user data passed to tracing APIs.
static uint32_t cb_insn_in(uch handle, uint32_t port, int size, void *user_data) { static uint32_t cb_insn_in(ucengine *eng, uint32_t port, int size, void *user_data) {
JNIEnv *env; JNIEnv *env;
uint32_t res = 0; uint32_t res = 0;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
@ -104,7 +104,7 @@ static uint32_t cb_insn_in(uch handle, uint32_t port, int size, void *user_data)
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return 0; return 0;
} }
res = (uint32_t)(*env)->CallStaticIntMethod(env, clz, invokeInCallbacks, (jlong)handle, (jint)port, (jint)size); res = (uint32_t)(*env)->CallStaticIntMethod(env, clz, invokeInCallbacks, (jlong)eng, (jint)port, (jint)size);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
return res; return res;
} }
@ -113,26 +113,26 @@ static uint32_t cb_insn_in(uch handle, uint32_t port, int size, void *user_data)
// @port: port number // @port: port number
// @size: data size (1/2/4) to be written to this port // @size: data size (1/2/4) to be written to this port
// @value: data value to be written to this port // @value: data value to be written to this port
static void cb_insn_out(uch handle, uint32_t port, int size, uint32_t value, void *user_data) { static void cb_insn_out(ucengine *eng, uint32_t port, int size, uint32_t value, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn"); jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return; return;
} }
(*env)->CallStaticVoidMethod(env, clz, invokeOutCallbacks, (jlong)handle, (jint)port, (jint)size, (jint)value); (*env)->CallStaticVoidMethod(env, clz, invokeOutCallbacks, (jlong)eng, (jint)port, (jint)size, (jint)value);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
} }
// x86's handler for SYSCALL/SYSENTER // x86's handler for SYSCALL/SYSENTER
static void cb_insn_syscall(uch handle, void *user_data) { static void cb_insn_syscall(ucengine *eng, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn"); jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return; return;
} }
(*env)->CallStaticVoidMethod(env, clz, invokeSyscallCallbacks, (jlong)handle); (*env)->CallStaticVoidMethod(env, clz, invokeSyscallCallbacks, (jlong)eng);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
} }
@ -142,7 +142,7 @@ static void cb_insn_syscall(uch handle, void *user_data) {
// @size: size of data being read or written // @size: size of data being read or written
// @value: value of data being written to memory, or irrelevant if type = READ. // @value: value of data being written to memory, or irrelevant if type = READ.
// @user_data: user data passed to tracing APIs // @user_data: user data passed to tracing APIs
static void cb_hookmem(uch handle, uc_mem_type type, static void cb_hookmem(ucengine *eng, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data) { uint64_t address, int size, int64_t value, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
@ -152,13 +152,13 @@ static void cb_hookmem(uch handle, uc_mem_type type,
} }
switch (type) { switch (type) {
case UC_MEM_READ: case UC_MEM_READ:
(*env)->CallStaticVoidMethod(env, clz, invokeReadCallbacks, (jlong)handle, (jlong)address, (int)size); (*env)->CallStaticVoidMethod(env, clz, invokeReadCallbacks, (jlong)eng, (jlong)address, (int)size);
break; break;
case UC_MEM_WRITE: case UC_MEM_WRITE:
(*env)->CallStaticVoidMethod(env, clz, invokeWriteCallbacks, (jlong)handle, (jlong)address, (int)size, (jlong)value); (*env)->CallStaticVoidMethod(env, clz, invokeWriteCallbacks, (jlong)eng, (jlong)address, (int)size, (jlong)value);
break; break;
case UC_MEM_READ_WRITE: case UC_MEM_READ_WRITE:
(*env)->CallStaticVoidMethod(env, clz, invokeReadWriteCallbacks, (jlong)handle, (int)type, (jlong)address, (int)size, (jlong)value); (*env)->CallStaticVoidMethod(env, clz, invokeReadWriteCallbacks, (jlong)eng, (int)type, (jlong)address, (int)size, (jlong)value);
break; break;
} }
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
@ -171,7 +171,7 @@ static void cb_hookmem(uch handle, uc_mem_type type,
// @value: value of data being written to memory, or irrelevant if type = READ. // @value: value of data being written to memory, or irrelevant if type = READ.
// @user_data: user data passed to tracing APIs // @user_data: user data passed to tracing APIs
// @return: return true to continue, or false to stop program (due to invalid memory). // @return: return true to continue, or false to stop program (due to invalid memory).
static bool cb_eventmem(uch handle, uc_mem_type type, static bool cb_eventmem(ucengine *eng, uc_mem_type type,
uint64_t address, int size, int64_t value, void *user_data) { uint64_t address, int size, int64_t value, void *user_data) {
JNIEnv *env; JNIEnv *env;
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL); (*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
@ -179,7 +179,7 @@ static bool cb_eventmem(uch handle, uc_mem_type type,
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
return false; return false;
} }
jboolean res = (*env)->CallStaticBooleanMethod(env, clz, invokeMemInvalidCallbacks, (jlong)handle, (int)type, (jlong)address, (int)size, (jlong)value); jboolean res = (*env)->CallStaticBooleanMethod(env, clz, invokeMemInvalidCallbacks, (jlong)eng, (int)type, (jlong)address, (int)size, (jlong)value);
(*cachedJVM)->DetachCurrentThread(cachedJVM); (*cachedJVM)->DetachCurrentThread(cachedJVM);
return res; return res;
} }
@ -193,16 +193,16 @@ static void throwException(JNIEnv *env, uc_err err) {
} }
} }
static uch getHandle(JNIEnv *env, jobject self) { static ucengine *getEngine(JNIEnv *env, jobject self) {
static int haveFid = 0; static int haveFid = 0;
static jfieldID fid; static jfieldID fid;
if (haveFid == 0) { if (haveFid == 0) {
//cache the field id //cache the field id
jclass clazz = (*env)->GetObjectClass(env, self); jclass clazz = (*env)->GetObjectClass(env, self);
fid = (*env)->GetFieldID(env, clazz, "handle", "J"); fid = (*env)->GetFieldID(env, clazz, "eng", "J");
haveFid = 1; haveFid = 1;
} }
return (uch)(*env)->GetLongField(env, self, fid); return (ucengine *)(*env)->GetLongField(env, self, fid);
} }
/* /*
@ -212,12 +212,12 @@ static uch getHandle(JNIEnv *env, jobject self) {
*/ */
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_open JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_open
(JNIEnv *env, jobject self, jint arch, jint mode) { (JNIEnv *env, jobject self, jint arch, jint mode) {
uch handle = -1; ucengine *eng = NULL;
uc_err err = uc_open((uc_arch)arch, (uc_mode)mode, &handle); uc_err err = uc_open((uc_arch)arch, (uc_mode)mode, &eng);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
return (jlong)handle; return (jlong)eng;
} }
/* /*
@ -247,8 +247,8 @@ JNIEXPORT jboolean JNICALL Java_unicorn_Unicorn_arch_1supported
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_close JNIEXPORT void JNICALL Java_unicorn_Unicorn_close
(JNIEnv *env, jobject self) { (JNIEnv *env, jobject self) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
uc_close(&handle); uc_close(eng);
} }
/* /*
@ -258,8 +258,8 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_close
*/ */
JNIEXPORT jint JNICALL Java_unicorn_Unicorn_errno JNIEXPORT jint JNICALL Java_unicorn_Unicorn_errno
(JNIEnv *env, jobject self) { (JNIEnv *env, jobject self) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
return (jint)uc_errno(handle); return (jint)uc_errno(eng);
} }
/* /*
@ -281,9 +281,9 @@ JNIEXPORT jstring JNICALL Java_unicorn_Unicorn_strerror
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_reg_1write JNIEXPORT void JNICALL Java_unicorn_Unicorn_reg_1write
(JNIEnv *env, jobject self, jint regid, jbyteArray value) { (JNIEnv *env, jobject self, jint regid, jbyteArray value) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
jbyte *array = (*env)->GetByteArrayElements(env, value, NULL); jbyte *array = (*env)->GetByteArrayElements(env, value, NULL);
uc_err err = uc_reg_write(handle, (int)regid, (void *)array); uc_err err = uc_reg_write(eng, (int)regid, (void *)array);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -297,10 +297,10 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_reg_1write
*/ */
JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_reg_1read JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_reg_1read
(JNIEnv *env, jobject self, jint regid, jint regsz) { (JNIEnv *env, jobject self, jint regid, jint regsz) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
jbyteArray regval = (*env)->NewByteArray(env, (jsize)regsz); jbyteArray regval = (*env)->NewByteArray(env, (jsize)regsz);
jbyte *array = (*env)->GetByteArrayElements(env, regval, NULL); jbyte *array = (*env)->GetByteArrayElements(env, regval, NULL);
uc_err err = uc_reg_read(handle, (int)regid, (void *)array); uc_err err = uc_reg_read(eng, (int)regid, (void *)array);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -316,10 +316,10 @@ JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_reg_1read
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write
(JNIEnv *env , jobject self, jlong address, jbyteArray bytes) { (JNIEnv *env , jobject self, jlong address, jbyteArray bytes) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL); jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL);
jsize size = (*env)->GetArrayLength(env, bytes); jsize size = (*env)->GetArrayLength(env, bytes);
uc_err err = uc_mem_write(handle, (uint64_t)address, (uint8_t *)array, (size_t)size); uc_err err = uc_mem_write(eng, (uint64_t)address, (uint8_t *)array, (size_t)size);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
@ -335,11 +335,11 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write
*/ */
JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read
(JNIEnv *env, jobject self, jlong address, jlong size) { (JNIEnv *env, jobject self, jlong address, jlong size) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
jbyteArray bytes = (*env)->NewByteArray(env, (jsize)size); jbyteArray bytes = (*env)->NewByteArray(env, (jsize)size);
jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL); jbyte *array = (*env)->GetByteArrayElements(env, bytes, NULL);
uc_err err = uc_mem_read(handle, (uint64_t)address, (uint8_t *)array, (size_t)size); uc_err err = uc_mem_read(eng, (uint64_t)address, (uint8_t *)array, (size_t)size);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -354,9 +354,9 @@ JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1start JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1start
(JNIEnv *env, jobject self, jlong begin, jlong until, jlong timeout, jlong count) { (JNIEnv *env, jobject self, jlong begin, jlong until, jlong timeout, jlong count) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
uc_err err = uc_emu_start(handle, (uint64_t)begin, (uint64_t)until, (uint64_t)timeout, (size_t)count); uc_err err = uc_emu_start(eng, (uint64_t)begin, (uint64_t)until, (uint64_t)timeout, (size_t)count);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -369,9 +369,9 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1start
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1stop JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1stop
(JNIEnv *env, jobject self) { (JNIEnv *env, jobject self) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
uc_err err = uc_emu_stop(handle); uc_err err = uc_emu_stop(eng);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -383,24 +383,24 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1stop
* Signature: (JI)J * Signature: (JI)J
*/ */
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI
(JNIEnv *env, jclass clz, jlong handle, jint type) { (JNIEnv *env, jclass clz, jlong eng, jint type) {
uch h2 = 0; uchook hh = 0;
uc_err err = 0; uc_err err = 0;
switch (type) { switch (type) {
case UC_HOOK_INTR: // Hook all interrupt events case UC_HOOK_INTR: // Hook all interrupt events
if (invokeInterruptCallbacks == 0) { if (invokeInterruptCallbacks == 0) {
invokeInterruptCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeInterruptCallbacks", "(JI)V"); invokeInterruptCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeInterruptCallbacks", "(JI)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookintr, env); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookintr, env);
break; break;
case UC_HOOK_MEM_INVALID: // Hook for all invalid memory access events case UC_HOOK_MEM_INVALID: // Hook for all invalid memory access events
if (invokeMemInvalidCallbacks == 0) { if (invokeMemInvalidCallbacks == 0) {
invokeMemInvalidCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeMemInvalidCallbacks", "(JIJIJ)Z"); invokeMemInvalidCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeMemInvalidCallbacks", "(JIJIJ)Z");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_eventmem, env); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_eventmem, env);
break; break;
} }
return (jlong)h2; return (jlong)hh;
} }
/* /*
@ -409,8 +409,8 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI
* Signature: (JII)J * Signature: (JII)J
*/ */
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
(JNIEnv *env, jclass clz, jlong handle, jint type, jint arg1) { (JNIEnv *env, jclass clz, jlong eng, jint type, jint arg1) {
uch h2 = 0; uchook hh = 0;
uc_err err = 0; uc_err err = 0;
switch (type) { switch (type) {
case UC_HOOK_INSN: // Hook a particular instruction case UC_HOOK_INSN: // Hook a particular instruction
@ -419,22 +419,22 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
if (invokeOutCallbacks == 0) { if (invokeOutCallbacks == 0) {
invokeOutCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeOutCallbacks", "(JIII)V"); invokeOutCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeOutCallbacks", "(JIII)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_insn_out, env, arg1); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_insn_out, env, arg1);
case UC_X86_INS_IN: case UC_X86_INS_IN:
if (invokeInCallbacks == 0) { if (invokeInCallbacks == 0) {
invokeInCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeInCallbacks", "(JII)I"); invokeInCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeInCallbacks", "(JII)I");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_insn_in, env, arg1); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_insn_in, env, arg1);
case UC_X86_INS_SYSENTER: case UC_X86_INS_SYSENTER:
case UC_X86_INS_SYSCALL: case UC_X86_INS_SYSCALL:
if (invokeSyscallCallbacks == 0) { if (invokeSyscallCallbacks == 0) {
invokeSyscallCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeSyscallCallbacks", "(J)V"); invokeSyscallCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeSyscallCallbacks", "(J)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_insn_syscall, env, arg1); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_insn_syscall, env, arg1);
} }
break; break;
} }
return (jlong)h2; return (jlong)hh;
} }
/* /*
@ -443,42 +443,42 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
* Signature: (JIJJ)J * Signature: (JIJJ)J
*/ */
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ
(JNIEnv *env, jclass clz, jlong handle, jint type, jlong arg1, jlong arg2) { (JNIEnv *env, jclass clz, jlong eng, jint type, jlong arg1, jlong arg2) {
uch h2 = 0; uchook hh = 0;
uc_err err = 0; uc_err err = 0;
switch (type) { switch (type) {
case UC_HOOK_CODE: // Hook a range of code case UC_HOOK_CODE: // Hook a range of code
if (invokeCodeCallbacks == 0) { if (invokeCodeCallbacks == 0) {
invokeCodeCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeCodeCallbacks", "(JJI)V"); invokeCodeCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeCodeCallbacks", "(JJI)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookcode, env, arg1, arg2); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookcode, env, arg1, arg2);
break; break;
case UC_HOOK_BLOCK: // Hook basic blocks case UC_HOOK_BLOCK: // Hook basic blocks
if (invokeBlockCallbacks == 0) { if (invokeBlockCallbacks == 0) {
invokeBlockCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeBlockCallbacks", "(JJI)V"); invokeBlockCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeBlockCallbacks", "(JJI)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookblock, env, arg1, arg2); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookblock, env, arg1, arg2);
break; break;
case UC_HOOK_MEM_READ: // Hook all memory read events. case UC_HOOK_MEM_READ: // Hook all memory read events.
if (invokeReadCallbacks == 0) { if (invokeReadCallbacks == 0) {
invokeReadCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeReadCallbacks", "(JJI)V"); invokeReadCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeReadCallbacks", "(JJI)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookmem, env, arg1, arg2); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookmem, env, arg1, arg2);
break; break;
case UC_HOOK_MEM_WRITE: // Hook all memory write events. case UC_HOOK_MEM_WRITE: // Hook all memory write events.
if (invokeWriteCallbacks == 0) { if (invokeWriteCallbacks == 0) {
invokeWriteCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeWriteCallbacks", "(JJIJ)V"); invokeWriteCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeWriteCallbacks", "(JJIJ)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookmem, env, arg1, arg2); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookmem, env, arg1, arg2);
break; break;
case UC_HOOK_MEM_READ_WRITE: // Hook all memory accesses (either READ or WRITE). case UC_HOOK_MEM_READ_WRITE: // Hook all memory accesses (either READ or WRITE).
if (invokeReadWriteCallbacks == 0) { if (invokeReadWriteCallbacks == 0) {
invokeReadWriteCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeReadWriteCallbacks", "(JIJIJ)V"); invokeReadWriteCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeReadWriteCallbacks", "(JIJIJ)V");
} }
err = uc_hook_add((uch)handle, &h2, (uc_hook_t)type, cb_hookmem, env, arg1, arg2); err = uc_hook_add((ucengine*)eng, &hh, (uc_hook_t)type, cb_hookmem, env, arg1, arg2);
break; break;
} }
return (jlong)h2; return (jlong)hh;
} }
/* /*
@ -487,13 +487,12 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ
* Signature: (J)V * Signature: (J)V
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
(JNIEnv *env, jobject self, jlong hook) { (JNIEnv *env, jobject self, jlong hh) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
uch h2 = (uch)hook;
//**** TODO remove hook from any internal hook tables as well //**** TODO remove hook from any internal hook tables as well
uc_err err = uc_hook_del(handle, &h2); uc_err err = uc_hook_del(eng, (uchook)hh);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }
@ -506,9 +505,39 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
*/ */
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms) { (JNIEnv *env, jobject self, jlong address, jlong size, jint perms) {
uch handle = getHandle(env, self); ucengine *eng = getEngine(env, self);
uc_err err = uc_mem_map(handle, (uint64_t)address, (size_t)size, (uint32_t)perms); uc_err err = uc_mem_map(eng, (uint64_t)address, (size_t)size, (uint32_t)perms);
if (err != UC_ERR_OK) {
throwException(env, err);
}
}
/*
* Class: unicorn_Unicorn
* Method: mem_unmap
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1unmap
(JNIEnv *env, jobject self, jlong address, jlong size) {
ucengine *eng = getEngine(env, self);
uc_err err = uc_mem_unmap(eng, (uint64_t)address, (size_t)size);
if (err != UC_ERR_OK) {
throwException(env, err);
}
}
/*
* Class: unicorn_Unicorn
* Method: mem_protect
* Signature: (JJI)V
*/
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1protect
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms) {
ucengine *eng = getEngine(env, self);
uc_err err = uc_mem_protect(eng, (uint64_t)address, (size_t)size, (uint32_t)perms);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
throwException(env, err); throwException(env, err);
} }

View file

@ -175,6 +175,7 @@ struct uc_struct {
bool block_full; bool block_full;
MemoryRegion **mapped_blocks; MemoryRegion **mapped_blocks;
uint32_t mapped_block_count; uint32_t mapped_block_count;
uint32_t mapped_block_cache_index;
void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c) void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c)
uint32_t target_page_size; uint32_t target_page_size;
uint32_t target_page_align; uint32_t target_page_align;

View file

@ -49,10 +49,13 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
{ {
int i; int i;
target_ulong addr; target_ulong addr;
//make sure all pages associated with the MemoryRegion are flushed // Make sure all pages associated with the MemoryRegion are flushed
// Only need to do this if we are in a running state
if (uc->current_cpu) {
for (addr = mr->addr; addr < mr->end; addr += uc->target_page_size) { for (addr = mr->addr; addr < mr->end; addr += uc->target_page_size) {
tlb_flush_page(uc->current_cpu, addr); tlb_flush_page(uc->current_cpu, addr);
} }
}
mr->enabled = false; mr->enabled = false;
memory_region_del_subregion(get_system_memory(uc), mr); memory_region_del_subregion(get_system_memory(uc), mr);

View file

@ -1,5 +1,5 @@
CFLAGS += -I../include CFLAGS += -I../include
LDFLAGS = -L.. -lunicorn 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
@ -7,10 +7,16 @@ TESTS += block_test
TESTS += ro_mem_test nr_mem_test TESTS += ro_mem_test nr_mem_test
TESTS += timeout_segfault TESTS += timeout_segfault
TESTS += rep_movsb TESTS += rep_movsb
TESTS += mem_unmap
TESTS += mem_protect
TESTS += mem_exec
all: $(TESTS) all: $(TESTS)
clean: clean:
rm -f $(TESTS) rm -f $(TESTS)
%: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
.PHONY: all clean .PHONY: all clean

View file

@ -1,5 +1,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -13,7 +14,7 @@ static int count = 1;
// @size: size of machine instruction being executed // @size: size of machine instruction being executed
// @user_data: user data passed to tracing APIs. // @user_data: user data passed to tracing APIs.
void cb_hookblock(ucengine *uc, uint64_t address, uint32_t size, void *user_data) { void cb_hookblock(ucengine *uc, uint64_t address, uint32_t size, void *user_data) {
fprintf(stderr, "# >>> Tracing basic block at 0x%llx, block size = 0x%x\n", address, size); fprintf(stderr, "# >>> Tracing basic block at 0x%"PRIx64", block size = 0x%x\n", address, size);
if (address != 0x1000000 && address != 0x1000200) { if (address != 0x1000000 && address != 0x1000200) {
fprintf(stderr, "not ok %d - address != 0x1000000 && address != 0x1000200\n", count++); fprintf(stderr, "not ok %d - address != 0x1000000 && address != 0x1000200\n", count++);
_exit(1); _exit(1);

View file

@ -7,7 +7,7 @@ LIBNAME = unicorn
# Find GLIB # Find GLIB
ifndef GLIB ifndef GLIB
GLIB = `pkg-config --libs glib-2.0` GLIB = $(shell pkg-config --libs glib-2.0)
endif endif
UNICORN_DEP_LIBS_STATIC += -lpthread -lm $(GLIB) UNICORN_DEP_LIBS_STATIC += -lpthread -lm $(GLIB)
@ -97,9 +97,6 @@ endif
ifneq (,$(findstring x86,$(UNICORN_ARCHS))) ifneq (,$(findstring x86,$(UNICORN_ARCHS)))
SOURCES += sample_x86.c SOURCES += sample_x86.c
SOURCES += shellcode.c SOURCES += shellcode.c
SOURCES += mem_unmap.c
SOURCES += mem_protect.c
SOURCES += mem_exec.c
endif endif
ifneq (,$(findstring m68k,$(UNICORN_ARCHS))) ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
SOURCES += sample_m68k.c SOURCES += sample_m68k.c
@ -114,8 +111,7 @@ all: $(BINARY)
clean: clean:
rm -rf *.o $(OBJS_ELF) $(BINARY) $(SAMPLEDIR)/*.exe $(SAMPLEDIR)/*.static $(OBJDIR)/lib$(LIBNAME)* $(OBJDIR)/$(LIBNAME)* rm -rf *.o $(OBJS_ELF) $(BINARY) $(SAMPLEDIR)/*.exe $(SAMPLEDIR)/*.static $(OBJDIR)/lib$(LIBNAME)* $(OBJDIR)/$(LIBNAME)*
rm -rf libunicorn*.so libunicorn*.lib libunicorn*.dylib unicorn*.dll unicorn*.lib rm -rf libunicorn*.so libunicorn*.lib libunicorn*.dylib unicorn*.dll unicorn*.lib
rm -rf sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k \ rm -rf sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k shellcode
shellcode mem_unmap mem_protect mem_exec
$(BINARY): $(OBJS) $(BINARY): $(OBJS)

11
uc.c
View file

@ -798,9 +798,18 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
{ {
unsigned int i; unsigned int i;
for(i = 0; i < uc->mapped_block_count; i++) { // try with the cache index first
i = uc->mapped_block_cache_index;
if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end)
return uc->mapped_blocks[i]; return uc->mapped_blocks[i];
for(i = 0; i < uc->mapped_block_count; i++) {
if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) {
// cache this index for the next query
uc->mapped_block_cache_index = i;
return uc->mapped_blocks[i];
}
} }
// not found // not found