Commit 8775fed6 authored by swift_gan's avatar swift_gan

[ResolveMethod]add resolve method in java

parent a2623a31
...@@ -12,15 +12,16 @@ namespace SandHook { ...@@ -12,15 +12,16 @@ namespace SandHook {
if (SDK_INT >= ANDROID_P) if (SDK_INT >= ANDROID_P)
return getParentSize() + 1; return getParentSize() + 1;
auto filter = [](int offset, void *ptr) -> bool { auto filter = [](int offset, void *ptr) -> bool {
if (isBadReadPtr(ptr, BYTE_POINT)) // if (isBadReadPtr(ptr, BYTE_POINT))
return false; // return false;
Size addr = ADDR(ptr); // Size addr = ADDR(ptr);
if (isBadReadPtr(reinterpret_cast<void *>(addr + offset), BYTE_POINT)) // if (isBadReadPtr(reinterpret_cast<void *>(addr + offset), BYTE_POINT))
return false; // return false;
Size subAddr = ADDR(addr + offset); // Size subAddr = ADDR(addr + offset);
return addr == subAddr; // return addr == subAddr;
}; };
int offset = findOffsetWithCB1(&p, getParentSize(), 4, *filter); int offset = findOffsetWithCB1(&p, getParentSize(), 4, *filter);
return offset;
} }
}; };
...@@ -85,7 +86,13 @@ namespace SandHook { ...@@ -85,7 +86,13 @@ namespace SandHook {
entryPointFormInterpreter->init(m1, size); entryPointFormInterpreter->init(m1, size);
dexCacheResolvedMethods = new CastDexCacheResolvedMethods(); dexCacheResolvedMethods = new CastDexCacheResolvedMethods();
dexCacheResolvedMethods->init(m1, size); // dexCacheResolvedMethods->init(m1, size);
//test
art::mirror::ArtMethod** mArray = reinterpret_cast<art::mirror::ArtMethod**>(m1.dex_cache_resolved_methods_);
art::mirror::ArtMethod m1B = *(mArray + 8)[m1.dex_method_index_];
art::mirror::ArtMethod m1C = *(mArray + 8)[m2.dex_method_index_];
} }
......
//
// Created by SwiftGan on 2019/1/14.
//
#ifndef SANDHOOK_IMETHODRESOLVER_H
#define SANDHOOK_IMETHODRESOLVER_H
#endif //SANDHOOK_IMETHODRESOLVER_H
...@@ -10,6 +10,7 @@ import android.view.View; ...@@ -10,6 +10,7 @@ import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
...@@ -40,11 +41,45 @@ public class MainActivity extends AppCompatActivity { ...@@ -40,11 +41,45 @@ public class MainActivity extends AppCompatActivity {
try { try {
Method method1 = ArtMethodSizeTest.class.getDeclaredMethod("method1"); Method method1 = ArtMethodSizeTest.class.getDeclaredMethod("method1");
Method method2 = ArtMethodSizeTest.class.getDeclaredMethod("method2"); Method method2 = ArtMethodSizeTest.class.getDeclaredMethod("method2");
tv.setText("" + calArtSize(method1, method2)); Field field = Class.class.getDeclaredField("dexCache");
field.setAccessible(true);
Object dexCache = field.get(ArtMethodSizeTest.class);
Field resolvedMethodsField = dexCache.getClass().getDeclaredField("resolvedMethods");
resolvedMethodsField.setAccessible(true);
long[] methods = (long[]) resolvedMethodsField.get(dexCache);
Field dexMethodIndexField = getField(Method.class, "dexMethodIndex");
dexMethodIndexField.setAccessible(true);
int dexMethodIndex = (int) dexMethodIndexField.get(method1);
Field artMethodField = getField(Method.class, "artMethod");
artMethodField.setAccessible(true);
long artMethod = (long) artMethodField.get(method1);
// methods[dexMethodIndex] = artMethod;
initHook(); initHook();
// SandHook.init();
tv.setText("" + calArtSize(method1, method2));
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException {
while (topClass != null && topClass != Object.class) {
try {
return topClass.getDeclaredField(fieldName);
} catch (Exception e) {
}
topClass = topClass.getSuperclass();
} }
throw new NoSuchFieldException(fieldName);
} }
@Override @Override
......
package com.swift.sandhook; package com.swift.sandhook;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class SandHook { public class SandHook {
public final static boolean init() {
// make sure resolved! public static Class artMethodClass;
public static Method testOffsetMethod1;
public static Method testOffsetMethod2;
public static Object testOffsetArtMethod1;
public static Object testOffsetArtMethod2;
public static int testAccessFlag;
public static int methodOffset;
public static boolean init() {
initTestOffset();
return true;
}
private static void initTestOffset() {
// make test methods sure resolved!
ArtMethodSizeTest.method1(); ArtMethodSizeTest.method1();
ArtMethodSizeTest.method2(); ArtMethodSizeTest.method2();
return true; // get test methods
try {
testOffsetMethod1 = ArtMethodSizeTest.class.getDeclaredMethod("method1");
testOffsetMethod2 = ArtMethodSizeTest.class.getDeclaredMethod("method2");
} catch (NoSuchMethodException e) {
throw new RuntimeException("SandHook init error", e);
}
//
initTestAccessFlag();
} }
private static void initTestAccessFlag() {
if (hasJavaArtMethod()) {
try {
loadArtMethod();
Field fieldAccessFlags = getField(artMethodClass, "accessFlags");
fieldAccessFlags.setAccessible(true);
testAccessFlag = (int) fieldAccessFlags.get(testOffsetArtMethod1);
} catch (Exception e) {
}
} else {
try {
Field fieldAccessFlags = getField(Method.class, "accessFlags");
fieldAccessFlags.setAccessible(true);
testAccessFlag = (int) fieldAccessFlags.get(testOffsetMethod1);
} catch (Exception e) {
}
}
}
private static void loadArtMethod() {
try {
Field fieldArtMethod = getField(Method.class, "artMethod");
fieldArtMethod.setAccessible(true);
testOffsetArtMethod1 = fieldArtMethod.get(testOffsetMethod1);
testOffsetArtMethod2 = fieldArtMethod.get(testOffsetMethod2);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public static boolean hasJavaArtMethod() {
if (artMethodClass != null)
return true;
try {
artMethodClass = Class.forName("java.lang.reflect.ArtMethod");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException {
while (topClass != null && topClass != Object.class) {
try {
Field field = topClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (Exception e) {
}
topClass = topClass.getSuperclass();
}
throw new NoSuchFieldException(fieldName);
}
} }
package com.swift.sandhook;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class SandHookMethodResolver {
public static Field resolvedMethodsField;
public static Field dexCacheField;
public static Field dexMethodIndexField;
public static Field artMethodField;
public static boolean canResolvedInJava = false;
public static long resolvedMethodsAddress = 0;
public static int dexMethodIndex = 0;
public static void init() {
checkSupport();
}
private static void checkSupport() {
try {
dexMethodIndexField = SandHook.getField(Method.class, "dexMethodIndex");
dexMethodIndex = (int) dexMethodIndexField.get(SandHook.testOffsetMethod1);
dexCacheField = SandHook.getField(Class.class, "dexCache");
dexCacheField.setAccessible(true);
Object dexCache = dexCacheField.get(ArtMethodSizeTest.class);
resolvedMethodsField = SandHook.getField(dexCache.getClass(), "resolvedMethods");
Object resolvedMethods = resolvedMethodsField.get(dexCache);
if (resolvedMethods instanceof Long) {
canResolvedInJava = false;
resolvedMethodsAddress = (long) resolvedMethods;
} else if (resolvedMethods instanceof long[]) {
canResolvedInJava = true;
} else if (SandHook.hasJavaArtMethod() && resolvedMethods instanceof Object[]) {
canResolvedInJava = true;
} else {
canResolvedInJava = false;
}
if (canResolvedInJava) {
artMethodField = SandHook.getField(Method.class, "artMethod");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void resolveMethod(Method method) {
if (canResolvedInJava && artMethodField != null) {
// in java
try {
resolveInJava(method);
} catch (Exception e) {
// in native
}
} else {
// in native
}
}
private static void resolveInJava(Method method) throws Exception {
Object dexCache = dexCacheField.get(method.getDeclaringClass());
resolvedMethodsField.setAccessible(true);
int dexMethodIndex = (int) dexMethodIndexField.get(method);
Object resolvedMethods = resolvedMethodsField.get(dexCache);
if (resolvedMethods instanceof long[]) {
long artMethod = (long) artMethodField.get(method);
((long[])resolvedMethods)[dexMethodIndex] = artMethod;
} else if (resolvedMethods instanceof Object[]) {
Object artMethod = artMethodField.get(method);
((Object[])resolvedMethods)[dexMethodIndex] = artMethod;
} else {
throw new UnsupportedOperationException("unsupport");
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment