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:
parent
3739c7e3e0
commit
4f563490e2
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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[]) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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[]) {
|
||||
|
|
|
@ -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
|
@ -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[]) {
|
||||
|
|
|
@ -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>");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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, ®));
|
||||
|
||||
// NS && RW && API
|
||||
reg.val |= (1 | (1<<10) | (1<<17));
|
||||
|
||||
CHECK(uc_reg_write(uc, UC_ARM64_REG_CP_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, ®));
|
||||
|
||||
// EnIA && EnIB
|
||||
reg.val |= (1<<31) | (1<<30);
|
||||
|
||||
CHECK(uc_reg_write(uc, UC_ARM64_REG_CP_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, ®));
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue