Update Java samples to match C samples.

Also add all of the samples as Java tests, referencing the output of the C
samples.
This commit is contained in:
Robert Xiao 2023-05-14 16:23:49 -07:00
parent 3739c7e3e0
commit 4f563490e2
25 changed files with 3884 additions and 906 deletions

View File

@ -29,7 +29,7 @@ package samples;
import unicorn.*;
import java.util.*;
public class SampleNetworkAuditing {
public class SampleNetworkAuditing implements UnicornConst, X86Const {
public static long next_id = 3;
public static final int SIZE_REG = 4;
@ -67,11 +67,11 @@ public class SampleNetworkAuditing {
if (intno != 0x80) {
return;
}
long eax = uc.reg_read(Unicorn.UC_X86_REG_EAX);
long ebx = uc.reg_read(Unicorn.UC_X86_REG_EBX);
long ecx = uc.reg_read(Unicorn.UC_X86_REG_ECX);
long edx = uc.reg_read(Unicorn.UC_X86_REG_EDX);
long eip = uc.reg_read(Unicorn.UC_X86_REG_EIP);
long eax = uc.reg_read(UC_X86_REG_EAX);
long ebx = uc.reg_read(UC_X86_REG_EBX);
long ecx = uc.reg_read(UC_X86_REG_ECX);
long edx = uc.reg_read(UC_X86_REG_EDX);
long eip = uc.reg_read(UC_X86_REG_EIP);
// System.out.printf(">>> INTERRUPT %d\n", toInt(eax));
@ -114,7 +114,7 @@ public class SampleNetworkAuditing {
String filename = read_string(uc, filename_addr);
long dummy_fd = get_id();
uc.reg_write(Unicorn.UC_X86_REG_EAX, dummy_fd);
uc.reg_write(UC_X86_REG_EAX, dummy_fd);
String msg = String.format(
"open file (filename=%s flags=%d mode=%d) with fd(%d)",
@ -133,8 +133,8 @@ public class SampleNetworkAuditing {
System.out.printf(">>> SYS_DUP2 oldfd=%d newfd=%d\n", ebx, ecx);
} else if (eax == 102) { // sys_socketcall
// ref: http://www.skyfree.org/linux/kernel_network/socket.html
long call = uc.reg_read(Unicorn.UC_X86_REG_EBX);
long args = uc.reg_read(Unicorn.UC_X86_REG_ECX);
long call = uc.reg_read(UC_X86_REG_EBX);
long args = uc.reg_read(UC_X86_REG_ECX);
// int sys_socketcall(int call, unsigned long *args)
if (call == 1) { // sys_socket
@ -147,7 +147,7 @@ public class SampleNetworkAuditing {
toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG));
long dummy_fd = get_id();
uc.reg_write(Unicorn.UC_X86_REG_EAX, dummy_fd);
uc.reg_write(UC_X86_REG_EAX, dummy_fd);
if (family == 2) { // AF_INET
String msg =
@ -437,16 +437,16 @@ public class SampleNetworkAuditing {
System.out.printf("Emulate i386 code\n");
try {
// Initialize emulator in X86-32bit mode
Unicorn mu = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
Unicorn mu = new Unicorn(UC_ARCH_X86, UC_MODE_32);
// map 2MB memory for this emulation
mu.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
mu.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
mu.mem_write(ADDRESS, code);
// initialize stack
mu.reg_write(Unicorn.UC_X86_REG_ESP, ADDRESS + 0x200000L);
mu.reg_write(UC_X86_REG_ESP, ADDRESS + 0x200000L);
// handle interrupt ourself
mu.hook_add(new MyInterruptHook(), null);

View File

@ -5,111 +5,117 @@
package samples;
import java.util.Arrays;
import unicorn.*;
public class Sample_arm {
public class Sample_arm implements UnicornConst, ArmConst {
// code to be emulated
public static final byte[] ARM_CODE =
{ 55, 0, (byte) 0xa0, (byte) 0xe3, 3, 16, 66, (byte) 0xe0 }; // mov r0, #0x37; sub r1, r2, r3
public static final byte[] THUMB_CODE = { (byte) 0x83, (byte) 0xb0 }; // sub sp, #0xc
/** code to be emulated {@code mov r0, #0x37; sub r1, r2, r3} */
// private static final byte[] ARM_CODE = Utils.hexToBytes("3700a0e3031042e0");
/** code to be emulated {@code nop} */
private static final byte[] ARM_CODE = Utils.hexToBytes("00f020e3");
// memory address where emulation starts
public static final int ADDRESS = 0x10000;
/** code to be emulated {@code sub sp, #0xc} */
private static final byte[] THUMB_CODE = Utils.hexToBytes("83b0");
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
/** code to be emulated
* <pre>
* cmp r2, r3
* it ne
* mov r2, #0x68
* mov r2, #0x4d
* </pre>
*/
private static final byte[] ARM_THUMB_COND_CODE =
Utils.hexToBytes("9a4214bf68224d22");
private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n", address,
size));
}
}
/** code to be emulated {@code mov r0, #0x37; sub r1, r2, r3} */
private static final byte[] ARM_CODE_EB =
Utils.hexToBytes("e3a00037e0421003");
/** code to be emulated {@code sub sp, #0xc} */
private static final byte[] THUMB_CODE_EB = Utils.hexToBytes("b083");
// callback for tracing instruction
private static class MyCodeHook implements CodeHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
/** {@code 0xf3ef8014 - mrs r0, control} */
private static final byte[] THUMB_CODE_MRS = Utils.hexToBytes("eff31480");
/** memory address where emulation starts */
private static final long ADDRESS = 0x10000;
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
}
}
address, size);
};
public static void test_arm() {
long r0 = 0x1234L; // R0 register
long r2 = 0x6789L; // R1 register
long r3 = 0x3333L; // R2 register
long r1; // R1 register
System.out.print("Emulate ARM code\n");
System.out.println("Emulate ARM code");
// Initialize emulator in ARM mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM);
Unicorn u = new Unicorn(UC_ARCH_ARM, UC_MODE_ARM);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, ARM_CODE);
// initialize machine registers
u.reg_write(Unicorn.UC_ARM_REG_R0, r0);
u.reg_write(Unicorn.UC_ARM_REG_R2, r2);
u.reg_write(Unicorn.UC_ARM_REG_R3, r3);
u.reg_write(UC_ARM_REG_R0, r0);
u.reg_write(UC_ARM_REG_R2, r2);
u.reg_write(UC_ARM_REG_R3, r3);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
u.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
u.hook_add(new MyCodeHook(), ADDRESS, ADDRESS, null);
u.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
u.emu_start(ADDRESS, ADDRESS + ARM_CODE.length, 0, 0);
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
System.out.println(">>> Emulation done. Below is the CPU context");
r0 = u.reg_read(Unicorn.UC_ARM_REG_R0);
r1 = u.reg_read(Unicorn.UC_ARM_REG_R1);
System.out.print(String.format(">>> R0 = 0x%x\n", r0));
System.out.print(String.format(">>> R1 = 0x%x\n", r1));
u.close();
System.out.format(">>> R0 = 0x%x\n", u.reg_read(UC_ARM_REG_R0));
System.out.format(">>> R1 = 0x%x\n", u.reg_read(UC_ARM_REG_R1));
}
public static void test_thumb() {
long sp = 0x1234L; // R0 register
System.out.print("Emulate THUMB code\n");
System.out.println("Emulate THUMB code");
// Initialize emulator in ARM mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_THUMB);
Unicorn u = new Unicorn(UC_ARCH_ARM, UC_MODE_THUMB);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, THUMB_CODE);
// initialize machine registers
u.reg_write(Unicorn.UC_ARM_REG_SP, sp);
u.reg_write(UC_ARM_REG_SP, sp);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
u.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
u.hook_add(new MyCodeHook(), ADDRESS, ADDRESS, null);
u.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
@ -117,17 +123,204 @@ public class Sample_arm {
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
System.out.format(">>> SP = 0x%x\n", u.reg_read(UC_ARM_REG_SP));
}
sp = u.reg_read(Unicorn.UC_ARM_REG_SP);
System.out.print(String.format(">>> SP = 0x%x\n", sp));
public static void test_armeb() {
long r0 = 0x1234L; // R0 register
long r2 = 0x6789L; // R1 register
long r3 = 0x3333L; // R2 register
u.close();
System.out.println("Emulate ARM Big-Endian code");
// Initialize emulator in ARM mode
Unicorn uc = new Unicorn(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, ARM_CODE_EB);
// initialize machine registers
uc.reg_write(UC_ARM_REG_R0, r0);
uc.reg_write(UC_ARM_REG_R2, r2);
uc.reg_write(UC_ARM_REG_R3, r3);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + ARM_CODE_EB.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> R0 = 0x%x\n", uc.reg_read(UC_ARM_REG_R0));
System.out.format(">>> R1 = 0x%x\n", uc.reg_read(UC_ARM_REG_R1));
}
public static void test_thumbeb() {
long sp = 0x1234L;
System.out.println("Emulate THUMB Big-Endian code");
// Initialize emulator in ARM mode
Unicorn uc =
new Unicorn(UC_ARCH_ARM, UC_MODE_THUMB + UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, THUMB_CODE_EB);
// initialize machine registers
uc.reg_write(UC_ARM_REG_SP, sp);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
// Note we start at ADDRESS | 1 to indicate THUMB mode.
uc.emu_start(ADDRESS | 1, ADDRESS + THUMB_CODE_EB.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> SP = 0x%x\n", uc.reg_read(UC_ARM_REG_SP));
}
public static void test_thumb_mrs() {
System.out.println("Emulate THUMB MRS instruction");
// 0xf3ef8014 - mrs r0, control
// Initialize emulator in ARM mode
Unicorn uc = new Unicorn(UC_ARCH_ARM, UC_MODE_THUMB);
// Setup the cpu model.
uc.ctl_set_cpu_model(UC_CPU_ARM_CORTEX_M33);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, THUMB_CODE_MRS);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
// Note we start at ADDRESS | 1 to indicate THUMB mode.
uc.emu_start(ADDRESS | 1, ADDRESS + THUMB_CODE_MRS.length, 0, 1);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
long pc = uc.reg_read(UC_ARM_REG_PC);
System.out.format(">>> PC = 0x%x\n", pc);
if (pc != ADDRESS + 4) {
System.out.format("Error, PC was 0x%x, expected was 0x%x.\n", pc,
ADDRESS + 4);
}
}
private static void test_thumb_ite_internal(boolean step, long[] r2r3) {
Unicorn uc = new Unicorn(UC_ARCH_ARM, UC_MODE_THUMB);
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
uc.mem_write(ADDRESS, ARM_THUMB_COND_CODE);
uc.reg_write(UC_ARM_REG_SP, 0x1234L);
uc.reg_write(UC_ARM_REG_R2, 0);
uc.reg_write(UC_ARM_REG_R3, 1);
if (!step) {
uc.emu_start(ADDRESS | 1, ADDRESS + ARM_THUMB_COND_CODE.length, 0,
0);
} else {
long addr = ADDRESS;
for (int i = 0; i < ARM_THUMB_COND_CODE.length / 2; i++) {
uc.emu_start(addr | 1, ADDRESS + ARM_THUMB_COND_CODE.length, 0,
1);
addr = uc.reg_read(UC_ARM_REG_PC);
}
}
r2r3[0] = uc.reg_read(UC_ARM_REG_R2);
r2r3[1] = uc.reg_read(UC_ARM_REG_R3);
}
public static void test_thumb_ite() {
long[] r2r3 = new long[2];
long[] step_r2r3 = new long[2];
System.out.println(
"Emulate a THUMB ITE block as a whole or per instruction.");
// Run once.
System.out.println("Running the entire binary.");
test_thumb_ite_internal(false, r2r3);
System.out.format(">>> R2: %d\n", r2r3[0]);
System.out.format(">>> R3: %d\n\n", r2r3[1]);
// Step each instruction.
System.out.println("Running the binary one instruction at a time.");
test_thumb_ite_internal(true, step_r2r3);
System.out.format(">>> R2: %d\n", step_r2r3[0]);
System.out.format(">>> R3: %d\n\n", step_r2r3[1]);
if (!Arrays.equals(r2r3, step_r2r3)) {
System.out.println("Failed with ARM ITE blocks stepping!");
}
}
public static void test_read_sctlr() {
System.out.println("Read the SCTLR register.");
Unicorn uc = new Unicorn(UC_ARCH_ARM, UC_MODE_ARM);
// SCTLR. See arm reference.
Arm_CP reg = new Arm_CP(15, 0, 0, 1, 0, 0, 0);
long val = (Long) uc.reg_read(UC_ARM_REG_CP_REG, reg);
System.out.format(">>> SCTLR = 0x%x\n", val & 0xffffffffL);
System.out.format(">>> SCTLR.IE = %d\n", (val >> 31) & 1);
System.out.format(">>> SCTLR.B = %d\n", (val >> 7) & 1);
}
public static void main(String args[]) {
test_arm();
System.out.print("==========================\n");
test_thumb();
System.out.print("==========================\n");
test_armeb();
System.out.print("==========================\n");
test_thumbeb();
System.out.print("==========================\n");
test_thumb_mrs();
System.out.print("==========================\n");
test_thumb_ite();
System.out.print("==========================\n");
test_read_sctlr();
}
}

View File

@ -26,94 +26,262 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package samples;
import java.util.Arrays;
import unicorn.*;
public class Sample_arm64 {
public class Sample_arm64 implements UnicornConst, Arm64Const {
// code to be emulated
public static final byte[] ARM_CODE = { -85, 1, 15, -117 }; // add x11, x13, x15
/** code to be emulated {@code str w11, [x13], #0; ldrb w15, [x13], #0} */
private static final byte[] ARM64_CODE =
Utils.hexToBytes("ab0500b8af054038");
/** code to be emulated {@code str w11, [x13]; ldrb w15, [x13]} */
//private static final byte[] ARM64_CODE_EB = Utils.hexToBytes("b80005ab384005af"); // str w11, [x13];
private static final byte[] ARM64_CODE_EB = ARM64_CODE;
/** code to be emulated {@code mrs x2, tpidrro_el0} */
private static final byte[] ARM64_MRS_CODE = Utils.hexToBytes("62d03bd5");
/** code to be emulated {@code paciza x1} */
private static final byte[] ARM64_PAC_CODE = Utils.hexToBytes("e123c1da");
// memory address where emulation starts
public static final int ADDRESS = 0x10000;
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
// callback for tracing basic blocks
private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
">>> 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.print(String.format(
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
}
address, size);
};
public static void test_arm64_mem_fetch() {
// msr x0, CurrentEL
byte[] shellcode0 = { 64, 66, 56, (byte) 213 };
// .text:00000000004002C0 LDR X1, [SP,#arg_0]
byte[] shellcode = { (byte) 0xE1, 0x03, 0x40, (byte) 0xF9 };
long shellcode_address = 0x4002C0L;
long data_address = 0x10000000000000L;
System.out.format(
">>> Emulate ARM64 fetching stack data from high address %x\n",
data_address);
// Initialize emulator in ARM mode
Unicorn uc = new Unicorn(UC_ARCH_ARM64, UC_MODE_ARM);
uc.mem_map(data_address, 0x30000, UC_PROT_ALL);
uc.mem_map(0x400000, 0x1000, UC_PROT_ALL);
uc.reg_write(UC_ARM64_REG_SP, data_address);
byte[] data = new byte[8];
Arrays.fill(data, (byte) 0xc8);
uc.mem_write(data_address, data);
uc.mem_write(shellcode_address, shellcode0);
uc.mem_write(shellcode_address + 4, shellcode);
uc.emu_start(shellcode_address, shellcode_address + 4, 0, 0);
long x0 = uc.reg_read(UC_ARM64_REG_X0);
System.out.format(">>> x0(Exception Level)=%x\n", x0 >> 2);
uc.emu_start(shellcode_address + 4, shellcode_address + 8, 0, 0);
long x1 = uc.reg_read(UC_ARM64_REG_X1);
System.out.format(">>> X1 = 0x%x\n", x1);
}
public static void test_arm64() {
long x11 = 0x12345678; // X11 register
long x13 = 0x10000 + 0x8; // X13 register
long x15 = 0x33; // X15 register
long x11 = 0x1234L; // X11 register
long x13 = 0x6789L; // X13 register
long x15 = 0x3333L; // X15 register
System.out.print("Emulate ARM64 code\n");
System.out.println("Emulate ARM64 code");
// Initialize emulator in ARM mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM);
Unicorn uc = new Unicorn(UC_ARCH_ARM64, UC_MODE_ARM);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, ARM_CODE);
uc.mem_write(ADDRESS, ARM64_CODE);
// initialize machine registers
u.reg_write(Unicorn.UC_ARM64_REG_X11, x11);
u.reg_write(Unicorn.UC_ARM64_REG_X13, x13);
u.reg_write(Unicorn.UC_ARM64_REG_X15, x15);
uc.reg_write(UC_ARM64_REG_X11, x11);
uc.reg_write(UC_ARM64_REG_X13, x13);
uc.reg_write(UC_ARM64_REG_X15, x15);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
u.hook_add(new MyCodeHook(), ADDRESS, ADDRESS, null);
uc.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
u.emu_start(ADDRESS, ADDRESS + ARM_CODE.length, 0, 0);
uc.emu_start(ADDRESS, ADDRESS + ARM64_CODE.length, 0, 0);
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.println(">>> As little endian, X15 should be 0x78:");
System.out.format(">>> X15 = 0x%x\n", uc.reg_read(UC_ARM64_REG_X15));
}
x11 = u.reg_read(Unicorn.UC_ARM64_REG_X11);
System.out.print(String.format(">>> X11 = 0x%x\n", x11));
public static void test_arm64eb() {
long x11 = 0x12345678; // X11 register
long x13 = 0x10000 + 0x8; // X13 register
long x15 = 0x33; // X15 register
u.close();
System.out.println("Emulate ARM64 Big-Endian code");
// Initialize emulator in ARM mode
Unicorn uc =
new Unicorn(UC_ARCH_ARM64, UC_MODE_ARM + UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, ARM64_CODE_EB);
// initialize machine registers
uc.reg_write(UC_ARM64_REG_X11, x11);
uc.reg_write(UC_ARM64_REG_X13, x13);
uc.reg_write(UC_ARM64_REG_X15, x15);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + ARM64_CODE_EB.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.println(">>> As big endian, X15 should be 0x78:");
System.out.format(">>> X15 = 0x%x\n", uc.reg_read(UC_ARM64_REG_X15));
}
public static void test_arm64_sctlr() {
long val;
System.out.println("Read the SCTLR register.");
Unicorn uc =
new Unicorn(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN | UC_MODE_ARM);
// SCTLR_EL1. See arm reference.
Arm64_CP reg = new Arm64_CP(1, 0, 3, 0, 0);
val = (long) uc.reg_read(UC_ARM64_REG_CP_REG, reg);
System.out.format(">>> SCTLR_EL1 = 0x%x\n", val);
reg.op1 = 0b100;
val = (long) uc.reg_read(UC_ARM64_REG_CP_REG, reg);
System.out.format(">>> SCTLR_EL2 = 0x%x\n", val);
}
private static final Arm64SysHook hook_mrs =
(uc, reg, cp_reg, user_data) -> {
System.out
.println(">>> Hook MSR instruction. Write 0x114514 to X2.");
uc.reg_write(reg, 0x114514L);
// Skip
return 1;
};
public static void test_arm64_hook_mrs() {
System.out.println("Hook MRS instruction.");
Unicorn uc =
new Unicorn(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN | UC_MODE_ARM);
uc.mem_map(0x1000, 0x1000, UC_PROT_ALL);
uc.mem_write(0x1000, ARM64_MRS_CODE);
uc.hook_add(hook_mrs, UC_ARM64_INS_MRS, 1, 0, null);
uc.emu_start(0x1000, 0x1000 + ARM64_MRS_CODE.length, 0, 0);
System.out.format(">>> X2 = 0x%x\n", uc.reg_read(UC_ARM64_REG_X2));
}
public static void test_arm64_pac() {
long x1 = 0x0000aaaabbbbccccL;
System.out.println("Try ARM64 PAC");
// Initialize emulator in ARM mode
Unicorn uc = new Unicorn(UC_ARCH_ARM64, UC_MODE_ARM);
uc.ctl_set_cpu_model(UC_CPU_ARM64_MAX);
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
uc.mem_write(ADDRESS, ARM64_PAC_CODE);
uc.reg_write(UC_ARM64_REG_X1, x1);
/** Initialize PAC support **/
Arm64_CP reg;
// SCR_EL3
reg = new Arm64_CP(1, 1, 3, 6, 0);
reg.val = (Long) uc.reg_read(UC_ARM64_REG_CP_REG, reg);
// NS && RW && API
reg.val |= (1 | (1L << 10) | (1L << 17));
uc.reg_write(UC_ARM64_REG_CP_REG, reg);
// SCTLR_EL1
reg = new Arm64_CP(1, 0, 3, 0, 0);
reg.val = (Long) uc.reg_read(UC_ARM64_REG_CP_REG, reg);
// EnIA && EnIB
reg.val |= (1L << 31) | (1L << 30);
uc.reg_write(UC_ARM64_REG_CP_REG, reg);
// HCR_EL2
reg = new Arm64_CP(1, 1, 3, 4, 0);
reg.val = (Long) uc.reg_read(UC_ARM64_REG_CP_REG, reg);
// HCR.API
reg.val |= (1L << 41);
uc.reg_write(UC_ARM64_REG_CP_REG, reg);
/** Check that PAC worked **/
uc.emu_start(ADDRESS, ADDRESS + ARM64_PAC_CODE.length, 0, 0);
long new_x1 = uc.reg_read(UC_ARM64_REG_X1);
System.out.format("X1 = 0x%x\n", new_x1);
if (new_x1 == x1) {
System.out.println("FAIL: No PAC tag added!");
} else {
// Expect 0x1401aaaabbbbccccULL with the default key
System.out.println("SUCCESS: PAC tag found.");
}
}
public static void main(String args[]) {
test_arm64_mem_fetch();
System.out.println("-------------------------");
test_arm64();
System.out.println("-------------------------");
test_arm64eb();
System.out.println("-------------------------");
test_arm64_sctlr();
System.out.println("-------------------------");
test_arm64_hook_mrs();
System.out.println("-------------------------");
test_arm64_pac();
}
}

View File

@ -0,0 +1,159 @@
package samples;
import java.util.Arrays;
import unicorn.*;
public class Sample_ctl implements UnicornConst, X86Const {
/** Code to be emulated
* <pre>
* cmp eax, 0;
* jg lb;
* inc eax;
* nop;
* lb:
* inc ebx;
* nop;
* </pre>
*/
private static final byte[] X86_JUMP_CODE =
Utils.hexToBytes("83f8007f0240904390");
/** memory address where emulation starts */
private static final long ADDRESS = 0x10000;
public static void test_uc_ctl_read() {
System.out.println("Reading some properties by uc_ctl.");
// Initialize emulator in X86-32bit mode
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_32);
// Let's query some properties by uc_ctl.
int mode = uc.ctl_get_mode();
int arch = uc.ctl_get_arch();
long timeout = uc.ctl_get_timeout();
int pagesize = uc.ctl_get_page_size();
System.out.format(">>> mode = %d, arch = %d, timeout=%d, pagesize=%d\n",
mode, arch, timeout, pagesize);
}
private static final EdgeGeneratedHook trace_new_edge =
(uc, cur, prev, data) -> {
System.out.format(">>> Getting a new edge from 0x%x to 0x%x.\n",
prev.pc + prev.size - 1, cur.pc);
};
public static void test_uc_ctl_exits() {
long r_eax, r_ebx;
long exits[] = { ADDRESS + 6, ADDRESS + 8 };
System.out.println("Using multiple exits by uc_ctl.");
// Initialize emulator in X86-32bit mode
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_32);
uc.mem_map(ADDRESS, 0x1000, UC_PROT_ALL);
// Write our code to the memory.
uc.mem_write(ADDRESS, X86_JUMP_CODE);
// We trace if any new edge is generated.
uc.hook_add(trace_new_edge, 1, 0, null);
// Enable multiple exits.
uc.ctl_exits_enabled(true);
uc.ctl_set_exits(exits);
// This should stop at ADDRESS + 6 and increase eax, even thouhg we don't
// provide an exit.
uc.emu_start(ADDRESS, 0, 0, 0);
r_eax = uc.reg_read(UC_X86_REG_EAX);
r_ebx = uc.reg_read(UC_X86_REG_EBX);
System.out.format(
">>> eax = %d and ebx = %d after the first emulation\n",
r_eax, r_ebx);
// This should stop at ADDRESS + 8, even though we don't provide an exit.
uc.emu_start(ADDRESS, 0, 0, 0);
r_eax = uc.reg_read(UC_X86_REG_EAX);
r_ebx = uc.reg_read(UC_X86_REG_EBX);
System.out.format(
">>> eax = %d and ebx = %d after the second emulation\n",
r_eax, r_ebx);
}
private static final int TB_COUNT = 8;
private static final int TCG_MAX_INSNS = 512; // from tcg.h
private static final int CODE_LEN = TB_COUNT * TCG_MAX_INSNS;
private static double time_emulation(Unicorn uc, long start, long end) {
long t1 = System.nanoTime();
uc.emu_start(start, end, 0, 0);
long t2 = System.nanoTime();
return (t2 - t1) / 1000000.0;
}
public static void test_uc_ctl_tb_cache() {
byte[] code = new byte[CODE_LEN];
double standard, cached, evicted;
System.out.println(
"Controlling the TB cache in a finer granularity by uc_ctl.");
// Fill the code buffer with NOP.
Arrays.fill(code, (byte) 0x90);
// Initialize emulator in X86-32bit mode
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_32);
uc.mem_map(ADDRESS, 0x10000, UC_PROT_ALL);
// Write our code to the memory.
uc.mem_write(ADDRESS, code);
// We trace if any new edge is generated.
// Note: In this sample, there is only **one** basic block while muliple
// translation blocks is generated due to QEMU tcg buffer limit. In this
// case, we don't consider it as a new edge.
uc.hook_add(trace_new_edge, 1, 0, null);
// Do emulation without any cache.
standard = time_emulation(uc, ADDRESS, ADDRESS + CODE_LEN);
// Now we request cache for all TBs.
for (int i = 0; i < TB_COUNT; i++) {
TranslationBlock tb =
uc.ctl_request_cache(ADDRESS + i * TCG_MAX_INSNS);
System.out.format(
">>> TB is cached at 0x%x which has %d instructions with %d bytes.\n",
tb.pc, tb.icount, tb.size);
}
// Do emulation with all TB cached.
cached = time_emulation(uc, ADDRESS, ADDRESS + CODE_LEN);
// Now we clear cache for all TBs.
for (int i = 0; i < TB_COUNT; i++) {
uc.ctl_remove_cache(ADDRESS + i * TCG_MAX_INSNS,
ADDRESS + i * TCG_MAX_INSNS + 1);
}
// Do emulation with all TB cache evicted.
evicted = time_emulation(uc, ADDRESS, ADDRESS + CODE_LEN);
System.out.format(
">>> Run time: First time: %fms, Cached: %fms, Cache evicted: %fms\n",
standard, cached, evicted);
}
public static final void main(String[] args) {
test_uc_ctl_read();
System.out.println("====================");
test_uc_ctl_exits();
System.out.println("====================");
test_uc_ctl_tb_cache();
}
}

