mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-01 23:21:08 +00:00
Merge remote-tracking branch 'upstream/master' into hook_mem_constants_documentation
This commit is contained in:
commit
84a374e876
|
@ -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
|
||||
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_STATIC: build static 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
|
||||
make.sh, as followings.
|
||||
|
|
4
Makefile
4
Makefile
|
@ -204,11 +204,11 @@ config:
|
|||
qemu/config-host.h-timestamp:
|
||||
ifeq ($(UNICORN_DEBUG),yes)
|
||||
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
|
||||
else
|
||||
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
|
||||
endif
|
||||
|
||||
|
|
|
@ -395,7 +395,7 @@ public class SampleNetworkAuditing {
|
|||
Unicorn mu = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||
|
||||
// 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
|
||||
mu.mem_write(ADDRESS, code);
|
||||
|
|
|
@ -51,7 +51,7 @@ public class Sample_arm {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, THUMB_CODE);
|
||||
|
|
|
@ -79,7 +79,7 @@ public class Sample_arm64 {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, ARM_CODE);
|
||||
|
|
|
@ -95,7 +95,7 @@ public class Sample_m68k {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, M68K_CODE);
|
||||
|
|
|
@ -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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, MIPS_CODE_EL);
|
||||
|
|
|
@ -79,7 +79,7 @@ public class Sample_sparc {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, SPARC_CODE);
|
||||
|
|
|
@ -64,23 +64,22 @@ public class Sample_x86 {
|
|||
// callback for tracing basic blocks
|
||||
// callback for tracing instruction
|
||||
private static class MyBlockHook implements BlockHook {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// callback for tracing instruction
|
||||
private static class MyCodeHook implements CodeHook {
|
||||
public void hook(Unicorn u, long address, int size, Object user_data) {
|
||||
System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size);
|
||||
|
||||
byte eflags[] = u.reg_read(Unicorn.UC_X86_REG_EFLAGS, 4);
|
||||
System.out.printf(">>> --- EFLAGS is 0x%x\n", toInt(eflags));
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// u.emu_stop();
|
||||
System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size);
|
||||
|
||||
byte eflags[] = u.reg_read(Unicorn.UC_X86_REG_EFLAGS, 4);
|
||||
System.out.printf(">>> --- EFLAGS is 0x%x\n", toInt(eflags));
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// u.emu_stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
address, size, value);
|
||||
// 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;
|
||||
}
|
||||
|
@ -102,13 +101,13 @@ public class Sample_x86 {
|
|||
// callback for tracing instruction
|
||||
private static class MyCode64Hook implements CodeHook {
|
||||
public void hook(Unicorn u, long address, int size, Object user_data) {
|
||||
byte[] r_rip = u.reg_read(Unicorn.UC_X86_REG_RIP, 8);
|
||||
System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size);
|
||||
System.out.printf(">>> RIP is 0x%x\n", toInt(r_rip));
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(handle);
|
||||
byte[] r_rip = u.reg_read(Unicorn.UC_X86_REG_RIP, 8);
|
||||
System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size);
|
||||
System.out.printf(">>> RIP is 0x%x\n", toInt(r_rip));
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,55 +128,53 @@ public class Sample_x86 {
|
|||
// callback for IN instruction (X86).
|
||||
// this returns the data read from the port
|
||||
private static class MyInHook implements InHook {
|
||||
public int hook(Unicorn u, int port, int size, Object user_data)
|
||||
{
|
||||
byte[] r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
|
||||
public int hook(Unicorn u, int port, int size, Object user_data) {
|
||||
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));
|
||||
|
||||
switch(size) {
|
||||
case 1:
|
||||
// read 1 byte to AL
|
||||
return 0xf1;
|
||||
case 2:
|
||||
// read 2 byte to AX
|
||||
return 0xf2;
|
||||
case 4:
|
||||
// read 4 byte to EAX
|
||||
return 0xf4;
|
||||
}
|
||||
return 0;
|
||||
switch(size) {
|
||||
case 1:
|
||||
// read 1 byte to AL
|
||||
return 0xf1;
|
||||
case 2:
|
||||
// read 2 byte to AX
|
||||
return 0xf2;
|
||||
case 4:
|
||||
// read 4 byte to EAX
|
||||
return 0xf4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// callback for OUT instruction (X86).
|
||||
private static class MyOutHook implements OutHook {
|
||||
public void hook(Unicorn u, int port, int size, int value, Object user) {
|
||||
byte[] eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
|
||||
byte[] tmp = null;
|
||||
System.out.printf("--- writing to port 0x%x, size: %d, value: 0x%x, address: 0x%x\n", port, size, value, toInt(eip));
|
||||
byte[] eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
|
||||
byte[] tmp = null;
|
||||
System.out.printf("--- writing to port 0x%x, size: %d, value: 0x%x, address: 0x%x\n", port, size, value, toInt(eip));
|
||||
|
||||
// confirm that value is indeed the value of AL/AX/EAX
|
||||
switch(size) {
|
||||
default:
|
||||
return; // should never reach this
|
||||
case 1:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_AL, 1);
|
||||
break;
|
||||
case 2:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_AX, 2);
|
||||
break;
|
||||
case 4:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_EAX, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
// confirm that value is indeed the value of AL/AX/EAX
|
||||
switch(size) {
|
||||
default:
|
||||
return; // should never reach this
|
||||
case 1:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_AL, 1);
|
||||
break;
|
||||
case 2:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_AX, 2);
|
||||
break;
|
||||
case 4:
|
||||
tmp = u.reg_read(Unicorn.UC_X86_REG_EAX, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
System.out.printf("--- register value = 0x%x\n", toInt(tmp));
|
||||
System.out.printf("--- register value = 0x%x\n", toInt(tmp));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_i386()
|
||||
{
|
||||
static void test_i386() {
|
||||
byte r_ecx[] = {(byte)0x34, (byte)0x12, 0, 0}; //0x1234; // ECX register
|
||||
byte r_edx[] = {(byte)0x90, (byte)0x78, 0, 0}; //0x7890; // EDX register
|
||||
|
||||
|
@ -188,19 +185,19 @@ public class Sample_x86 {
|
|||
try {
|
||||
uc = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||
} catch (UnicornException uex) {
|
||||
System.out.println("Failed on uc_open() with error returned: " + uex);
|
||||
return;
|
||||
System.out.println("Failed on uc_open() with error returned: " + uex);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
try {
|
||||
uc.mem_write(ADDRESS, X86_CODE32);
|
||||
uc.mem_write(ADDRESS, X86_CODE32);
|
||||
} catch (UnicornException uex) {
|
||||
System.out.println("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
System.out.println("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
|
@ -251,7 +248,7 @@ public class Sample_x86 {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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
|
||||
u.mem_write(0, X86_CODE16);
|
||||
|
|
|
@ -121,7 +121,7 @@ public class Shellcode {
|
|||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||
|
||||
// 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
|
||||
u.mem_write(ADDRESS, X86_CODE32_SELF);
|
||||
|
|
|
@ -25,11 +25,7 @@ import java.util.*;
|
|||
|
||||
public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const {
|
||||
|
||||
// Scales to calculate timeout on microsecond unit
|
||||
// 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 eng;
|
||||
|
||||
private long blockHandle = 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
|
||||
* 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 size The size of the basic block being executed
|
||||
* @see hook_add, unicorn.BlockHook
|
||||
*/
|
||||
private static void invokeBlockCallbacks(long handle, long address, int size) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeBlockCallbacks(long eng, long address, int size) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.blockList) {
|
||||
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
|
||||
* 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
|
||||
* @see hook_add, unicorn.InterruptHook
|
||||
*/
|
||||
private static void invokeInterruptCallbacks(long handle, int intno) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeInterruptCallbacks(long eng, int intno) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.intrList) {
|
||||
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
|
||||
* 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 size The size of the instruction being executed
|
||||
* @see hook_add, unicorn.CodeHook
|
||||
*/
|
||||
private static void invokeCodeCallbacks(long handle, long address, int size) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeCodeCallbacks(long eng, long address, int size) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.codeList) {
|
||||
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
|
||||
* 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 address Address of instruction being executed
|
||||
* @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).
|
||||
* @see hook_add, unicorn.MemoryInvalidHook
|
||||
*/
|
||||
private static boolean invokeMemInvalidCallbacks(long handle, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static boolean invokeMemInvalidCallbacks(long eng, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
boolean result = true;
|
||||
if (u != null) {
|
||||
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
|
||||
* 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 size Size of data being read
|
||||
* @see hook_add, unicorn.ReadHook
|
||||
*/
|
||||
private static void invokeReadCallbacks(long handle, long address, int size) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeReadCallbacks(long eng, long address, int size) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.readList) {
|
||||
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
|
||||
* 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 size Size of data being read
|
||||
* @param value value being written
|
||||
* @see hook_add, unicorn.WriteHook
|
||||
*/
|
||||
private static void invokeWriteCallbacks(long handle, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeWriteCallbacks(long eng, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.writeList) {
|
||||
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
|
||||
* 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 address Address of instruction being executed
|
||||
* @param size Size of data being read
|
||||
* @param value value being written (if applicable)
|
||||
* @see hook_add, unicorn.ReadWriteHook
|
||||
*/
|
||||
private static void invokeReadWriteCallbacks(long handle, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeReadWriteCallbacks(long eng, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.readWriteList) {
|
||||
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
|
||||
* 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 size Data size (1/2/4) to be read from this port
|
||||
* @return Data supplied from the input port
|
||||
* @see hook_add, unicorn.InHook
|
||||
*/
|
||||
private static int invokeInCallbacks(long handle, int port, int size) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static int invokeInCallbacks(long eng, int port, int size) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
int result = 0;
|
||||
if (u != null) {
|
||||
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
|
||||
* 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 size Data size (1/2/4) to be written to this port
|
||||
* @see hook_add, unicorn.OutHook
|
||||
*/
|
||||
private static void invokeOutCallbacks(long handle, int port, int size, int value) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeOutCallbacks(long eng, int port, int size, int value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
int result = 0;
|
||||
if (u != null) {
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
private static void invokeSyscallCallbacks(long handle) {
|
||||
Unicorn u = unicorns.get(handle);
|
||||
private static void invokeSyscallCallbacks(long eng) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
int result = 0;
|
||||
if (u != null) {
|
||||
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 long handle;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
handle = open(arch, mode);
|
||||
unicorns.put(handle, this);
|
||||
eng = open(arch, mode);
|
||||
unicorns.put(eng, this);
|
||||
allLists.add(blockList);
|
||||
allLists.add(intrList);
|
||||
allLists.add(codeList);
|
||||
|
@ -323,7 +317,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*
|
||||
*/
|
||||
protected void finalize() {
|
||||
unicorns.remove(handle);
|
||||
unicorns.remove(eng);
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -346,7 +340,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
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;
|
||||
|
@ -423,32 +417,32 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
/**
|
||||
* 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
|
||||
* @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.
|
||||
*
|
||||
* @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 arg1 Additional varargs argument
|
||||
* @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.
|
||||
*
|
||||
* @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 arg1 First additional varargs argument
|
||||
* @param arg2 Second additional varargs argument
|
||||
* @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
|
||||
|
@ -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 {
|
||||
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));
|
||||
}
|
||||
|
@ -477,7 +471,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*/
|
||||
public void hook_add(InterruptHook callback, Object user_data) throws UnicornException {
|
||||
if (interruptHandle == 0) {
|
||||
interruptHandle = registerHook(handle, UC_HOOK_INTR);
|
||||
interruptHandle = registerHook(eng, UC_HOOK_INTR);
|
||||
}
|
||||
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 {
|
||||
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));
|
||||
}
|
||||
|
@ -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 {
|
||||
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));
|
||||
}
|
||||
|
@ -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 {
|
||||
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));
|
||||
}
|
||||
|
@ -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 {
|
||||
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));
|
||||
}
|
||||
|
@ -559,7 +553,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*/
|
||||
public void hook_add(MemoryInvalidHook callback, Object user_data) throws UnicornException {
|
||||
if (memInvalidHandle == 0) {
|
||||
memInvalidHandle = registerHook(handle, UC_HOOK_MEM_INVALID);
|
||||
memInvalidHandle = registerHook(eng, UC_HOOK_MEM_INVALID);
|
||||
}
|
||||
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 {
|
||||
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));
|
||||
}
|
||||
|
@ -587,7 +581,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*/
|
||||
public void hook_add(OutHook callback, Object user_data) throws UnicornException {
|
||||
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));
|
||||
}
|
||||
|
@ -601,7 +595,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*/
|
||||
public void hook_add(SyscallHook callback, Object user_data) throws UnicornException {
|
||||
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));
|
||||
}
|
||||
|
@ -622,8 +616,26 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
|||
*
|
||||
* @param address Base address of the memory range
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -31,31 +31,32 @@ public interface UnicornConst {
|
|||
public static final int UC_MODE_MIPS32R6 = 64;
|
||||
public static final int UC_MODE_V9 = 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_MIPS64 = 8;
|
||||
|
||||
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_HANDLE = 3;
|
||||
public static final int UC_ERR_UCH = 4;
|
||||
public static final int UC_ERR_MODE = 5;
|
||||
public static final int UC_ERR_VERSION = 6;
|
||||
public static final int UC_ERR_MEM_READ = 7;
|
||||
public static final int UC_ERR_MEM_WRITE = 8;
|
||||
public static final int UC_ERR_CODE_INVALID = 9;
|
||||
public static final int UC_ERR_HOOK = 10;
|
||||
public static final int UC_ERR_INSN_INVALID = 11;
|
||||
public static final int UC_ERR_MAP = 12;
|
||||
public static final int UC_ERR_MEM_WRITE_NW = 13;
|
||||
public static final int UC_ERR_MEM_READ_NR = 14;
|
||||
public static final int UC_ERR_MODE = 4;
|
||||
public static final int UC_ERR_VERSION = 5;
|
||||
public static final int UC_ERR_MEM_READ = 6;
|
||||
public static final int UC_ERR_MEM_WRITE = 7;
|
||||
public static final int UC_ERR_CODE_INVALID = 8;
|
||||
public static final int UC_ERR_HOOK = 9;
|
||||
public static final int UC_ERR_INSN_INVALID = 10;
|
||||
public static final int UC_ERR_MAP = 11;
|
||||
public static final int UC_ERR_WRITE_PROT = 12;
|
||||
public static final int UC_ERR_READ_PROT = 13;
|
||||
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_WRITE = 17;
|
||||
public static final int UC_MEM_READ_WRITE = 18;
|
||||
public static final int UC_MEM_WRITE_NW = 19;
|
||||
public static final int UC_MEM_READ_NR = 20;
|
||||
public static final int UC_MEM_NX = 21;
|
||||
public static final int UC_MEM_WRITE_PROT = 19;
|
||||
public static final int UC_MEM_READ_PROT = 20;
|
||||
public static final int UC_MEM_EXEC_PROT = 21;
|
||||
public static final int UC_HOOK_INTR = 32;
|
||||
public static final int UC_HOOK_INSN = 33;
|
||||
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_WRITE = 38;
|
||||
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_WRITE = 2;
|
||||
public static final int UC_PROT_EXEC = 4;
|
||||
public static final int UC_PROT_ALL = 7;
|
||||
|
||||
}
|
||||
|
|
|
@ -52,14 +52,14 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
|||
// @address: address where the code is being executed
|
||||
// @size: size of machine instruction being executed
|
||||
// @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;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
// @size: size of machine instruction being executed
|
||||
// @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;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Callback function for tracing interrupts (for uc_hook_intr())
|
||||
// @intno: interrupt number
|
||||
// @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;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return;
|
||||
}
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeInterruptCallbacks, (jlong)handle, (int)intno);
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeInterruptCallbacks, (jlong)eng, (int)intno);
|
||||
(*cachedJVM)->DetachCurrentThread(cachedJVM);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ static void cb_hookintr(uch handle, uint32_t intno, void *user_data) {
|
|||
// @port: port number
|
||||
// @size: data size (1/2/4) to be read from this port
|
||||
// @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;
|
||||
uint32_t res = 0;
|
||||
(*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)) {
|
||||
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);
|
||||
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
|
||||
// @size: data size (1/2/4) 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;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return;
|
||||
}
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeSyscallCallbacks, (jlong)handle);
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeSyscallCallbacks, (jlong)eng);
|
||||
(*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
|
||||
// @value: value of data being written to memory, or irrelevant if type = READ.
|
||||
// @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) {
|
||||
JNIEnv *env;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
|
@ -152,13 +152,13 @@ static void cb_hookmem(uch handle, uc_mem_type type,
|
|||
}
|
||||
switch (type) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
(*cachedJVM)->DetachCurrentThread(cachedJVM);
|
||||
|
@ -171,15 +171,15 @@ static void cb_hookmem(uch handle, uc_mem_type type,
|
|||
// @value: value of data being written to memory, or irrelevant if type = READ.
|
||||
// @user_data: user data passed to tracing APIs
|
||||
// @return: return true to continue, or false to stop program (due to invalid memory).
|
||||
static bool cb_eventmem(uch handle, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data) {
|
||||
static bool cb_eventmem(ucengine *eng, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data) {
|
||||
JNIEnv *env;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
jclass clz = (*env)->FindClass(env, "unicorn/Unicorn");
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
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);
|
||||
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 jfieldID fid;
|
||||
if (haveFid == 0) {
|
||||
//cache the field id
|
||||
jclass clazz = (*env)->GetObjectClass(env, self);
|
||||
fid = (*env)->GetFieldID(env, clazz, "handle", "J");
|
||||
fid = (*env)->GetFieldID(env, clazz, "eng", "J");
|
||||
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
|
||||
(JNIEnv *env, jobject self, jint arch, jint mode) {
|
||||
uch handle = -1;
|
||||
uc_err err = uc_open((uc_arch)arch, (uc_mode)mode, &handle);
|
||||
ucengine *eng = NULL;
|
||||
uc_err err = uc_open((uc_arch)arch, (uc_mode)mode, &eng);
|
||||
if (err != UC_ERR_OK) {
|
||||
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
|
||||
(JNIEnv *env, jobject self) {
|
||||
uch handle = getHandle(env, self);
|
||||
uc_close(&handle);
|
||||
ucengine *eng = getEngine(env, self);
|
||||
uc_close(eng);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -258,8 +258,8 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_close
|
|||
*/
|
||||
JNIEXPORT jint JNICALL Java_unicorn_Unicorn_errno
|
||||
(JNIEnv *env, jobject self) {
|
||||
uch handle = getHandle(env, self);
|
||||
return (jint)uc_errno(handle);
|
||||
ucengine *eng = getEngine(env, self);
|
||||
return (jint)uc_errno(eng);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -281,9 +281,9 @@ JNIEXPORT jstring JNICALL Java_unicorn_Unicorn_strerror
|
|||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_reg_1write
|
||||
(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);
|
||||
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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -297,10 +297,10 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_reg_1write
|
|||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_reg_1read
|
||||
(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);
|
||||
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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -316,10 +316,10 @@ JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_reg_1read
|
|||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write
|
||||
(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);
|
||||
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) {
|
||||
throwException(env, err);
|
||||
|
@ -335,11 +335,11 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1write
|
|||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read
|
||||
(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);
|
||||
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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -354,9 +354,9 @@ JNIEXPORT jbyteArray JNICALL Java_unicorn_Unicorn_mem_1read
|
|||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1start
|
||||
(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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -369,9 +369,9 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1start
|
|||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1stop
|
||||
(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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -383,24 +383,24 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_emu_1stop
|
|||
* Signature: (JI)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI
|
||||
(JNIEnv *env, jclass clz, jlong handle, jint type) {
|
||||
uch h2 = 0;
|
||||
(JNIEnv *env, jclass clz, jlong eng, jint type) {
|
||||
uchook hh = 0;
|
||||
uc_err err = 0;
|
||||
switch (type) {
|
||||
case UC_HOOK_INTR: // Hook all interrupt events
|
||||
if (invokeInterruptCallbacks == 0) {
|
||||
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;
|
||||
case UC_HOOK_MEM_INVALID: // Hook for all invalid memory access events
|
||||
if (invokeMemInvalidCallbacks == 0) {
|
||||
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;
|
||||
}
|
||||
return (jlong)h2;
|
||||
return (jlong)hh;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -409,8 +409,8 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI
|
|||
* Signature: (JII)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
|
||||
(JNIEnv *env, jclass clz, jlong handle, jint type, jint arg1) {
|
||||
uch h2 = 0;
|
||||
(JNIEnv *env, jclass clz, jlong eng, jint type, jint arg1) {
|
||||
uchook hh = 0;
|
||||
uc_err err = 0;
|
||||
switch (type) {
|
||||
case UC_HOOK_INSN: // Hook a particular instruction
|
||||
|
@ -419,22 +419,22 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
|
|||
if (invokeOutCallbacks == 0) {
|
||||
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:
|
||||
if (invokeInCallbacks == 0) {
|
||||
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_SYSCALL:
|
||||
if (invokeSyscallCallbacks == 0) {
|
||||
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;
|
||||
}
|
||||
return (jlong)h2;
|
||||
return (jlong)hh;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -443,42 +443,42 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JII
|
|||
* Signature: (JIJJ)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ
|
||||
(JNIEnv *env, jclass clz, jlong handle, jint type, jlong arg1, jlong arg2) {
|
||||
uch h2 = 0;
|
||||
(JNIEnv *env, jclass clz, jlong eng, jint type, jlong arg1, jlong arg2) {
|
||||
uchook hh = 0;
|
||||
uc_err err = 0;
|
||||
switch (type) {
|
||||
case UC_HOOK_CODE: // Hook a range of code
|
||||
if (invokeCodeCallbacks == 0) {
|
||||
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;
|
||||
case UC_HOOK_BLOCK: // Hook basic blocks
|
||||
if (invokeBlockCallbacks == 0) {
|
||||
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;
|
||||
case UC_HOOK_MEM_READ: // Hook all memory read events.
|
||||
if (invokeReadCallbacks == 0) {
|
||||
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;
|
||||
case UC_HOOK_MEM_WRITE: // Hook all memory write events.
|
||||
if (invokeWriteCallbacks == 0) {
|
||||
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;
|
||||
case UC_HOOK_MEM_READ_WRITE: // Hook all memory accesses (either READ or WRITE).
|
||||
if (invokeReadWriteCallbacks == 0) {
|
||||
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;
|
||||
}
|
||||
return (jlong)h2;
|
||||
return (jlong)hh;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -487,13 +487,12 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ
|
|||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
|
||||
(JNIEnv *env, jobject self, jlong hook) {
|
||||
uch handle = getHandle(env, self);
|
||||
uch h2 = (uch)hook;
|
||||
(JNIEnv *env, jobject self, jlong hh) {
|
||||
ucengine *eng = getEngine(env, self);
|
||||
|
||||
//**** 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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
@ -506,9 +505,39 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
|
|||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
|
||||
(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) {
|
||||
throwException(env, err);
|
||||
}
|
||||
|
|
|
@ -175,6 +175,7 @@ struct uc_struct {
|
|||
bool block_full;
|
||||
MemoryRegion **mapped_blocks;
|
||||
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)
|
||||
uint32_t target_page_size;
|
||||
uint32_t target_page_align;
|
||||
|
|
|
@ -49,9 +49,12 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
|
|||
{
|
||||
int i;
|
||||
target_ulong addr;
|
||||
//make sure all pages associated with the MemoryRegion are flushed
|
||||
for (addr = mr->addr; addr < mr->end; addr += uc->target_page_size) {
|
||||
tlb_flush_page(uc->current_cpu, addr);
|
||||
// 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) {
|
||||
tlb_flush_page(uc->current_cpu, addr);
|
||||
}
|
||||
}
|
||||
mr->enabled = false;
|
||||
memory_region_del_subregion(get_system_memory(uc), mr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
CFLAGS += -I../include
|
||||
LDFLAGS = -L.. -lunicorn
|
||||
LDFLAGS += ../libunicorn.a $(shell pkg-config --libs glib-2.0) -lpthread -lm
|
||||
|
||||
TESTS = map_crash map_write
|
||||
TESTS += sigill sigill2
|
||||
|
@ -7,10 +7,16 @@ TESTS += block_test
|
|||
TESTS += ro_mem_test nr_mem_test
|
||||
TESTS += timeout_segfault
|
||||
TESTS += rep_movsb
|
||||
TESTS += mem_unmap
|
||||
TESTS += mem_protect
|
||||
TESTS += mem_exec
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
clean:
|
||||
rm -f $(TESTS)
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
.PHONY: all clean
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
@ -13,7 +14,7 @@ static int count = 1;
|
|||
// @size: size of machine instruction being executed
|
||||
// @user_data: user data passed to tracing APIs.
|
||||
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) {
|
||||
fprintf(stderr, "not ok %d - address != 0x1000000 && address != 0x1000200\n", count++);
|
||||
_exit(1);
|
||||
|
|
|
@ -7,7 +7,7 @@ LIBNAME = unicorn
|
|||
|
||||
# Find GLIB
|
||||
ifndef GLIB
|
||||
GLIB = `pkg-config --libs glib-2.0`
|
||||
GLIB = $(shell pkg-config --libs glib-2.0)
|
||||
endif
|
||||
|
||||
UNICORN_DEP_LIBS_STATIC += -lpthread -lm $(GLIB)
|
||||
|
@ -97,9 +97,6 @@ endif
|
|||
ifneq (,$(findstring x86,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_x86.c
|
||||
SOURCES += shellcode.c
|
||||
SOURCES += mem_unmap.c
|
||||
SOURCES += mem_protect.c
|
||||
SOURCES += mem_exec.c
|
||||
endif
|
||||
ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_m68k.c
|
||||
|
@ -114,8 +111,7 @@ all: $(BINARY)
|
|||
clean:
|
||||
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 sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k \
|
||||
shellcode mem_unmap mem_protect mem_exec
|
||||
rm -rf sample_x86 sample_arm sample_arm64 sample_mips sample_sparc sample_ppc sample_m68k shellcode
|
||||
|
||||
$(BINARY): $(OBJS)
|
||||
|
||||
|
|
11
uc.c
11
uc.c
|
@ -798,9 +798,18 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
|||
{
|
||||
unsigned int 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)
|
||||
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)
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue