212 lines
6.1 KiB
Java
212 lines
6.1 KiB
Java
// Capstone Java binding
|
|
// By Nguyen Anh Quynh & Dang Hoang Vu, 2013
|
|
|
|
import com.sun.jna.Library;
|
|
import com.sun.jna.Native;
|
|
import com.sun.jna.Structure;
|
|
import com.sun.jna.Union;
|
|
import com.sun.jna.ptr.LongByReference;
|
|
import com.sun.jna.Pointer;
|
|
import com.sun.jna.ptr.PointerByReference;
|
|
|
|
import java.util.List;
|
|
import java.util.Arrays;
|
|
import java.lang.RuntimeException;
|
|
|
|
class Capstone {
|
|
|
|
public int arch;
|
|
public int mode;
|
|
|
|
public static abstract class OpInfo {
|
|
}
|
|
|
|
public static class PrivateOpInfo extends Union {
|
|
public X86.UnionOpInfo x86;
|
|
public Arm64.UnionOpInfo arm64;
|
|
public Arm.UnionOpInfo arm;
|
|
public Mips.UnionOpInfo mips;
|
|
}
|
|
|
|
public static class _cs_insn extends Structure implements Structure.ByReference {
|
|
public int id;
|
|
public long address;
|
|
public short size;
|
|
public byte[] mnemonic = new byte[32];
|
|
public byte[] operands = new byte[96];
|
|
public int[] regs_read = new int[32];
|
|
public int[] regs_write = new int[32];
|
|
public int[] groups = new int[8];
|
|
|
|
public PrivateOpInfo _op_info;
|
|
|
|
public _cs_insn(Pointer p) { super(p); }
|
|
|
|
@Override
|
|
public List getFieldOrder() {
|
|
return Arrays.asList("id", "address", "size", "mnemonic", "operands", "regs_read", "regs_write", "groups", "_op_info");
|
|
}
|
|
}
|
|
|
|
public static class cs_insn {
|
|
OpInfo op_info;
|
|
Pointer ptr_origin;
|
|
long csh;
|
|
CS cs;
|
|
|
|
int id;
|
|
long address;
|
|
short size;
|
|
String mnemonic;
|
|
String operands;
|
|
int[] regs_read;
|
|
int[] regs_write;
|
|
int[] groups;
|
|
|
|
public cs_insn (_cs_insn struct, Pointer _ptr_origin, long _csh, CS _cs, OpInfo _op_info) {
|
|
id = struct.id;
|
|
address = struct.address;
|
|
size = struct.size;
|
|
mnemonic = new String(struct.mnemonic).replace("\u0000","");
|
|
operands = new String(struct.operands).replace("\u0000","");
|
|
regs_read = struct.regs_read;
|
|
regs_write = struct.regs_write;
|
|
groups = struct.groups;
|
|
|
|
ptr_origin = _ptr_origin;
|
|
op_info = _op_info;
|
|
csh = _csh;
|
|
cs = _cs;
|
|
}
|
|
|
|
public int op_count(int type) {
|
|
return cs.cs_op_count(csh, ptr_origin, type);
|
|
}
|
|
|
|
public int op_index(int type, int index) {
|
|
return cs.cs_op_index(csh, ptr_origin, type, index);
|
|
}
|
|
}
|
|
|
|
private cs_insn fromPointer(Pointer pointer)
|
|
{
|
|
_cs_insn insn = new _cs_insn(pointer);
|
|
OpInfo op_info = null;
|
|
|
|
switch (this.arch) {
|
|
case CS_ARCH_ARM:
|
|
insn._op_info.setType(Arm.UnionOpInfo.class);
|
|
insn.read();
|
|
op_info = new Arm.OpInfo(insn._op_info.arm);
|
|
break;
|
|
case CS_ARCH_ARM64:
|
|
insn._op_info.setType(Arm64.UnionOpInfo.class);
|
|
insn.read();
|
|
op_info = new Arm64.OpInfo(insn._op_info.arm64);
|
|
break;
|
|
case CS_ARCH_MIPS:
|
|
insn._op_info.setType(Mips.UnionOpInfo.class);
|
|
insn.read();
|
|
op_info = new Mips.OpInfo(insn._op_info.mips);
|
|
break;
|
|
case CS_ARCH_X86:
|
|
insn._op_info.setType(X86.UnionOpInfo.class);
|
|
insn.read();
|
|
op_info = new X86.OpInfo(insn._op_info.x86);
|
|
break;
|
|
default:
|
|
}
|
|
return new cs_insn(insn, pointer, csh, cs, op_info);
|
|
}
|
|
|
|
private cs_insn[] fromArrayPointer(Pointer pointer, int numberResults)
|
|
{
|
|
cs_insn[] arr = new cs_insn[numberResults];
|
|
int offset = 0;
|
|
|
|
for (int i = 0; i < numberResults; i++) {
|
|
arr[i] = fromPointer(pointer.share(offset));
|
|
offset += 1728; // sizeof(cs_insn);
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
private interface CS extends Library {
|
|
public int cs_open(int arch, int mode, LongByReference handle);
|
|
public long cs_disasm_dyn(long handle, byte[] code, long code_len,
|
|
long addr, long count, PointerByReference insn);
|
|
public void cs_free(Pointer p);
|
|
public int cs_close(long handle);
|
|
public String cs_reg_name(long csh, int id);
|
|
public int cs_op_count(long csh, Pointer insn, int type);
|
|
public int cs_op_index(long csh, Pointer insn, int type, int index);
|
|
}
|
|
|
|
public static final int CS_ARCH_ARM = 0;
|
|
public static final int CS_ARCH_ARM64 = 1;
|
|
public static final int CS_ARCH_MIPS = 2;
|
|
public static final int CS_ARCH_X86 = 3;
|
|
|
|
public static final int CS_MODE_LITTLE_ENDIAN = 0; // default mode
|
|
public static final int CS_MODE_SYNTAX_INTEL = 0; // default X86 asm syntax (applicable for CS_ARCH_INTEL only)
|
|
public static final int CS_MODE_ARM = 0; // 32-bit ARM
|
|
public static final int CS_MODE_16 = 1 << 1;
|
|
public static final int CS_MODE_32 = 1 << 2;
|
|
public static final int CS_MODE_64 = 1 << 3;
|
|
public static final int CS_MODE_THUMB = 1 << 4; // ARM's Thumb mode, including Thumb-2
|
|
public static final int CS_MODE_SYNTAX_ATT = 1 << 30; // X86 ATT asm syntax (applicable for CS_ARCH_INTEL only)
|
|
public static final int CS_MODE_BIG_ENDIAN = 1 << 31;
|
|
|
|
// capstone error
|
|
public static final int CS_ERR_OK = 0;
|
|
public static final int CS_ERR_MEM = 1; // Out-Of-Memory error
|
|
public static final int CS_ERR_ARCH = 2; // Unsupported architecture
|
|
public static final int CS_ERR_HANDLE = 3; // Invalid handle
|
|
public static final int CS_ERR_CSH = 4; // Invalid csh argument
|
|
public static final int CS_ERR_MODE = 5; // Invalid/unsupported mode
|
|
|
|
|
|
private long csh;
|
|
private PointerByReference insnRef;
|
|
private CS cs;
|
|
|
|
Capstone(int arch, int mode)
|
|
{
|
|
this.arch = arch;
|
|
this.mode = mode;
|
|
cs = (CS)Native.loadLibrary("capstone", CS.class);
|
|
LongByReference handleref = new LongByReference();
|
|
if (cs.cs_open(arch, mode, handleref) != CS_ERR_OK) {
|
|
throw new RuntimeException("ERROR: Wrong arch or mode");
|
|
}
|
|
csh = handleref.getValue();
|
|
}
|
|
|
|
public String reg_name(int reg) {
|
|
return cs.cs_reg_name(csh, reg);
|
|
}
|
|
|
|
protected void finalize()
|
|
{
|
|
cs.cs_close(csh);
|
|
}
|
|
|
|
cs_insn[] disasm(byte[] code, long address)
|
|
{
|
|
return disasm(code, address, 0);
|
|
}
|
|
|
|
cs_insn[] disasm(byte[] code, long address, long count)
|
|
{
|
|
insnRef = new PointerByReference();
|
|
|
|
long c = cs.cs_disasm_dyn(csh, code, code.length, address, count, insnRef);
|
|
|
|
Pointer p = insnRef.getValue();
|
|
cs_insn[] all_insn = fromArrayPointer(p, (int)c);
|
|
return all_insn;
|
|
}
|
|
}
|
|
|