public static ArtMethod hook(Constructor<?> originalMethod, Method replacementMethod) { Assertions.argumentNotNull(originalMethod, "originalMethod"); Assertions.argumentNotNull(replacementMethod, "replacementMethod"); if (replacementMethod.getReturnType() != Void.TYPE) throw new IllegalArgumentException("return types of replacementMethod has to be 'void'"); return hook(ArtMethod.of(originalMethod), ArtMethod.of(replacementMethod)); }
public static OriginalMethod hook( Method originalMethod, Method replacementMethod, String backupIdentifier) { ArtMethod backArt = hook(originalMethod, replacementMethod); Method backupMethod = (Method) backArt.getAssociatedMethod(); backupMethod.setAccessible(true); OriginalMethod.store(originalMethod, backupMethod, backupIdentifier); return new OriginalMethod(backupMethod); }
private static ArtMethod hook(ArtMethod original, ArtMethod replacement) { HookPage page = handleHookPage(original, replacement); ArtMethod backArt = original.clone(); backArt.makePrivate(); if (getQuickCompiledCodeSize(original) < INSTRUCTION_SET_HELPER.sizeOfDirectJump()) { original.setEntryPointFromQuickCompiledCode(page.getCallHook()); } else { page.activate(); } return backArt; }
public static ArtMethod hook(Method originalMethod, Method replacementMethod) { Assertions.argumentNotNull(originalMethod, "originalMethod"); Assertions.argumentNotNull(replacementMethod, "replacementMethod"); if (originalMethod == replacementMethod || originalMethod.equals(replacementMethod)) throw new IllegalArgumentException("originalMethod and replacementMethod can't be the same"); if (!replacementMethod.getReturnType().isAssignableFrom(originalMethod.getReturnType())) throw new IllegalArgumentException( "return types of originalMethod and replacementMethod do not match"); return hook(ArtMethod.of(originalMethod), ArtMethod.of(replacementMethod)); }
private static HookPage handleHookPage(ArtMethod original, ArtMethod replacement) { long originalEntryPoint = INSTRUCTION_SET_HELPER.toMem(original.getEntryPointFromQuickCompiledCode()); if (!pages.containsKey(originalEntryPoint)) { pages.put( originalEntryPoint, new HookPage( INSTRUCTION_SET_HELPER, originalEntryPoint, getQuickCompiledCodeSize(original))); } HookPage page = pages.get(originalEntryPoint); page.addHook(new HookPage.Hook(original, replacement)); page.update(); return page; }
static { try { boolean isArm = true; // TODO: logic if (isArm) { if ((ArtMethod.of(ArtMethod.class.getDeclaredMethod("of", Method.class)) .getEntryPointFromQuickCompiledCode() & 1) == 1) { INSTRUCTION_SET_HELPER = new Thumb2(); } else { INSTRUCTION_SET_HELPER = new Arm32(); } } logd("Using: " + INSTRUCTION_SET_HELPER.getName()); } catch (Exception ignored) { } }
private static int getQuickCompiledCodeSize(ArtMethod method) { long entryPoint = INSTRUCTION_SET_HELPER.toMem(method.getEntryPointFromQuickCompiledCode()); long sizeInfo1 = entryPoint - 4; byte[] bytes = Memory.get(sizeInfo1, 4); return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); }