Merge pull request #152 from cseagle/java_dev
Update for new mem hooking apis
This commit is contained in:
commit
4da8cac8fa
@ -83,18 +83,14 @@ public class Sample_x86 {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyMemInvalidHook implements MemoryInvalidHook {
|
||||
public boolean hook(Unicorn u, int type, long address, int size, long value, Object user) {
|
||||
switch(type) {
|
||||
case Unicorn.UC_MEM_WRITE:
|
||||
System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n",
|
||||
address, size, value);
|
||||
// map this memory in with 2MB in size
|
||||
u.mem_map(0xaaaa0000, 2 * 1024*1024, Unicorn.UC_PROT_ALL);
|
||||
// return true to indicate we want to continue
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
private static class MyWriteInvalidHook implements EventMemHook {
|
||||
public boolean hook(Unicorn u, long address, int size, long value, Object user) {
|
||||
System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n",
|
||||
address, size, value);
|
||||
// map this memory in with 2MB in size
|
||||
u.mem_map(0xaaaa0000, 2 * 1024*1024, Unicorn.UC_PROT_ALL);
|
||||
// return true to indicate we want to continue
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +419,7 @@ public class Sample_x86 {
|
||||
u.hook_add(new MyCodeHook(), 1, 0, null);
|
||||
|
||||
// intercept invalid memory events
|
||||
u.hook_add(new MyMemInvalidHook(), null);
|
||||
u.hook_add(new MyWriteInvalidHook(), Unicorn.UC_HOOK_MEM_WRITE_INVALID, null);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
try {
|
||||
|
@ -21,9 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
package unicorn;
|
||||
|
||||
public interface ReadWriteHook extends Hook {
|
||||
public interface EventMemHook extends Hook {
|
||||
|
||||
public void hook(Unicorn u, int type, long address, int size, long value, Object user);
|
||||
public boolean hook(Unicorn u, long address, int size, long value, Object user);
|
||||
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
package unicorn;
|
||||
|
||||
public interface MemoryInvalidHook extends Hook {
|
||||
|
||||
public boolean hook(Unicorn u, int type, long address, int size, long value, Object user);
|
||||
public interface MemHook extends ReadHook,WriteHook {
|
||||
|
||||
}
|
||||
|
@ -31,10 +31,15 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
private long interruptHandle = 0;
|
||||
private long codeHandle = 0;
|
||||
|
||||
private long memInvalidHandle = 0;
|
||||
private Hashtable<Integer, Long> eventMemHandles = new Hashtable<Integer, Long>();
|
||||
private long readInvalidHandle = 0;
|
||||
private long writeInvalidHandle = 0;
|
||||
private long fetchProtHandle = 0;
|
||||
private long readProtHandle = 0;
|
||||
private long writeProtHandle = 0;
|
||||
|
||||
private long readHandle = 0;
|
||||
private long writeHandle = 0;
|
||||
private long readWriteHandle = 0;
|
||||
private long inHandle = 0;
|
||||
private long outHandle = 0;
|
||||
private long syscallHandle = 0;
|
||||
@ -51,21 +56,28 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
private ArrayList<Tuple> blockList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> intrList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> codeList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> memInvalidList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> readList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> writeList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> readWriteList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> inList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> outList = new ArrayList<Tuple>();
|
||||
private ArrayList<Tuple> syscallList = new ArrayList<Tuple>();
|
||||
|
||||
private Hashtable<Integer, ArrayList<Tuple> > eventMemLists = new Hashtable<Integer, ArrayList<Tuple> >();
|
||||
|
||||
private ArrayList<ArrayList<Tuple>> allLists = new ArrayList<ArrayList<Tuple>>();
|
||||
|
||||
private static Hashtable<Integer,Integer> eventMemMap = new Hashtable<Integer,Integer>();
|
||||
private static Hashtable<Long,Unicorn> unicorns = new Hashtable<Long,Unicorn>();
|
||||
|
||||
//required to load native method implementations
|
||||
static {
|
||||
System.loadLibrary("unicorn_java"); //loads unicorn.dll or libunicorn.so
|
||||
eventMemMap.put(UC_HOOK_MEM_READ_INVALID, UC_MEM_READ_INVALID);
|
||||
eventMemMap.put(UC_HOOK_MEM_WRITE_INVALID, UC_MEM_WRITE_INVALID);
|
||||
eventMemMap.put(UC_HOOK_MEM_FETCH_INVALID, UC_MEM_FETCH_INVALID);
|
||||
eventMemMap.put(UC_HOOK_MEM_READ_PROT, UC_MEM_READ_PROT);
|
||||
eventMemMap.put(UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT);
|
||||
eventMemMap.put(UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,25 +140,29 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke all UC_HOOK_MEM_INVALID callbacks registered for a specific Unicorn.
|
||||
* Invoke all UC_HOOK_MEM_XXX_INVALID andor UC_HOOK_MEM_XXX_PROT callbacks registered
|
||||
* for a specific Unicorn.
|
||||
* This function gets invoked from the native C callback registered for
|
||||
* for UC_HOOK_MEM_INVALID
|
||||
* for UC_HOOK_MEM_XXX_INVALID or UC_HOOK_MEM_XXX_PROT
|
||||
*
|
||||
* @param eng A Unicorn uc_engine* eng returned by uc_open
|
||||
* @param type This memory is being read (UC_MEM_READ), or written (UC_MEM_WRITE)
|
||||
* @param type The type of event that is taking place
|
||||
* @param address Address of instruction being executed
|
||||
* @param size Size of data being read or written
|
||||
* @param value Value of data being written to memory, or irrelevant if type = READ.
|
||||
* @return true to continue, or false to stop program (due to invalid memory).
|
||||
* @see hook_add, unicorn.MemoryInvalidHook
|
||||
* @see hook_add, unicorn.EventMemHook
|
||||
*/
|
||||
private static boolean invokeMemInvalidCallbacks(long eng, int type, long address, int size, long value) {
|
||||
private static boolean invokeEventMemCallbacks(long eng, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
boolean result = true;
|
||||
if (u != null) {
|
||||
for (Tuple p : u.memInvalidList) {
|
||||
MemoryInvalidHook mh = (MemoryInvalidHook)p.function;
|
||||
result &= mh.hook(u, type, address, size, value, p.data);
|
||||
ArrayList<Tuple> funcList = u.eventMemLists.get(type);
|
||||
if (funcList != null) {
|
||||
for (Tuple p : funcList) {
|
||||
EventMemHook emh = (EventMemHook)p.function;
|
||||
result &= emh.hook(u, address, size, value, p.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -193,28 +209,6 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke all UC_HOOK_MEM_READ_WRITE callbacks registered for a specific Unicorn.
|
||||
* This function gets invoked from the native C callback registered for
|
||||
* for UC_HOOK_MEM_READ_WRITE
|
||||
*
|
||||
* @param eng A Unicorn uc_engine* eng returned by uc_open
|
||||
* @param type Type of access being performed (UC_MEM_READ, UC_MEM_WRITE, UC_MEM_READ_WRITE)
|
||||
* @param address Address of instruction being executed
|
||||
* @param size Size of data being read
|
||||
* @param value value being written (if applicable)
|
||||
* @see hook_add, unicorn.ReadWriteHook
|
||||
*/
|
||||
private static void invokeReadWriteCallbacks(long eng, int type, long address, int size, long value) {
|
||||
Unicorn u = unicorns.get(eng);
|
||||
if (u != null) {
|
||||
for (Tuple p : u.readWriteList) {
|
||||
ReadWriteHook rwh = (ReadWriteHook)p.function;
|
||||
rwh.hook(u, type, address, size, value, p.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke all UC_HOOK_INSN callbacks registered for a specific Unicorn.
|
||||
* This is specifically for the x86 IN instruction.
|
||||
@ -303,10 +297,8 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
allLists.add(blockList);
|
||||
allLists.add(intrList);
|
||||
allLists.add(codeList);
|
||||
allLists.add(memInvalidList);
|
||||
allLists.add(readList);
|
||||
allLists.add(writeList);
|
||||
allLists.add(readWriteList);
|
||||
allLists.add(inList);
|
||||
allLists.add(outList);
|
||||
allLists.add(syscallList);
|
||||
@ -528,34 +520,47 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook registration for UC_HOOK_MEM_READ_WRITE hooks. The registered callback function will be
|
||||
* invoked whenever a memory read or write is performed within the address range begin <= mem_addr <= end. For
|
||||
* the special case in which begin > end, the callback will be invoked for ALL memory reads and writes.
|
||||
* Hook registration for UC_HOOK_MEM_WRITE | UC_HOOK_MEM_WRITE hooks. The registered callback function will be
|
||||
* invoked whenever a memory write or read is performed within the address range begin <= addr <= end. For
|
||||
* the special case in which begin > end, the callback will be invoked for ALL memory writes.
|
||||
*
|
||||
* @param callback Implementation of a ReadWriteHook interface
|
||||
* @param begin Start address of memory read/write range
|
||||
* @param end End address of memory read/write range
|
||||
* @param callback Implementation of a MemHook interface
|
||||
* @param begin Start address of memory range
|
||||
* @param end End address of memory range
|
||||
* @param user_data User data to be passed to the callback function each time the event is triggered
|
||||
*/
|
||||
public void hook_add(ReadWriteHook callback, long begin, long end, Object user_data) throws UnicornException {
|
||||
if (readWriteHandle == 0) {
|
||||
readWriteHandle = registerHook(eng, UC_HOOK_MEM_READ_WRITE, begin, end);
|
||||
}
|
||||
readWriteList.add(new Tuple(callback, user_data));
|
||||
public void hook_add(MemHook callback, long begin, long end, Object user_data) throws UnicornException {
|
||||
hook_add((ReadHook)callback, begin, end, user_data);
|
||||
hook_add((WriteHook)callback, begin, end, user_data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hook registration for UC_HOOK_MEM_INVALID hooks. The registered callback function will be
|
||||
* invoked whenever a read or write is attempted from an unmapped memory address.
|
||||
* Hook registration for UC_HOOK_MEM_XXX_INVALID and UC_HOOK_MEM_XXX_PROT hooks.
|
||||
* The registered callback function will be invoked whenever a read or write is
|
||||
* attempted from an invalid or protected memory address.
|
||||
*
|
||||
* @param callback Implementation of a MemoryInvalidHook interface
|
||||
* @param callback Implementation of a EventMemHook interface
|
||||
* @param type Type of memory event being hooked such as UC_HOOK_MEM_READ_INVALID or UC_HOOK_MEM_WRITE_PROT
|
||||
* @param user_data User data to be passed to the callback function each time the event is triggered
|
||||
*/
|
||||
public void hook_add(MemoryInvalidHook callback, Object user_data) throws UnicornException {
|
||||
if (memInvalidHandle == 0) {
|
||||
memInvalidHandle = registerHook(eng, UC_HOOK_MEM_INVALID);
|
||||
public void hook_add(EventMemHook callback, int type, Object user_data) throws UnicornException {
|
||||
//test all of the EventMem related bits in type
|
||||
for (Integer htype : eventMemMap.keySet()) {
|
||||
if ((type & htype) != 0) { //the 'htype' bit is set in type
|
||||
Long handle = eventMemHandles.get(htype);
|
||||
if (handle == null) {
|
||||
eventMemHandles.put(htype, registerHook(eng, htype));
|
||||
}
|
||||
int cbType = eventMemMap.get(htype);
|
||||
ArrayList<Tuple> flist = eventMemLists.get(cbType);
|
||||
if (flist == null) {
|
||||
flist = new ArrayList<Tuple>();
|
||||
allLists.add(flist);
|
||||
eventMemLists.put(cbType, flist);
|
||||
}
|
||||
flist.add(new Tuple(callback, user_data));
|
||||
}
|
||||
}
|
||||
memInvalidList.add(new Tuple(callback, user_data));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,23 +50,33 @@ public interface UnicornConst {
|
||||
public static final int UC_ERR_MAP = 12;
|
||||
public static final int UC_ERR_WRITE_PROT = 13;
|
||||
public static final int UC_ERR_READ_PROT = 14;
|
||||
public static final int UC_ERR_EXEC_PROT = 15;
|
||||
public static final int UC_ERR_FETCH_PROT = 15;
|
||||
public static final int UC_ERR_ARG = 16;
|
||||
public static final int UC_ERR_READ_UNALIGNED = 17;
|
||||
public static final int UC_ERR_WRITE_UNALIGNED = 18;
|
||||
public static final int UC_ERR_FETCH_UNALIGNED = 19;
|
||||
public static final int UC_MEM_READ = 16;
|
||||
public static final int UC_MEM_WRITE = 17;
|
||||
public static final int UC_MEM_READ_WRITE = 18;
|
||||
public static final int UC_MEM_FETCH = 19;
|
||||
public static final int UC_MEM_WRITE_PROT = 20;
|
||||
public static final int UC_MEM_READ_PROT = 21;
|
||||
public static final int UC_MEM_EXEC_PROT = 22;
|
||||
public static final int UC_HOOK_INTR = 32;
|
||||
public static final int UC_HOOK_INSN = 33;
|
||||
public static final int UC_HOOK_CODE = 34;
|
||||
public static final int UC_HOOK_BLOCK = 35;
|
||||
public static final int UC_HOOK_MEM_INVALID = 36;
|
||||
public static final int UC_HOOK_MEM_READ = 37;
|
||||
public static final int UC_HOOK_MEM_WRITE = 38;
|
||||
public static final int UC_HOOK_MEM_READ_WRITE = 39;
|
||||
public static final int UC_MEM_FETCH = 18;
|
||||
public static final int UC_MEM_READ_INVALID = 19;
|
||||
public static final int UC_MEM_WRITE_INVALID = 20;
|
||||
public static final int UC_MEM_FETCH_INVALID = 21;
|
||||
public static final int UC_MEM_WRITE_PROT = 22;
|
||||
public static final int UC_MEM_READ_PROT = 23;
|
||||
public static final int UC_MEM_FETCH_PROT = 24;
|
||||
public static final int UC_HOOK_INTR = 1;
|
||||
public static final int UC_HOOK_INSN = 2;
|
||||
public static final int UC_HOOK_CODE = 4;
|
||||
public static final int UC_HOOK_BLOCK = 8;
|
||||
public static final int UC_HOOK_MEM_READ_INVALID = 16;
|
||||
public static final int UC_HOOK_MEM_WRITE_INVALID = 32;
|
||||
public static final int UC_HOOK_MEM_FETCH_INVALID = 64;
|
||||
public static final int UC_HOOK_MEM_READ_PROT = 128;
|
||||
public static final int UC_HOOK_MEM_WRITE_PROT = 256;
|
||||
public static final int UC_HOOK_MEM_FETCH_PROT = 512;
|
||||
public static final int UC_HOOK_MEM_READ = 1024;
|
||||
public static final int UC_HOOK_MEM_WRITE = 2048;
|
||||
public static final int UC_HOOK_MEM_FETCH = 4096;
|
||||
|
||||
public static final int UC_PROT_NONE = 0;
|
||||
public static final int UC_PROT_READ = 1;
|
||||
|
@ -33,10 +33,9 @@ static jmethodID invokeBlockCallbacks = 0;
|
||||
static jmethodID invokeInterruptCallbacks = 0;
|
||||
static jmethodID invokeCodeCallbacks = 0;
|
||||
|
||||
static jmethodID invokeMemInvalidCallbacks = 0;
|
||||
static jmethodID invokeEventMemCallbacks = 0;
|
||||
static jmethodID invokeReadCallbacks = 0;
|
||||
static jmethodID invokeWriteCallbacks = 0;
|
||||
static jmethodID invokeReadWriteCallbacks = 0;
|
||||
static jmethodID invokeInCallbacks = 0;
|
||||
static jmethodID invokeOutCallbacks = 0;
|
||||
static jmethodID invokeSyscallCallbacks = 0;
|
||||
@ -157,9 +156,6 @@ static void cb_hookmem(uc_engine *eng, uc_mem_type type,
|
||||
case UC_MEM_WRITE:
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeWriteCallbacks, (jlong)eng, (jlong)address, (int)size, (jlong)value);
|
||||
break;
|
||||
case UC_MEM_READ_WRITE:
|
||||
(*env)->CallStaticVoidMethod(env, clz, invokeReadWriteCallbacks, (jlong)eng, (int)type, (jlong)address, (int)size, (jlong)value);
|
||||
break;
|
||||
}
|
||||
(*cachedJVM)->DetachCurrentThread(cachedJVM);
|
||||
}
|
||||
@ -179,7 +175,7 @@ static bool cb_eventmem(uc_engine *eng, uc_mem_type type,
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return false;
|
||||
}
|
||||
jboolean res = (*env)->CallStaticBooleanMethod(env, clz, invokeMemInvalidCallbacks, (jlong)eng, (int)type, (jlong)address, (int)size, (jlong)value);
|
||||
jboolean res = (*env)->CallStaticBooleanMethod(env, clz, invokeEventMemCallbacks, (jlong)eng, (int)type, (jlong)address, (int)size, (jlong)value);
|
||||
(*cachedJVM)->DetachCurrentThread(cachedJVM);
|
||||
return res;
|
||||
}
|
||||
@ -393,9 +389,14 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JI
|
||||
}
|
||||
err = uc_hook_add((uc_engine*)eng, &hh, (uc_hook_type)type, cb_hookintr, env);
|
||||
break;
|
||||
case UC_HOOK_MEM_INVALID: // Hook for all invalid memory access events
|
||||
if (invokeMemInvalidCallbacks == 0) {
|
||||
invokeMemInvalidCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeMemInvalidCallbacks", "(JIJIJ)Z");
|
||||
case UC_HOOK_MEM_FETCH_INVALID: // Hook for all invalid memory access events
|
||||
case UC_HOOK_MEM_READ_INVALID: // Hook for all invalid memory access events
|
||||
case UC_HOOK_MEM_WRITE_INVALID: // Hook for all invalid memory access events
|
||||
case UC_HOOK_MEM_FETCH_PROT: // Hook for all invalid memory access events
|
||||
case UC_HOOK_MEM_READ_PROT: // Hook for all invalid memory access events
|
||||
case UC_HOOK_MEM_WRITE_PROT: // Hook for all invalid memory access events
|
||||
if (invokeEventMemCallbacks == 0) {
|
||||
invokeEventMemCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeEventMemCallbacks", "(JIJIJ)Z");
|
||||
}
|
||||
err = uc_hook_add((uc_engine*)eng, &hh, (uc_hook_type)type, cb_eventmem, env);
|
||||
break;
|
||||
@ -471,12 +472,6 @@ JNIEXPORT jlong JNICALL Java_unicorn_Unicorn_registerHook__JIJJ
|
||||
}
|
||||
err = uc_hook_add((uc_engine*)eng, &hh, (uc_hook_type)type, cb_hookmem, env, arg1, arg2);
|
||||
break;
|
||||
case UC_HOOK_MEM_READ_WRITE: // Hook all memory accesses (either READ or WRITE).
|
||||
if (invokeReadWriteCallbacks == 0) {
|
||||
invokeReadWriteCallbacks = (*env)->GetStaticMethodID(env, clz, "invokeReadWriteCallbacks", "(JIJIJ)V");
|
||||
}
|
||||
err = uc_hook_add((uc_engine*)eng, &hh, (uc_hook_type)type, cb_hookmem, env, arg1, arg2);
|
||||
break;
|
||||
}
|
||||
return (jlong)hh;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user