View File

@ -28,7 +28,7 @@ package samples;
import unicorn.*;
public class Sample_m68k {
public class Sample_m68k implements UnicornConst, M68kConst {
// code to be emulated
public static final byte[] M68K_CODE = { 118, -19 }; // movq #-19, %d3
@ -36,41 +36,21 @@ public class Sample_m68k {
// memory address where emulation starts
public static final int ADDRESS = 0x10000;
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
// callback for tracing basic blocks
private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n", address,
size));
}
}
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> 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.print(String.format(
// callback for tracing instructions
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
}
}
address, size);
};
public static void test_m68k() {
long d0 = 0x0000L; // d0 data register
@ -97,42 +77,41 @@ public class Sample_m68k {
System.out.print("Emulate M68K code\n");
// Initialize emulator in M68K mode
Unicorn u =
new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN);
Unicorn u = new Unicorn(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, M68K_CODE);
// initialize machine registers
u.reg_write(Unicorn.UC_M68K_REG_D0, d0);
u.reg_write(Unicorn.UC_M68K_REG_D1, d1);
u.reg_write(Unicorn.UC_M68K_REG_D2, d2);
u.reg_write(Unicorn.UC_M68K_REG_D3, d3);
u.reg_write(Unicorn.UC_M68K_REG_D4, d4);
u.reg_write(Unicorn.UC_M68K_REG_D5, d5);
u.reg_write(Unicorn.UC_M68K_REG_D6, d6);
u.reg_write(Unicorn.UC_M68K_REG_D7, d7);
u.reg_write(UC_M68K_REG_D0, d0);
u.reg_write(UC_M68K_REG_D1, d1);
u.reg_write(UC_M68K_REG_D2, d2);
u.reg_write(UC_M68K_REG_D3, d3);
u.reg_write(UC_M68K_REG_D4, d4);
u.reg_write(UC_M68K_REG_D5, d5);
u.reg_write(UC_M68K_REG_D6, d6);
u.reg_write(UC_M68K_REG_D7, d7);
u.reg_write(Unicorn.UC_M68K_REG_A0, a0);
u.reg_write(Unicorn.UC_M68K_REG_A1, a1);
u.reg_write(Unicorn.UC_M68K_REG_A2, a2);
u.reg_write(Unicorn.UC_M68K_REG_A3, a3);
u.reg_write(Unicorn.UC_M68K_REG_A4, a4);
u.reg_write(Unicorn.UC_M68K_REG_A5, a5);
u.reg_write(Unicorn.UC_M68K_REG_A6, a6);
u.reg_write(Unicorn.UC_M68K_REG_A7, a7);
u.reg_write(UC_M68K_REG_A0, a0);
u.reg_write(UC_M68K_REG_A1, a1);
u.reg_write(UC_M68K_REG_A2, a2);
u.reg_write(UC_M68K_REG_A3, a3);
u.reg_write(UC_M68K_REG_A4, a4);
u.reg_write(UC_M68K_REG_A5, a5);
u.reg_write(UC_M68K_REG_A6, a6);
u.reg_write(UC_M68K_REG_A7, a7);
u.reg_write(Unicorn.UC_M68K_REG_PC, pc);
u.reg_write(Unicorn.UC_M68K_REG_SR, sr);
u.reg_write(UC_M68K_REG_PC, pc);
u.reg_write(UC_M68K_REG_SR, sr);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
u.hook_add(hook_block, 1, 0, null);
// tracing all instruction
u.hook_add(new MyCodeHook(), 1, 0, null);
u.hook_add(hook_code, 1, 0, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
@ -141,47 +120,37 @@ public class Sample_m68k {
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
d0 = u.reg_read(Unicorn.UC_M68K_REG_D0);
d1 = u.reg_read(Unicorn.UC_M68K_REG_D1);
d2 = u.reg_read(Unicorn.UC_M68K_REG_D2);
d3 = u.reg_read(Unicorn.UC_M68K_REG_D3);
d4 = u.reg_read(Unicorn.UC_M68K_REG_D4);
d5 = u.reg_read(Unicorn.UC_M68K_REG_D5);
d6 = u.reg_read(Unicorn.UC_M68K_REG_D6);
d7 = u.reg_read(Unicorn.UC_M68K_REG_D7);
d0 = u.reg_read(UC_M68K_REG_D0);
d1 = u.reg_read(UC_M68K_REG_D1);
d2 = u.reg_read(UC_M68K_REG_D2);
d3 = u.reg_read(UC_M68K_REG_D3);
d4 = u.reg_read(UC_M68K_REG_D4);
d5 = u.reg_read(UC_M68K_REG_D5);
d6 = u.reg_read(UC_M68K_REG_D6);
d7 = u.reg_read(UC_M68K_REG_D7);
a0 = u.reg_read(Unicorn.UC_M68K_REG_A0);
a1 = u.reg_read(Unicorn.UC_M68K_REG_A1);
a2 = u.reg_read(Unicorn.UC_M68K_REG_A2);
a3 = u.reg_read(Unicorn.UC_M68K_REG_A3);
a4 = u.reg_read(Unicorn.UC_M68K_REG_A4);
a5 = u.reg_read(Unicorn.UC_M68K_REG_A5);
a6 = u.reg_read(Unicorn.UC_M68K_REG_A6);
a7 = u.reg_read(Unicorn.UC_M68K_REG_A7);
a0 = u.reg_read(UC_M68K_REG_A0);
a1 = u.reg_read(UC_M68K_REG_A1);
a2 = u.reg_read(UC_M68K_REG_A2);
a3 = u.reg_read(UC_M68K_REG_A3);
a4 = u.reg_read(UC_M68K_REG_A4);
a5 = u.reg_read(UC_M68K_REG_A5);
a6 = u.reg_read(UC_M68K_REG_A6);
a7 = u.reg_read(UC_M68K_REG_A7);
pc = u.reg_read(Unicorn.UC_M68K_REG_PC);
sr = u.reg_read(Unicorn.UC_M68K_REG_SR);
pc = u.reg_read(UC_M68K_REG_PC);
sr = u.reg_read(UC_M68K_REG_SR);
System.out.print(String.format(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n",
a0, d0));
System.out.print(String.format(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n",
a1, d1));
System.out.print(String.format(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n",
a2, d2));
System.out.print(String.format(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n",
a3, d3));
System.out.print(String.format(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n",
a4, d4));
System.out.print(String.format(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n",
a5, d5));
System.out.print(String.format(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n",
a6, d6));
System.out.print(String.format(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n",
a7, d7));
System.out.print(String.format(">>> PC = 0x%x\n", pc));
System.out.print(String.format(">>> SR = 0x%x\n", sr));
u.close();
System.out.format(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0);
System.out.format(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1);
System.out.format(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n", a2, d2);
System.out.format(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n", a3, d3);
System.out.format(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n", a4, d4);
System.out.format(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n", a5, d5);
System.out.format(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n", a6, d6);
System.out.format(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n", a7, d7);
System.out.format(">>> PC = 0x%x\n", pc);
System.out.format(">>> SR = 0x%x\n", sr);
}
public static void main(String args[]) {

View File

@ -28,48 +28,30 @@ package samples;
import unicorn.*;
public class Sample_mips {
public class Sample_mips implements UnicornConst, MipsConst {
// code to be emulated
public static final byte[] MIPS_CODE_EB = { 52, 33, 52, 86 };
public static final byte[] MIPS_CODE_EL = { 86, 52, 33, 52 };
public static final byte[] MIPS_CODE_EB = { 52, 33, 52, 86 }; // ori $at, $at, 0x3456
public static final byte[] MIPS_CODE_EL = { 86, 52, 33, 52 }; // ori $at, $at, 0x3456
// memory address where emulation starts
public static final int ADDRESS = 0x10000;
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
// callback for tracing basic blocks
private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n", address,
size));
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.print(String.format(
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
address, size);
}
}
@ -77,20 +59,20 @@ public class Sample_mips {
long r1 = 0x6789L; // R1 register
System.out.print("Emulate MIPS code (big-endian)\n");
System.out.println("Emulate MIPS code (big-endian)");
// Initialize emulator in MIPS mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS,
Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_BIG_ENDIAN);
Unicorn u =
new Unicorn(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, MIPS_CODE_EB);
// initialize machine registers
u.reg_write(Unicorn.UC_MIPS_REG_1, r1);
u.reg_write(UC_MIPS_REG_1, r1);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
@ -103,32 +85,29 @@ public class Sample_mips {
u.emu_start(ADDRESS, ADDRESS + MIPS_CODE_EB.length, 0, 0);
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
System.out.println(">>> Emulation done. Below is the CPU context");
r1 = u.reg_read(Unicorn.UC_MIPS_REG_1);
System.out.print(String.format(">>> R1 = 0x%x\n", r1));
u.close();
r1 = u.reg_read(UC_MIPS_REG_1);
System.out.format(">>> R1 = 0x%x\n", r1);
}
public static void test_mips_el() {
long r1 = 0x6789L; // R1 register
System.out.print("===========================\n");
System.out.print("Emulate MIPS code (little-endian)\n");
System.out.println("Emulate MIPS code (little-endian)");
// Initialize emulator in MIPS mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS,
Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_LITTLE_ENDIAN);
Unicorn u = new Unicorn(UC_ARCH_MIPS,
UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, MIPS_CODE_EL);
// initialize machine registers
u.reg_write(Unicorn.UC_MIPS_REG_1, r1);
u.reg_write(UC_MIPS_REG_1, r1);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
@ -141,16 +120,15 @@ public class Sample_mips {
u.emu_start(ADDRESS, ADDRESS + MIPS_CODE_EL.length, 0, 0);
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
System.out.println(">>> Emulation done. Below is the CPU context");
r1 = u.reg_read(Unicorn.UC_MIPS_REG_1);
System.out.print(String.format(">>> R1 = 0x%x\n", r1));
u.close();
r1 = u.reg_read(UC_MIPS_REG_1);
System.out.format(">>> R1 = 0x%x\n", r1);
}
public static void main(String args[]) {
test_mips_eb();
System.out.println("===========================");
test_mips_el();
}
}

View File

@ -0,0 +1,224 @@
package samples;
import unicorn.*;
public class Sample_mmu implements UnicornConst, X86Const {
/** Code:
* <pre>
* mov rax, 57
* syscall
* test rax, rax
* jz child
* xor rax, rax
* mov rax, 60
* mov [0x4000], rax
* syscall
*
* child:
* xor rcx, rcx
* mov rcx, 42
* mov [0x4000], rcx
* mov rax, 60
* syscall
* </pre>
*/
private static final byte[] CODE = Utils.hexToBytes(
"B8390000000F054885C0740FB83C00000048890425004000000F05B92A00000048890C2500400000B83C0000000F05");
private static final MemHook mmu_write_callback =
(uc, type, address, size, value, user_data) -> {
System.out.format("write at 0x%x: 0x%x\n", address, value);
};
private static void x86_mmu_prepare_tlb(Unicorn uc, long vaddr,
long tlb_base) {
long cr0;
long cr4;
X86_MSR msr = new X86_MSR(0xC0000080);
long pml4o = ((vaddr & 0x00ff8000000000L) >> 39) * 8;
long pdpo = ((vaddr & 0x00007fc0000000L) >> 30) * 8;
long pdo = ((vaddr & 0x0000003fe00000L) >> 21) * 8;
long pml4e = (tlb_base + 0x1000L) | 1 | (1 << 2);
long pdpe = (tlb_base + 0x2000L) | 1 | (1 << 2);
long pde = (tlb_base + 0x3000L) | 1 | (1 << 2);
uc.mem_write(tlb_base + pml4o, Utils.toBytes(pml4e));
uc.mem_write(tlb_base + 0x1000 + pdpo, Utils.toBytes(pdpe));
uc.mem_write(tlb_base + 0x2000 + pdo, Utils.toBytes(pde));
uc.reg_write(UC_X86_REG_CR3, tlb_base);
cr0 = uc.reg_read(UC_X86_REG_CR0);
cr4 = uc.reg_read(UC_X86_REG_CR4);
msr.value = (Long) uc.reg_read(UC_X86_REG_MSR, msr);
cr0 |= 1; //enable protected mode
cr0 |= 1l << 31; //enable paging
cr4 |= 1l << 5; //enable physical address extension
msr.value |= 1l << 8; //enable long mode
uc.reg_write(UC_X86_REG_CR0, cr0);
uc.reg_write(UC_X86_REG_CR4, cr4);
uc.reg_write(UC_X86_REG_MSR, msr);
}
private static void x86_mmu_pt_set(Unicorn uc, long vaddr, long paddr,
long tlb_base) {
long pto = ((vaddr & 0x000000001ff000L) >> 12) * 8;
long pte = (paddr) | 1 | (1 << 2);
uc.mem_write(tlb_base + 0x3000 + pto, Utils.toBytes((int) pte));
}
private static SyscallHook x86_mmu_syscall_callback = (uc, userdata) -> {
boolean[] parent_done = (boolean[]) userdata;
long rax = uc.reg_read(UC_X86_REG_RAX);
switch ((int) rax) {
case 57:
/* fork */
break;
case 60:
/* exit */
parent_done[0] = true;
uc.emu_stop();
return;
default:
System.out.println("unknown syscall");
System.exit(1);
}
if (!parent_done[0]) {
rax = 27;
uc.reg_write(UC_X86_REG_RAX, rax);
uc.emu_stop();
}
};
public static void cpu_tlb() {
long tlb_base = 0x3000;
long rip;
boolean[] parent_done = { false };
System.out.println(
"Emulate x86 amd64 code with mmu enabled and switch mappings");
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_64);
uc.ctl_tlb_mode(UC_TLB_CPU);
Unicorn.Context context = uc.context_save();
uc.hook_add(x86_mmu_syscall_callback, UC_X86_INS_SYSCALL, 1, 0,
parent_done);
// Memory hooks are called after the mmu translation, so hook the physicall addresses
uc.hook_add(mmu_write_callback, UC_HOOK_MEM_WRITE, 0x1000, 0x3000,
null);
System.out.println("map code");
uc.mem_map(0x0, 0x1000, UC_PROT_ALL); // Code
uc.mem_write(0x0, CODE);
System.out.println("map parent memory");
uc.mem_map(0x1000, 0x1000, UC_PROT_ALL); // Parrent
System.out.println("map child memory");
uc.mem_map(0x2000, 0x1000, UC_PROT_ALL); // Child
System.out.println("map tlb memory");
uc.mem_map(tlb_base, 0x4000, UC_PROT_ALL); // TLB
System.out.println("set up the tlb");
x86_mmu_prepare_tlb(uc, 0x0, tlb_base);
x86_mmu_pt_set(uc, 0x2000, 0x0, tlb_base);
x86_mmu_pt_set(uc, 0x4000, 0x1000, tlb_base);
uc.ctl_flush_tlb();
System.out.println("run the parent");
uc.emu_start(0x2000, 0x0, 0, 0);
System.out.println("save the context for the child");
uc.context_update(context);
System.out.println("finish the parent");
rip = uc.reg_read(UC_X86_REG_RIP);
uc.emu_start(rip, 0x0, 0, 0);
System.out.println("restore the context for the child");
uc.context_restore(context);
x86_mmu_prepare_tlb(uc, 0x0, tlb_base);
x86_mmu_pt_set(uc, 0x4000, 0x2000, tlb_base);
uc.reg_write(UC_X86_REG_RAX, 0L);
uc.ctl_flush_tlb();
uc.emu_start(rip, 0x0, 0, 0);
long parent = Utils.toLong(uc.mem_read(0x1000, Long.BYTES));
long child = Utils.toLong(uc.mem_read(0x2000, Long.BYTES));
System.out.format("parent result == %d\n", parent);
System.out.format("child result == %d\n", child);
}
private static final TlbFillHook virtual_tlb_callback =
(uc, addr, type, user_data) -> {
boolean[] parent_done = (boolean[]) user_data;
System.out.format("tlb lookup for address: 0x%X\n", addr);
switch ((int) (addr & ~(0xfffL))) {
case 0x2000:
return 0x0L | UC_PROT_EXEC;
case 0x4000:
if (parent_done[0]) {
return (0x2000L) | UC_PROT_READ | UC_PROT_WRITE;
} else {
return (0x1000L) | UC_PROT_READ | UC_PROT_WRITE;
}
default:
return -1L;
}
};
public static void virtual_tlb() {
long rip;
boolean[] parent_done = { false };
System.out.println("Emulate x86 amd64 code with virtual mmu");
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_64);
uc.ctl_tlb_mode(UC_TLB_VIRTUAL);
Unicorn.Context context = uc.context_save();
uc.hook_add(x86_mmu_syscall_callback, UC_X86_INS_SYSCALL, 1, 0,
parent_done);
// Memory hooks are called after the mmu translation, so hook the physicall addresses
uc.hook_add(mmu_write_callback, UC_HOOK_MEM_WRITE, 0x1000, 0x3000,
null);
System.out.println("map code");
uc.mem_map(0x0, 0x1000, UC_PROT_ALL); // Code
uc.mem_write(0x0, CODE);
System.out.println("map parent memory");
uc.mem_map(0x1000, 0x1000, UC_PROT_ALL); // Parrent
System.out.println("map child memory");
uc.mem_map(0x2000, 0x1000, UC_PROT_ALL); // Child
uc.hook_add(virtual_tlb_callback, 1, 0, parent_done);
System.out.println("run the parent");
uc.emu_start(0x2000, 0x0, 0, 0);
System.out.println("save the context for the child");
uc.context_update(context);
System.out.println("finish the parent");
rip = uc.reg_read(UC_X86_REG_RIP);
uc.emu_start(rip, 0x0, 0, 0);
System.out.println("restore the context for the child");
uc.context_restore(context);
parent_done[0] = true;
uc.reg_write(UC_X86_REG_RAX, 0);
uc.ctl_flush_tlb();
uc.emu_start(rip, 0x0, 0, 0);
long parent = Utils.toLong(uc.mem_read(0x1000, Long.BYTES));
long child = Utils.toLong(uc.mem_read(0x2000, Long.BYTES));
System.out.format("parent result == %d\n", parent);
System.out.format("child result == %d\n", child);
}
public static final void main(String[] args) {
cpu_tlb();
System.out.println("------------------");
virtual_tlb();
}
}

View File

@ -0,0 +1,91 @@
/*
Java bindings for the Unicorn Emulator Engine
Copyright(c) 2023 Robert Xiao
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Sample code to demonstrate how to emulate S390X code */
package samples;
import unicorn.*;
public class Sample_ppc implements UnicornConst, PpcConst {
/** code to be emulated:
* {@code add r26, r6, r3}
*/
private static final byte[] CODE = Utils.hexToBytes("7F461A14");
// memory address where emulation starts
private static final long ADDRESS = 0x10000;
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
};
public static void test_ppc() {
long r3 = 0x1234; // R3 register
long r6 = 0x6789; // R6 register
long r26 = 0x8877; // R26 register (result)
System.out.println("Emulate PPC code");
Unicorn uc =
new Unicorn(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_PPC_REG_3, r3);
uc.reg_write(UC_PPC_REG_6, r6);
uc.reg_write(UC_PPC_REG_26, r26);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS + CODE.length, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> r26 = 0x%x\n", uc.reg_read(UC_PPC_REG_26));
}
public static final void main(String[] args) {
test_ppc();
}
}

View File

@ -0,0 +1,477 @@
/*
Java bindings for the Unicorn Emulator Engine
Copyright(c) 2023 Robert Xiao
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Sample code to demonstrate how to emulate S390X code */
package samples;
import unicorn.*;
public class Sample_riscv implements UnicornConst, RiscvConst {
/** code to be emulated:
* <pre>
* $ cstool riscv64 1305100093850502
* 0 13 05 10 00 addi a0, zero, 1
* 4 93 85 05 02 addi a1, a1, 0x20
* </pre>
*/
private static final byte[] CODE = Utils.hexToBytes("1305100093850502");
// memory address where emulation starts
private static final long ADDRESS = 0x10000;
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code3 =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
if (address == ADDRESS) {
System.out.println("stop emulation");
uc.emu_stop();
}
};
/*
00813823 sd s0,16(sp)
00000013 nop
*/
private static final byte[] CODE64 = Utils.hexToBytes("2338810013000000");
// 10000: 00008067 ret
// 10004: 8082 c.ret
// 10006: 0001 nop
// 10008: 0001 nop
private static final byte[] FUNC_CODE =
Utils.hexToBytes("67800000828001000100");
public static void test_riscv() {
long a0 = 0x1234L;
long a1 = 0x7890L;
System.out.println("Emulate RISCV code");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV32);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
}
public static void test_riscv2() {
long a0 = 0x1234L;
long a1 = 0x7890L;
System.out.println("Emulate RISCV code: split emulation");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV32);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// emulate 1 instruction
uc.emu_start(ADDRESS, ADDRESS + 4, 0, 0);
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
// emulate one more instruction
uc.emu_start(ADDRESS + 4, ADDRESS + 8, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
}
public static void test_riscv3() {
long a0 = 0x1234L;
long a1 = 0x7890L;
System.out.println("Emulate RISCV code: early stop");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV32);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code3, 1, 0, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
}
public static void test_riscv_step() {
long a0 = 0x1234L;
long a1 = 0x7890L;
long pc = 0x0000L;
System.out.println("Emulate RISCV code: step");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV32);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// emulate 1 instruction
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 1);
pc = uc.reg_read(UC_RISCV_REG_PC);
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
if (pc != 0x10004) {
System.out.format(
"Error after step: PC is: 0x%x, expected was 0x10004\n", pc);
}
// emulate one more instruction
uc.emu_start(ADDRESS + 4, ADDRESS + 8, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
}
public static void test_riscv_timeout() {
long a0 = 0x1234L;
long a1 = 0x7890L;
long pc = 0x0000L;
System.out.println("Emulate RISCV code: timeout");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV32);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
// TODO(nneonneo): what code was meant to go here? sample_riscv.c
// has all zeros, but that just crashes without running into the
// timeout...
uc.mem_write(ADDRESS, new byte[8]);
// initialize machine registers
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// emulate 1 instruction with timeout
uc.emu_start(ADDRESS, ADDRESS + 4, 1000, 1);
pc = uc.reg_read(UC_RISCV_REG_PC);
if (pc != 0x10000) {
System.out.format(
"Error after step: PC is: 0x%x, expected was 0x10004\n", pc);
}
// emulate 1 instruction with timeout
uc.emu_start(ADDRESS, ADDRESS + 4, 1000, 1);
pc = uc.reg_read(UC_RISCV_REG_PC);
if (pc != 0x10000) {
System.out.format(
"Error after step: PC is: 0x%x, expected was 0x10004\n", pc);
}
// now print out some registers
System.out.println(">>> Emulation done");
}
public static void test_riscv_sd64() {
long reg;
System.out.println("Emulate RISCV code: sd64 instruction");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV64);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE64);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
reg = ADDRESS + 0x100;
uc.reg_write(UC_RISCV_REG_SP, reg);
reg = 0x11223344;
uc.reg_write(UC_RISCV_REG_S0, reg);
// execute instruction
uc.emu_start(0x10000, -1, 0, 1);
// now print out some registers
System.out.println(">>> Emulation done.");
}
private static final EventMemHook hook_memalloc =
(uc, type, address, size, value, user_data) -> {
long aligned_address = address & ~0xFFFL;
int aligned_size = ((int) (size / 0x1000) + 1) * 0x1000;
System.out.format(
">>> Allocating block at 0x%x (0x%x), block size = 0x%x (0x%x)\n",
address, aligned_address, size, aligned_size);
uc.mem_map(aligned_address, aligned_size, UC_PROT_ALL);
// this recovers from missing memory, so we return true
return true;
};
public static void test_recover_from_illegal() {
long a0 = 0x1234L;
long a1 = 0x7890L;
System.out.println("Emulate RISCV code: recover_from_illegal");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV64);
uc.reg_write(UC_RISCV_REG_A0, a0);
uc.reg_write(UC_RISCV_REG_A1, a1);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// auto-allocate memory on access
uc.hook_add(hook_memalloc, UC_HOOK_MEM_UNMAPPED, 1, 0, null);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// emulate 1 instruction, wrong address, illegal code
try {
uc.emu_start(0x1000, -1, 0, 1);
throw new RuntimeException("emu_start should have failed!");
} catch (UnicornException e) {
System.out.println("Expected Illegal Instruction error, got: " + e);
}
// emulate 1 instruction, correct address, valid code
uc.emu_start(ADDRESS, -1, 0, 1);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> A0 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A0));
System.out.format(">>> A1 = 0x%x\n", uc.reg_read(UC_RISCV_REG_A1));
}
public static void test_riscv_func_return() {
long pc = 0, ra = 0;
System.out.println("Emulate RISCV code: return from func");
// Initialize emulator in RISCV64 mode
Unicorn uc = new Unicorn(UC_ARCH_RISCV, UC_MODE_RISCV64);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, FUNC_CODE);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing all instruction
uc.hook_add(hook_code, 1, 0, null);
// set return address register
// RET instruction will return to address in RA
// so after RET, PC == RA
ra = 0x10006;
uc.reg_write(UC_RISCV_REG_RA, ra);
// execute ret instruction
uc.emu_start(0x10000, -1, 0, 1);
pc = uc.reg_read(UC_RISCV_REG_PC);
if (pc != ra) {
System.out.format(
"Error after execution: PC is: 0x%x, expected was 0x%x\n",
pc, ra);
if (pc == 0x10000) {
System.out.println(" PC did not change during execution");
}
} else {
System.out.println("Good, PC == RA");
}
// set return address register
// C.RET instruction will return to address in RA
// so after C.RET, PC == RA
ra = 0x10006;
uc.reg_write(UC_RISCV_REG_RA, ra);
System.out.println("========");
// execute c.ret instruction
uc.emu_start(0x10004, -1, 0, 1);
pc = uc.reg_read(UC_RISCV_REG_PC);
if (pc != ra) {
System.out.format(
"Error after execution: PC is: 0x%x, expected was 0x%x\n",
pc, ra);
if (pc == 0x10004) {
System.out.println(" PC did not change during execution");
}
} else {
System.out.println("Good, PC == RA");
}
// now print out some registers
System.out.println(">>> Emulation done.");
}
public static final void main(String[] args) {
test_recover_from_illegal();
System.out.println("------------------");
test_riscv();
System.out.println("------------------");
test_riscv2();
System.out.println("------------------");
test_riscv3();
System.out.println("------------------");
test_riscv_step();
// System.out.println("------------------");
// test_riscv_timeout();
System.out.println("------------------");
test_riscv_sd64();
System.out.println("------------------");
test_riscv_func_return();
}
}

