// Get the Unsafe object.
Field f = Unsafe.class.getDeclaredField("THE_ONE");
f.setAccessible(true);
Unsafe u = (Unsafe) f.get(null);
// Get the offsets into the original Transform class of the fields long off_secret_array = genericFieldOffset(Transform.class.getDeclaredField("SECRET_ARRAY")); long off_secret_number = genericFieldOffset(Transform.class.getDeclaredField("SECRET_NUMBER"));
System.out.println("Reading normally.");
System.out.println("\tOriginal secret number is: " + Transform.SECRET_NUMBER);
System.out.println("\tOriginal secret array is: " + Arrays.toString((byte[])Transform.SECRET_ARRAY));
System.out.println("Using unsafe to access values directly from memory.");
System.out.println( "\tOriginal secret number is: " + u.getLong(Transform.class, off_secret_number));
System.out.println( "\tOriginal secret array is: "
+ Arrays.toString((byte[]) u.getObject(Transform.class, off_secret_array)));
// Redefine in a way that changes the offsets.
Redefinition.doCommonStructuralClassRedefinition(Transform.class, REDEFINED_DEX_FILE);
// Make sure the value is the same.
System.out.println("Reading normally post redefinition.");
System.out.println("\tPost-redefinition secret number is: " + Transform.SECRET_NUMBER);
System.out.println("\tPost-redefinition secret array is: " + Arrays.toString((byte[])Transform.SECRET_ARRAY));
// Get the (old) obsolete class from the ClassExt
Field ext_field = Class.class.getDeclaredField("extData");
ext_field.setAccessible(true);
Object ext_data = ext_field.get(Transform.class);
Field oc_field = ext_data.getClass().getDeclaredField("obsoleteClass");
oc_field.setAccessible(true); Class<?> obsolete_class = (Class<?>) oc_field.get(ext_data);
// Try reading the fields directly out of memory using unsafe.
System.out.println("Obsolete class is: " + obsolete_class);
System.out.println("Using unsafe to access obsolete values directly from memory.");
System.out.println( "\tObsolete secret number is: " + u.getLong(obsolete_class, off_secret_number));
System.out.println( "\tObsolete secret array is: "
+ Arrays.toString((byte[]) u.getObject(obsolete_class, off_secret_array)));
// Try calling all the public, non-static methods on the obsolete class. Make sure we cannot get // j.l.r.{Method,Field} objects or instances.
TConsumer<Class> cc =
(Class c) -> { for (Method m : Class.class.getDeclaredMethods()) { if (Modifier.isPublic(m.getModifiers()) && !Modifier.isStatic(m.getModifiers())) {
Iterable<Object[]> iter = CollectParameterValues(m, obsolete_class);
System.out.println("Calling " + m + " with params: " + iter); for (Object[] arr : iter) { try {
System.out.println(
m
+ " on "
+ safePrint(c)
+ " with "
+ deepPrint(arr)
+ " = "
+ safePrint(m.invoke(c, arr)));
} catch (Throwable e) {
System.out.println(
m + " with " + deepPrint(arr) + " throws " + safePrint(e) + ": " + safePrint(e.getCause()));
}
}
}
}
};
System.out.println("\n\nUsing obsolete class object!\n\n");
cc.accept(obsolete_class);
System.out.println("\n\nUsing non-obsolete class object!\n\n");
cc.accept(Transform.class);
}
publicstatic Iterable<Object[]> CollectParameterValues(Method m, Class<?> obsolete_class) throws Exception { Class<?>[] types = m.getParameterTypes(); final Object[][] params = new Object[types.length][]; for (int i = 0; i < types.length; i++) { if (types[i].equals(Class.class)) {
params[i] = new Object[] { null, Object.class, obsolete_class, Transform.class, Long.TYPE, Class.class
};
} elseif (types[i].equals(Boolean.TYPE)) {
params[i] = new Object[] {Boolean.TRUE, Boolean.FALSE};
} elseif (types[i].equals(String.class)) {
params[i] = new Object[] {"NOT_USED_STRING", "foo", "SECRET_ARRAY"};
} elseif (types[i].equals(Object.class)) {
params[i] = new Object[] {null, "foo", "NOT_USED_STRING", Transform.class};
} elseif (types[i].isArray()) {
params[i] = new Object[] {new Object[0], newClass[0], null};
} else { thrownew Exception("Unknown type " + types[i] + " at " + i + " in " + m);
}
} // Build the reset-iter.
ResetIterator<Object[]> iter = new BaseResetIter(); for (int i = params.length - 1; i >= 0; i--) {
iter = new ComboIter(Arrays.asList(params[i]), iter);
} final Iterator<Object[]> fiter = iter; // Wrap in an iterator with a useful toString method. returnnew Iterable<Object[]>() { public Iterator<Object[]> iterator() { return fiter; } public String toString() { return deepPrint(params); }
};
}
public Object[] next() { if (!next.hasNext()) {
cur = my_vals.next();
first = false; if (next != null) {
next.reset();
}
} if (first) {
first = false;
cur = my_vals.next();
}
Object[] nv = next.next();
Object[] res = new Object[nv.length + 1];
res[0] = cur; for (int i = 0; i < nv.length; i++) {
res[i + 1] = nv[i];
} return res;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.