View File

@ -0,0 +1,88 @@
/*
Java bindings for the Unicorn Emulator Engine
Copyright(c) 2023 Robert Xiao
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Sample code to demonstrate how to emulate S390X code */
package samples;
import unicorn.*;
public class Sample_s390x implements UnicornConst, S390xConst {
/** code to be emulated:
* {@code lr %r2, %r3}
*/
private static final byte[] CODE = Utils.hexToBytes("1823");
// memory address where emulation starts
private static final long ADDRESS = 0x10000;
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
};
public static void test_s390x() {
long r2 = 2, r3 = 3;
System.out.println("Emulate S390X code");
Unicorn uc = new Unicorn(UC_ARCH_S390X, UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// initialize machine registers
uc.reg_write(UC_S390X_REG_R2, r2);
uc.reg_write(UC_S390X_REG_R3, r3);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS + CODE.length, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> R2 = 0x%x\t\t>>> R3 = 0x%x\n",
uc.reg_read(UC_S390X_REG_R2), uc.reg_read(UC_S390X_REG_R3));
}
public static final void main(String[] args) {
test_s390x();
}
}

View File

@ -28,50 +28,30 @@ package samples;
import unicorn.*;
public class Sample_sparc {
public class Sample_sparc implements UnicornConst, SparcConst {
// code to be emulated
public static final byte[] SPARC_CODE = { -122, 0, 64, 2 };
//public static final byte[] SPARC_CODE = {-69,112,0,0}; //illegal code
/** code to be emulated:
* {@code add %g1, %g2, %g3}
*/
private static final byte[] SPARC_CODE = Utils.hexToBytes("86004002");
//public static final byte[] SPARC_CODE = Utils.hexToBytes("bb700000"); //illegal code
// memory address where emulation starts
public static final int ADDRESS = 0x10000;
private static final int ADDRESS = 0x10000;
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
// callback for tracing basic blocks
private static class MyBlockHook implements BlockHook {
public void hook(Unicorn u, long address, int size, Object user_data) {
System.out.print(String.format(
">>> 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.print(String.format(
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
}
}
address, size);
};
public static void test_sparc() {
long g1 = 0x1230L; // G1 register
@ -81,25 +61,24 @@ public class Sample_sparc {
System.out.print("Emulate SPARC code\n");
// Initialize emulator in Sparc mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC,
Unicorn.UC_MODE_32 + Unicorn.UC_MODE_BIG_ENDIAN);
Unicorn u = new Unicorn(UC_ARCH_SPARC, UC_MODE_32 | UC_MODE_BIG_ENDIAN);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, SPARC_CODE);
// initialize machine registers
u.reg_write(Unicorn.UC_SPARC_REG_G1, g1);
u.reg_write(Unicorn.UC_SPARC_REG_G2, g2);
u.reg_write(Unicorn.UC_SPARC_REG_G3, g3);
u.reg_write(UC_SPARC_REG_G1, g1);
u.reg_write(UC_SPARC_REG_G2, g2);
u.reg_write(UC_SPARC_REG_G3, g3);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
u.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
u.hook_add(new MyCodeHook(), ADDRESS, ADDRESS, null);
u.hook_add(hook_code, ADDRESS, ADDRESS, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
@ -107,11 +86,7 @@ public class Sample_sparc {
// now print out some registers
System.out.print(">>> Emulation done. Below is the CPU context\n");
g3 = u.reg_read(Unicorn.UC_SPARC_REG_G3);
System.out.print(String.format(">>> G3 = 0x%x\n", g3));
u.close();
System.out.format(">>> G3 = 0x%x\n", u.reg_read(UC_SPARC_REG_G3));
}
public static void main(String args[]) {

View File

@ -0,0 +1,84 @@
/*
Java bindings for the Unicorn Emulator Engine
Copyright(c) 2023 Robert Xiao
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Sample code to demonstrate how to emulate TriCore code
* Ported from the C version originally by Eric Poole <eric.poole@aptiv.com>, 2022
*/
package samples;
import unicorn.*;
public class Sample_tricore implements UnicornConst, TriCoreConst {
/** code to be emulated:
* {@code mov d1, #0x1; mov.u d0, #0x8000}
*/
private static final byte[] CODE = Utils.hexToBytes("8211bb000008");
// memory address where emulation starts
private static final long ADDRESS = 0x10000;
private static final BlockHook hook_block =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing basic block at 0x%x, block size = 0x%x\n",
address, size);
};
private static final CodeHook hook_code =
(uc, address, size, user_data) -> {
System.out.format(
">>> Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
};
public static void test_tricore() {
System.out.println("Emulate TriCore code");
Unicorn uc = new Unicorn(UC_ARCH_TRICORE, UC_MODE_LITTLE_ENDIAN);
// map 2MB memory for this emulation
uc.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
uc.mem_write(ADDRESS, CODE);
// tracing all basic blocks with customized callback
uc.hook_add(hook_block, 1, 0, null);
// tracing one instruction at ADDRESS with customized callback
uc.hook_add(hook_code, ADDRESS, ADDRESS + CODE.length, null);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
uc.emu_start(ADDRESS, ADDRESS + CODE.length, 0, 0);
// now print out some registers
System.out.println(">>> Emulation done. Below is the CPU context");
System.out.format(">>> d0 = 0x%x\n", uc.reg_read(UC_TRICORE_REG_D0));
System.out.format(">>> d1 = 0x%x\n", uc.reg_read(UC_TRICORE_REG_D1));
}
public static final void main(String[] args) {
test_tricore();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -25,21 +25,14 @@ package samples;
import unicorn.*;
public class Sample_x86_mmr {
public class Sample_x86_mmr implements UnicornConst, X86Const {
public static void test_x86_mmr() {
// Initialize emulator in X86-32bit mode
Unicorn uc;
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;
}
Unicorn uc = new Unicorn(UC_ARCH_X86, UC_MODE_32);
// map 4k
uc.mem_map(0x400000, 0x1000, Unicorn.UC_PROT_ALL);
uc.mem_map(0x400000, 0x1000, UC_PROT_ALL);
X86_MMR ldtr1 = new X86_MMR(0x1111111122222222L, 0x33333333, 0x44444444,
(short) 0x5555);
@ -52,14 +45,14 @@ public class Sample_x86_mmr {
// initialize machine registers
uc.reg_write(Unicorn.UC_X86_REG_LDTR, ldtr1);
uc.reg_write(Unicorn.UC_X86_REG_GDTR, gdtr1);
uc.reg_write(Unicorn.UC_X86_REG_EAX, 0xddddddddL);
uc.reg_write(UC_X86_REG_LDTR, ldtr1);
uc.reg_write(UC_X86_REG_GDTR, gdtr1);
uc.reg_write(UC_X86_REG_EAX, 0xddddddddL);
// read the registers back out
eax = (int) uc.reg_read(Unicorn.UC_X86_REG_EAX);
ldtr2 = (X86_MMR) uc.reg_read(Unicorn.UC_X86_REG_LDTR, null);
gdtr2 = (X86_MMR) uc.reg_read(Unicorn.UC_X86_REG_GDTR, null);
eax = (int) uc.reg_read(UC_X86_REG_EAX);
ldtr2 = (X86_MMR) uc.reg_read(UC_X86_REG_LDTR, null);
gdtr2 = (X86_MMR) uc.reg_read(UC_X86_REG_GDTR, null);
System.out.printf(">>> EAX = 0x%x\n", eax);
@ -70,8 +63,6 @@ public class Sample_x86_mmr {
System.out.printf(">>> GDTR.base = 0x%x\n", gdtr2.base);
System.out.printf(">>> GDTR.limit = 0x%x\n", gdtr2.limit);
uc.close();
}
public static void main(String args[]) {

View File

@ -28,137 +28,107 @@ package samples;
import unicorn.*;
public class Shellcode {
public class Shellcode implements UnicornConst, X86Const {
public static final byte[] X86_CODE32 = { -21, 25, 49, -64, 49, -37, 49,
-46, 49, -55, -80, 4, -77, 1, 89, -78, 5, -51, -128, 49, -64, -80, 1,
49, -37, -51, -128, -24, -30, -1, -1, -1, 104, 101, 108, 108, 111 };
public static final byte[] X86_CODE32_SELF = { -21, 28, 90, -119, -42, -117,
2, 102, 61, -54, 125, 117, 6, 102, 5, 3, 3, -119, 2, -2, -62, 61, 65,
65, 65, 65, 117, -23, -1, -26, -24, -33, -1, -1, -1, 49, -46, 106, 11,
88, -103, 82, 104, 47, 47, 115, 104, 104, 47, 98, 105, 110, -119, -29,
82, 83, -119, -31, -54, 125, 65, 65, 65, 65, 65, 65, 65, 65 };
public static final byte[] X86_CODE32_SELF = Utils.hexToBytes(
"eb1c5a89d68b02663dca7d75066605030389" +
"02fec23d4141414175e9ffe6e8dfffffff31" +
"d26a0b589952682f2f7368682f62696e89e3" +
"525389e1ca7d4141414141414141");
// memory address where emulation starts
public static final int ADDRESS = 0x1000000;
public static final long toInt(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
public static class MyCodeHook implements CodeHook {
public void hook(Unicorn u, long address, int size, Object user) {
System.out.print(String.format(
"Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size));
long r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP);
System.out.print(
String.format("*** EIP = %x ***: ", r_eip));
size = Math.min(16, size);
byte[] tmp = u.mem_read(address, size);
for (int i = 0; i < tmp.length; i++) {
System.out.print(String.format("%x ", 0xff & tmp[i]));
}
System.out.print("\n");
public static CodeHook hook_code = (u, address, size, user) -> {
System.out.format(
"Tracing instruction at 0x%x, instruction size = 0x%x\n",
address, size);
long r_eip = u.reg_read(UC_X86_REG_EIP);
System.out.format("*** EIP = %x ***: ", r_eip);
byte[] tmp = u.mem_read(address, size);
for (int i = 0; i < tmp.length; i++) {
System.out.format("%x ", 0xff & tmp[i]);
}
System.out.println();
};
public static class MyInterruptHook implements InterruptHook {
public void hook(Unicorn u, int intno, Object user) {
long r_ecx;
long r_edx;
int size;
// only handle Linux syscall
if (intno != 0x80) {
return;
}
long r_eax = u.reg_read(Unicorn.UC_X86_REG_EAX);
long r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP);
switch ((int) r_eax) {
default:
System.out.print(
String.format(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n",
r_eip, intno, r_eax));
break;
case 1: // sys_exit
System.out.print(String.format(
">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n",
r_eip, intno));
u.emu_stop();
break;
case 4: // sys_write
// ECX = buffer address
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX);
// EDX = buffer size
r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX);
// read the buffer in
size = (int) Math.min(256, r_edx);
byte[] buffer = u.mem_read(r_ecx, size);
System.out.print(String.format(
">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n",
r_eip, intno, r_ecx,
r_edx, new String(buffer)));
break;
}
public static InterruptHook hook_intr = (u, intno, user) -> {
// only handle Linux syscall
if (intno != 0x80) {
return;
}
}
long r_eax = u.reg_read(UC_X86_REG_EAX);
long r_eip = u.reg_read(UC_X86_REG_EIP);
switch ((int) r_eax) {
default:
System.out.format(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n",
r_eip, intno, r_eax);
break;
case 1: // sys_exit
System.out.format(
">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n",
r_eip, intno);
u.emu_stop();
break;
case 4: { // sys_write
// ECX = buffer address
long r_ecx = u.reg_read(UC_X86_REG_ECX);
// EDX = buffer size
long r_edx = u.reg_read(UC_X86_REG_EDX);
// read the buffer in
int size = (int) Math.min(256, r_edx);
try {
byte[] buffer = u.mem_read(r_ecx, size);
System.out.format(
">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n",
r_eip, intno, r_ecx, r_edx, new String(buffer));
} catch (UnicornException e) {
System.out.format(
">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u (cannot get content)\n",
r_eip, intno, r_ecx, r_edx);
}
break;
}
}
};
public static void test_i386() {
long r_esp = ADDRESS + 0x200000L; // ESP register
System.out.print("Emulate i386 code\n");
System.out.println("Emulate i386 code");
// Initialize emulator in X86-32bit mode
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
Unicorn u = new Unicorn(UC_ARCH_X86, UC_MODE_32);
// map 2MB memory for this emulation
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
u.mem_map(ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
u.mem_write(ADDRESS, X86_CODE32_SELF);
// initialize machine registers
u.reg_write(Unicorn.UC_X86_REG_ESP, r_esp);
u.reg_write(UC_X86_REG_ESP, r_esp);
// tracing all instructions by having @begin > @end
u.hook_add(new MyCodeHook(), 1, 0, null);
u.hook_add(hook_code, 1, 0, null);
// handle interrupt ourself
u.hook_add(new MyInterruptHook(), null);
u.hook_add(hook_intr, null);
System.out.print("\n>>> Start tracing this Linux code\n");
System.out.println("\n>>> Start tracing this Linux code");
// emulate machine code in infinite time
// u.emu_start(ADDRESS, ADDRESS + X86_CODE32_SELF.length, 0, 12); <--- emulate only 12 instructions
u.emu_start(ADDRESS, ADDRESS + X86_CODE32_SELF.length, 0, 0);
System.out.print("\n>>> Emulation done.\n");
u.close();
System.out.println("\n>>> Emulation done.");
}
public static void main(String args[]) {
@ -167,7 +137,7 @@ public class Shellcode {
test_i386();
}
} else {
System.out.print("Syntax: java Shellcode <-32|-64>\n");
System.out.println("Syntax: java Shellcode <-32|-64>");
}
}

View File

@ -0,0 +1,49 @@
package samples;
public class Utils {
public static byte[] hexToBytes(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) +
Character.digit(s.charAt(i + 1), 16));
}
return data;
}
public static final int toInt(byte val[]) {
int res = 0;
for (int i = 0; i < val.length; i++) {
int v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
public static final long toLong(byte val[]) {
long res = 0;
for (int i = 0; i < val.length; i++) {
long v = val[i] & 0xff;
res = res + (v << (i * 8));
}
return res;
}
public static final byte[] toBytes(int val) {
byte[] res = new byte[4];
for (int i = 0; i < 4; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
public static final byte[] toBytes(long val) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[i] = (byte) (val & 0xff);
val >>>= 8;
}
return res;
}
}

View File

@ -122,8 +122,6 @@ public class FunctionalityTests {
u.emu_stop();
}).start();
u.emu_start(ADDRESS, ADDRESS + X86_CODE.length, 0, 0);
u.close();
}
@Test
@ -157,8 +155,6 @@ public class FunctionalityTests {
uc.context_restore(ctx);
assertEquals(0xfee1deadL, uc.reg_read(Unicorn.UC_ARM64_REG_X0));
assertEquals(0xfee1deadL, ctx.reg_read(Unicorn.UC_ARM64_REG_X0));
uc.close();
}
@Test
@ -188,6 +184,5 @@ public class FunctionalityTests {
assertEquals(0xfee1deadL, uc.reg_read(Unicorn.UC_ARM64_REG_X0));
uc.free(ctx);
uc.close();
}
}

View File

@ -59,7 +59,6 @@ public class HookTests {
// TODO(nneonneo): I don't totally understand this output! Why 8 bytes at address 5?
assertTranslationBlock(new TranslationBlock(ADDRESS + 5, 3, 8),
u.ctl_request_cache(ADDRESS + 5));
u.close();
}
@Test
@ -84,8 +83,6 @@ public class HookTests {
u.ctl_tlb_mode(Unicorn.UC_TLB_VIRTUAL);
u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_READ.length, 0, 0);
assertEquals("ecx", u.reg_read(Unicorn.UC_X86_REG_ECX), 0x04030201);
u.close();
}
@Test
@ -124,7 +121,5 @@ public class HookTests {
assertThrows(UnicornException.class, () -> u.hook_del(h1));
assertThrows(UnicornException.class, () -> u.hook_del(h3));
assertThrows(UnicornException.class, () -> u.hook_del(h4));
u.close();
}
}

View File

@ -29,7 +29,6 @@ public class MemTests {
assertEquals("two memory regions", 2, arr.length);
assertMemRegion(ADDR1, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL, arr[0]);
assertMemRegion(ADDR2, 4096, Unicorn.UC_PROT_READ, arr[1]);
uc.close();
}
@Test
@ -71,8 +70,6 @@ public class MemTests {
assertMemRegion(0x230000, 0x10000, Unicorn.UC_PROT_READ, mrs[7]);
assertMemRegion(0x250000, 0x10000, Unicorn.UC_PROT_WRITE, mrs[8]);
assertMemRegion(0x270000, 0x10000, Unicorn.UC_PROT_NONE, mrs[9]);
u.close();
}
@Test
@ -111,8 +108,6 @@ public class MemTests {
assertEquals("ecx", 0x44556679, u.reg_read(Unicorn.UC_X86_REG_ECX));
assertEquals("edx", 0x22334453, u.reg_read(Unicorn.UC_X86_REG_EDX));
u.close();
}
@Test
@ -132,7 +127,5 @@ public class MemTests {
u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_WRITE.length, 0, 0);
assertEquals("buffer contents", 0x12345678, buffer.getInt(0xaaa));
u.close();
}
}

View File

@ -33,7 +33,6 @@ public class RegTests {
assertEquals(Math.sin(Math.log(Math.E) / Math.log(2)), reg1.toDouble(),
1e-12);
assertEquals(reg1.toDouble(), reg2.toDouble(), 1e-12);
u.close();
}
@Test
@ -51,7 +50,6 @@ public class RegTests {
u.emu_start(ADDRESS, ADDRESS + X86_CODE.length, 0, 0);
reg = (X86_Float80) u.reg_read(Unicorn.UC_X86_REG_ST0, null);
assertEquals(Math.sin(-1.1), reg.toDouble(), 1e-12);
u.close();
}
@Test
@ -104,8 +102,6 @@ public class RegTests {
b[0x70] = -0x80;
uc.reg_write(reg, new BigInteger(b));
assertEquals("write untrimmed value", b127, uc.reg_read(reg, null));
uc.close();
}
@Test
@ -144,8 +140,6 @@ public class RegTests {
assertEquals("v0.8h = v1.8h + v2.8h",
new BigInteger("4860570d497678b4a5728c3e34a5f85c", 16),
uc.reg_read(Unicorn.UC_ARM64_REG_V0, null));
uc.close();
}
@Test
@ -200,7 +194,5 @@ public class RegTests {
uc.reg_read(Unicorn.UC_ARM64_REG_X1));
assertEquals("X1 low bits should be unchanged", 0x0000bbbbccccddddL,
uc.reg_read(Unicorn.UC_ARM64_REG_X1) & 0xffffffffffffL);
uc.close();
}
}

View File

@ -24,7 +24,6 @@ public class RegressionTests {
uc.reg_read(Unicorn.UC_ARM64_REG_B0));
assertEquals("V0 low halfword", 0x1234,
uc.reg_read(Unicorn.UC_ARM64_REG_H0));
uc.close();
}
/** Test for GH #1164: Java binding use CodeHook on Windows, will invoke callback before every instruction */

File diff suppressed because it is too large Load Diff

View File

@ -293,9 +293,94 @@ static void test_arm64_hook_mrs()
uc_close(uc);
}
#define CHECK(x) do { \
if((x) != UC_ERR_OK) { \
fprintf(stderr, "FAIL at %s:%d: %s\n", __FILE__, __LINE__, #x); \
exit(1); \
} \
} while(0)
static void test_arm64_pac(void)
{
uc_engine *uc;
uint64_t x1 = 0x0000aaaabbbbccccULL;
// paciza x1
#define ARM64_PAC_CODE "\xe1\x23\xc1\xda"
printf("Try ARM64 PAC\n");
// Initialize emulator in ARM mode
CHECK(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
CHECK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM64_MAX));
CHECK(uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL));
CHECK(uc_mem_write(uc, ADDRESS, ARM64_PAC_CODE, sizeof(ARM64_PAC_CODE) - 1));
CHECK(uc_reg_write(uc, UC_ARM64_REG_X1, &x1));
/** Initialize PAC support **/
uc_arm64_cp_reg reg;
// SCR_EL3
reg.op0 = 0b11;
reg.op1 = 0b110;
reg.crn = 0b0001;
reg.crm = 0b0001;
reg.op2 = 0b000;
CHECK(uc_reg_read(uc, UC_ARM64_REG_CP_REG, &reg));
// NS && RW && API
reg.val |= (1 | (1<<10) | (1<<17));
CHECK(uc_reg_write(uc, UC_ARM64_REG_CP_REG, &reg));
// SCTLR_EL1
reg.op0 = 0b11;
reg.op1 = 0b000;
reg.crn = 0b0001;
reg.crm = 0b0000;
reg.op2 = 0b000;
CHECK(uc_reg_read(uc, UC_ARM64_REG_CP_REG, &reg));
// EnIA && EnIB
reg.val |= (1<<31) | (1<<30);
CHECK(uc_reg_write(uc, UC_ARM64_REG_CP_REG, &reg));
// HCR_EL2
reg.op0 = 0b11;
reg.op1 = 0b100;
reg.crn = 0b0001;
reg.crm = 0b0001;
reg.op2 = 0b000;
// HCR.API
reg.val |= (1ULL<<41);
CHECK(uc_reg_write(uc, UC_ARM64_REG_CP_REG, &reg));
/** Check that PAC worked **/
CHECK(uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_PAC_CODE) - 1, 0, 0));
CHECK(uc_reg_read(uc, UC_ARM64_REG_X1, &x1));
printf("X1 = 0x%" PRIx64 "\n", x1);
if (x1 == 0x0000aaaabbbbccccULL) {
printf("FAIL: No PAC tag added!\n");
} else {
// Expect 0x1401aaaabbbbccccULL with the default key
printf("SUCCESS: PAC tag found.\n");
}
uc_close(uc);
}
int main(int argc, char **argv, char **envp)
{
test_arm64_mem_fetch();
printf("-------------------------\n");
test_arm64();
printf("-------------------------\n");
@ -307,5 +392,8 @@ int main(int argc, char **argv, char **envp)
printf("-------------------------\n");
test_arm64_hook_mrs();
printf("-------------------------\n");
test_arm64_pac();
return 0;
}

View File

@ -9,7 +9,7 @@
#include <string.h>
// code to be emulated
#define CODE "\x82\x11\xbb\x00\x00\x08" // mov d0, #0x1; mov.u d0, #0x8000
#define CODE "\x82\x11\xbb\x00\x00\x08" // mov d1, #0x1; mov.u d0, #0x8000
// memory address where emulation starts
#define ADDRESS 0x10000
@ -36,6 +36,7 @@ static void test_tricore(void)
uc_hook trace1, trace2;
uint32_t d0 = 0x0; // d0 register
uint32_t d1 = 0x0; // d1 register
printf("Emulate TriCore code\n");
@ -73,6 +74,9 @@ static void test_tricore(void)
uc_reg_read(uc, UC_TRICORE_REG_D0, &d0);
printf(">>> d0 = 0x%x\n", d0);
uc_reg_read(uc, UC_TRICORE_REG_D1, &d1);
printf(">>> d1 = 0x%x\n", d1);
uc_close(uc);
}

View File

@ -360,7 +360,6 @@ static void test_i386_map_ptr(void)
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code - use uc_mem_map_ptr()\n");
// Initialize emulator in X86-32bit mode
@ -426,7 +425,6 @@ static void test_i386_jump(void)
uc_err err;
uc_hook trace1, trace2;
printf("===================================\n");
printf("Emulate i386 code with jump\n");
// Initialize emulator in X86-32bit mode
@ -474,7 +472,6 @@ static void test_i386_loop(void)
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that loop forever\n");
// Initialize emulator in X86-32bit mode
@ -528,7 +525,6 @@ static void test_i386_invalid_mem_read(void)
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that read from invalid memory\n");
// Initialize emulator in X86-32bit mode
@ -588,7 +584,6 @@ static void test_i386_invalid_mem_write(void)
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that write to invalid memory\n");
// Initialize emulator in X86-32bit mode
@ -663,7 +658,6 @@ static void test_i386_jump_invalid(void)
int r_ecx = 0x1234; // ECX register
int r_edx = 0x7890; // EDX register
printf("===================================\n");
printf("Emulate i386 code that jumps to invalid memory\n");
// Initialize emulator in X86-32bit mode
@ -721,7 +715,6 @@ static void test_i386_inout(void)
int r_eax = 0x1234; // EAX register
int r_ecx = 0x6789; // ECX register
printf("===================================\n");
printf("Emulate i386 code with IN/OUT instructions\n");
// Initialize emulator in X86-32bit mode
@ -785,7 +778,6 @@ static void test_i386_context_save(void)
int r_eax = 0x1; // EAX register
printf("===================================\n");
printf("Save/restore CPU context in opaque blob\n");
// initialize emulator in X86-32bit mode
@ -908,7 +900,6 @@ static void test_i386_invalid_c6c7(void)
};
int i, j, k;
printf("===================================\n");
printf("Emulate i386 C6/C7 opcodes\n");
// Initialize emulator in X86-32bit mode
@ -1077,7 +1068,6 @@ static void test_x86_64_syscall(void)
int64_t rax = 0x100;
printf("===================================\n");
printf("Emulate x86_64 code with 'syscall' instruction\n");
// Initialize emulator in X86-64bit mode
@ -1186,7 +1176,6 @@ static void test_i386_invalid_mem_read_in_tb(void)
int r_edx = 0x7890; // EDX register
int r_eip = 0;
printf("===================================\n");
printf(
"Emulate i386 code that read invalid memory in the middle of a TB\n");
@ -1249,7 +1238,6 @@ static void test_i386_smc_xor()
uint32_t r_eax = 0xbc4177e6; // EDX register
uint32_t result;
printf("===================================\n");
printf("Emulate i386 code that modfies itself\n");
// Initialize emulator in X86-32bit mode
@ -1325,7 +1313,6 @@ static void test_i386_mmio()
int r_ecx = 0xdeadbeef;
uc_err err;
printf("===================================\n");
printf("Emulate i386 code that uses MMIO\n");
// Initialize emulator in X86-32bit mode
@ -1403,7 +1390,6 @@ static void test_i386_hook_mem_invalid()
"\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00";
uc_err err;
printf("===================================\n");
printf("Emulate i386 code that triggers invalid memory read/write.\n");
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
@ -1448,40 +1434,66 @@ int main(int argc, char **argv, char **envp)
test_x86_16();
} else if (!strcmp(argv[1], "-32")) {
test_miss_code();
printf("===================================\n");
test_i386();
printf("===================================\n");
test_i386_map_ptr();
printf("===================================\n");
test_i386_inout();
printf("===================================\n");
test_i386_context_save();
printf("===================================\n");
test_i386_jump();
printf("===================================\n");
test_i386_loop();
printf("===================================\n");
test_i386_invalid_mem_read();
printf("===================================\n");
test_i386_invalid_mem_write();
printf("===================================\n");
test_i386_jump_invalid();
// test_i386_invalid_c6c7();
} else if (!strcmp(argv[1], "-64")) {
test_x86_64();
printf("===================================\n");
test_x86_64_syscall();
} else if (!strcmp(argv[1], "-h")) {
printf("Syntax: %s <-16|-32|-64>\n", argv[0]);
}
} else {
test_x86_16();
printf("===================================\n");
test_miss_code();
printf("===================================\n");
test_i386();
printf("===================================\n");
test_i386_map_ptr();
printf("===================================\n");
test_i386_inout();
printf("===================================\n");
test_i386_context_save();
printf("===================================\n");
test_i386_jump();
printf("===================================\n");
test_i386_loop();
printf("===================================\n");
test_i386_invalid_mem_read();
printf("===================================\n");
test_i386_invalid_mem_write();
printf("===================================\n");
test_i386_jump_invalid();
// test_i386_invalid_c6c7();
printf("===================================\n");
test_x86_64();
printf("===================================\n");
test_x86_64_syscall();
printf("===================================\n");
test_i386_invalid_mem_read_in_tb();
printf("===================================\n");
test_i386_smc_xor();
printf("===================================\n");
test_i386_mmio();
printf("===================================\n");
test_i386_hook_mem_invalid();
}