Commit 3615f339 authored by swift_gan's avatar swift_gan

done compat for xposed

parent 8e0774b6
...@@ -27,4 +27,5 @@ dependencies { ...@@ -27,4 +27,5 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':hooklib') implementation project(':hooklib')
implementation project(':xposedcompat')
} }
package com.swift.sandhook; package com.swift.sandhook;
import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.util.Log;
import com.swift.sandhook.testHookers.ActivityHooker; import com.swift.sandhook.testHookers.ActivityHooker;
import com.swift.sandhook.testHookers.CtrHook; import com.swift.sandhook.testHookers.CtrHook;
...@@ -9,13 +11,17 @@ import com.swift.sandhook.testHookers.JniHooker; ...@@ -9,13 +11,17 @@ import com.swift.sandhook.testHookers.JniHooker;
import com.swift.sandhook.testHookers.LogHooker; import com.swift.sandhook.testHookers.LogHooker;
import com.swift.sandhook.testHookers.ObjectHooker; import com.swift.sandhook.testHookers.ObjectHooker;
import com.swift.sandhook.wrapper.HookErrorException; import com.swift.sandhook.wrapper.HookErrorException;
import com.swift.sandhook.xposedcompat.XposedCompat;
import dalvik.system.DexClassLoader; import dalvik.system.DexClassLoader;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
public class MyApp extends Application { public class MyApp extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
try { try {
SandHook.addHookClass(JniHooker.class, SandHook.addHookClass(JniHooker.class,
CtrHook.class, CtrHook.class,
...@@ -27,6 +33,26 @@ public class MyApp extends Application { ...@@ -27,6 +33,26 @@ public class MyApp extends Application {
e.printStackTrace(); e.printStackTrace();
} }
//setup for xposed
XposedCompat.cacheDir = getCacheDir();
XposedCompat.context = this;
XposedCompat.classLoader = getClassLoader();
XposedCompat.isFirstApplication= true;
XposedHelpers.findAndHookMethod(Activity.class, "onResume", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.e("XposedCompat", "beforeHookedMethod: " + param.method.getName());
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.e("XposedCompat", "afterHookedMethod: " + param.method.getName());
}
});
try { try {
ClassLoader classLoader = getClassLoader(); ClassLoader classLoader = getClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader("/sdcard/hookers-debug.apk", DexClassLoader dexClassLoader = new DexClassLoader("/sdcard/hookers-debug.apk",
......
...@@ -10,9 +10,13 @@ import java.lang.reflect.Field; ...@@ -10,9 +10,13 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SandHook { public class SandHook {
static Map<Member,HookWrapper.HookEntity> globalHookEntityMap = new ConcurrentHashMap<>();
public static Class artMethodClass; public static Class artMethodClass;
public static Field nativePeerField; public static Field nativePeerField;
...@@ -55,6 +59,15 @@ public class SandHook { ...@@ -55,6 +59,15 @@ public class SandHook {
HookWrapper.addHookClass(classLoader, hookWrapperClass); HookWrapper.addHookClass(classLoader, hookWrapperClass);
} }
public static void hook(HookWrapper.HookEntity entity) throws HookErrorException {
if (entity.target != null && entity.hook != null) {
if (!SandHook.hook(entity.target, entity.hook, entity.backup)) {
throw new HookErrorException("hook method <" + entity.target.getName() + "> error in native!");
}
globalHookEntityMap.put(entity.target, entity);
}
}
public static boolean hook(Member target, Method hook, Method backup) { public static boolean hook(Member target, Method hook, Method backup) {
if (target == null || hook == null) if (target == null || hook == null)
return false; return false;
......
...@@ -21,8 +21,6 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -21,8 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
public class HookWrapper { public class HookWrapper {
static Map<Member,HookEntity> globalHookEntityMap = new ConcurrentHashMap<>();
public static void addHookClass(Class<?>... classes) throws HookErrorException { public static void addHookClass(Class<?>... classes) throws HookErrorException {
addHookClass(null, classes); addHookClass(null, classes);
} }
...@@ -40,12 +38,7 @@ public class HookWrapper { ...@@ -40,12 +38,7 @@ public class HookWrapper {
Map<Member,HookEntity> hookEntityMap = getHookMethods(classLoader, targetHookClass, clazz); Map<Member,HookEntity> hookEntityMap = getHookMethods(classLoader, targetHookClass, clazz);
fillBackupMethod(classLoader, clazz, hookEntityMap); fillBackupMethod(classLoader, clazz, hookEntityMap);
for (HookEntity entity:hookEntityMap.values()) { for (HookEntity entity:hookEntityMap.values()) {
if (entity.target != null && entity.hook != null) { SandHook.hook(entity);
if (!SandHook.hook(entity.target, entity.hook, entity.backup)) {
throw new HookErrorException("hook method <" + entity.target.getName() + "> error in native!");
}
globalHookEntityMap.put(entity.target, entity);
}
} }
} }
...@@ -285,6 +278,11 @@ public class HookWrapper { ...@@ -285,6 +278,11 @@ public class HookWrapper {
this.target = target; this.target = target;
} }
public HookEntity(Member target, Method hook, Method backup) {
this.target = target;
this.hook = hook;
this.backup = backup;
}
public boolean isCtor() { public boolean isCtor() {
return target instanceof Constructor; return target instanceof Constructor;
......
...@@ -25,6 +25,7 @@ android { ...@@ -25,6 +25,7 @@ android {
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.linkedin.dexmaker:dexmaker:2.21.0' implementation 'com.linkedin.dexmaker:dexmaker:2.21.0'
compileOnly project(':hooklib')
} }
package com.swift.sandhook.xposedcompat;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by swift_gan on 2017/11/23.
*/
public class ProcessUtils {
private static volatile String processName = null;
public static String getProcessName(Context context) {
if (!TextUtils.isEmpty(processName))
return processName;
processName = doGetProcessName(context);
return processName;
}
private static String doGetProcessName(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
if (proInfo.pid == android.os.Process.myPid()) {
if (proInfo.processName != null) {
return proInfo.processName;
}
}
}
return context.getPackageName();
}
public static boolean isMainProcess(Context context) {
String processName = getProcessName(context);
String pkgName = context.getPackageName();
if (!TextUtils.isEmpty(processName) && !TextUtils.equals(processName, pkgName)) {
return false;
} else {
return true;
}
}
public static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
final PackageManager packageManager = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mainIntent.setPackage(packageName);
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
return apps != null ? apps : new ArrayList<ResolveInfo>();
}
}
package com.swift.sandhook.xposedcompat; package com.swift.sandhook.xposedcompat;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import java.io.File;
public class XposedCompat { public class XposedCompat {
public static File cacheDir;
public static Context context;
public static ClassLoader classLoader;
public static boolean isFirstApplication;
} }
package com.swift.sandhook.xposedcompat.methodgen;
import android.util.Log;
import com.swift.sandhook.xposedcompat.BuildConfig;
public class DexLog {
public static final String TAG = "SandXposed-dexmaker";
public static int v(String s) {
return Log.v(TAG, s);
}
public static int i(String s) {
return Log.i(TAG, s);
}
public static int d(String s) {
if (BuildConfig.DEBUG) {
return Log.d(TAG, s);
}
return 0;
}
public static int w(String s) {
return Log.w(TAG, s);
}
public static int e(String s) {
return Log.e(TAG, s);
}
public static int e(String s, Throwable t) {
return Log.e(TAG, s, t);
}
}
...@@ -225,6 +225,7 @@ public class DexMakerUtils { ...@@ -225,6 +225,7 @@ public class DexMakerUtils {
if (addInstMethod == null) { if (addInstMethod == null) {
try { try {
addInstMethod = Code.class.getDeclaredMethod("addInstruction", Insn.class); addInstMethod = Code.class.getDeclaredMethod("addInstruction", Insn.class);
addInstMethod.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -240,6 +241,7 @@ public class DexMakerUtils { ...@@ -240,6 +241,7 @@ public class DexMakerUtils {
if (specMethod == null) { if (specMethod == null) {
try { try {
specMethod = Local.class.getDeclaredMethod("spec"); specMethod = Local.class.getDeclaredMethod("spec");
specMethod.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
package com.swift.sandhook.xposedcompat.methodgen;
import com.swift.sandhook.xposedcompat.XposedCompat;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import de.robv.android.xposed.XposedBridge;
public final class DynamicBridge {
private static final HashMap<Member, Method> hookedInfo = new HashMap<>();
private static final HookerDexMaker dexMaker = new HookerDexMaker();
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
private static File dexDir;
private static File dexOptDir;
public static void onForkPost() {
dexPathInited.set(false);
}
public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
if (!checkMember(hookMethod)) {
return;
}
if (hookedInfo.containsKey(hookMethod)) {
DexLog.w("already hook method:" + hookMethod.toString());
return;
}
DexLog.d("start to generate class for: " + hookMethod);
try {
// using file based DexClassLoader
if (dexPathInited.compareAndSet(false, true)) {
// delete previous compiled dex to prevent potential crashing
// TODO find a way to reuse them in consideration of performance
try {
// we always choose to use device encrypted storage data on android N and later
// in case some app is installing hooks before phone is unlocked
String fixedAppDataDir = XposedCompat.cacheDir.getAbsolutePath();
dexDir = new File(fixedAppDataDir, "/sandxposed/");
dexOptDir = new File(dexDir, "oat");
dexDir.mkdirs();
try {
FileUtils.delete(dexOptDir);
} catch (Throwable throwable) {
}
} catch (Throwable throwable) {
DexLog.e("error when init dex path", throwable);
}
}
dexMaker.start(hookMethod, additionalHookInfo,
hookMethod.getDeclaringClass().getClassLoader(), dexDir == null ? null : dexDir.getAbsolutePath());
hookedInfo.put(hookMethod, dexMaker.getCallBackupMethod());
} catch (Exception e) {
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
}
}
private static boolean checkMember(Member member) {
if (member instanceof Method) {
return true;
} else if (member instanceof Constructor<?>) {
return true;
} else if (member.getDeclaringClass().isInterface()) {
DexLog.e("Cannot hook interfaces: " + member.toString());
return false;
} else if (Modifier.isAbstract(member.getModifiers())) {
DexLog.e("Cannot hook abstract methods: " + member.toString());
return false;
} else {
DexLog.e("Only methods and constructors can be hooked: " + member.toString());
return false;
}
}
public static Object invokeOriginalMethod(Member method, Object thisObject, Object[] args)
throws InvocationTargetException, IllegalAccessException {
Method callBackup = hookedInfo.get(method);
if (callBackup == null) {
throw new IllegalStateException("method not hooked, cannot call original method.");
}
if (!Modifier.isStatic(callBackup.getModifiers())) {
throw new IllegalStateException("original method is not static, something must be wrong!");
}
callBackup.setAccessible(true);
if (args == null) {
args = new Object[0];
}
final int argsSize = args.length;
if (Modifier.isStatic(method.getModifiers())) {
return callBackup.invoke(null, args);
} else {
Object[] newArgs = new Object[argsSize + 1];
newArgs[0] = thisObject;
for (int i = 1; i < newArgs.length; i++) {
newArgs[i] = args[i - 1];
}
return callBackup.invoke(null, newArgs);
}
}
}
package com.swift.sandhook.xposedcompat.methodgen;
import android.os.Build;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileUtils {
public static final boolean IS_USING_PROTECTED_STORAGE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
/**
* Delete a file or a directory and its children.
*
* @param file The directory to delete.
* @throws IOException Exception when problem occurs during deleting the directory.
*/
public static void delete(File file) throws IOException {
for (File childFile : file.listFiles()) {
if (childFile.isDirectory()) {
delete(childFile);
} else {
if (!childFile.delete()) {
throw new IOException();
}
}
}
if (!file.delete()) {
throw new IOException();
}
}
public static String readLine(File file) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
return reader.readLine();
} catch (Throwable throwable) {
return "";
}
}
public static void writeLine(File file, String line) {
try {
file.createNewFile();
} catch (IOException ex) {
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(line);
writer.flush();
} catch (Throwable throwable) {
DexLog.e("error writing line to file " + file + ": " + throwable.getMessage());
}
}
public static String getPackageName(String dataDir) {
if (TextUtils.isEmpty(dataDir)) {
DexLog.e("getPackageName using empty dataDir");
return "";
}
int lastIndex = dataDir.lastIndexOf("/");
if (lastIndex < 0) {
return dataDir;
}
return dataDir.substring(lastIndex + 1);
}
public static String getDataPathPrefix() {
return IS_USING_PROTECTED_STORAGE ? "/data/user_de/0/" : "/data/data/";
}
}
...@@ -11,6 +11,8 @@ import com.android.dx.Label; ...@@ -11,6 +11,8 @@ import com.android.dx.Label;
import com.android.dx.Local; import com.android.dx.Local;
import com.android.dx.MethodId; import com.android.dx.MethodId;
import com.android.dx.TypeId; import com.android.dx.TypeId;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.wrapper.HookWrapper;
import java.io.File; import java.io.File;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
...@@ -37,7 +39,7 @@ public class HookerDexMaker { ...@@ -37,7 +39,7 @@ public class HookerDexMaker {
public static final String METHOD_NAME_SETUP = "setup"; public static final String METHOD_NAME_SETUP = "setup";
public static final TypeId<Object[]> objArrayTypeId = TypeId.get(Object[].class); public static final TypeId<Object[]> objArrayTypeId = TypeId.get(Object[].class);
private static final String CLASS_DESC_PREFIX = "L"; private static final String CLASS_DESC_PREFIX = "L";
private static final String CLASS_NAME_PREFIX = "EdHooker"; private static final String CLASS_NAME_PREFIX = "SandHooker";
private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo"; private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo";
private static final String FIELD_NAME_METHOD = "method"; private static final String FIELD_NAME_METHOD = "method";
private static final String PARAMS_FIELD_NAME_METHOD = "method"; private static final String PARAMS_FIELD_NAME_METHOD = "method";
...@@ -203,7 +205,7 @@ public class HookerDexMaker { ...@@ -203,7 +205,7 @@ public class HookerDexMaker {
mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes); mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes);
mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes); mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes);
mCallBackupMethod = mHookClass.getMethod(METHOD_NAME_CALL_BACKUP, mActualParameterTypes); mCallBackupMethod = mHookClass.getMethod(METHOD_NAME_CALL_BACKUP, mActualParameterTypes);
//HookMain.backupAndHook(mMember, mHookMethod, mBackupMethod); SandHook.hook(new HookWrapper.HookEntity(mMember, mHookMethod, mBackupMethod));
} }
public Method getHookMethod() { public Method getHookMethod() {
......
package com.swift.sandhook.xposedcompat.methodgen;
import android.os.Process;
import android.text.TextUtils;
//import com.elderdrivers.riru.xposed.Main;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class ProcessUtils {
public static String getCurrentProcessName() {
String prettyName = null;//Main.sAppProcessName;
if (!TextUtils.isEmpty(prettyName)) {
return prettyName;
}
return getProcessName(Process.myPid());
}
/**
* a common solution from https://stackoverflow.com/a/21389402
* <p>
* use {@link com.elderdrivers.riru.xposed.Main#sAppProcessName} to get current process name
*/
public static String getProcessName(int pid) {
BufferedReader cmdlineReader = null;
try {
cmdlineReader = new BufferedReader(new InputStreamReader(
new FileInputStream(
"/proc/" + pid + "/cmdline"),
"iso-8859-1"));
int c;
StringBuilder processName = new StringBuilder();
while ((c = cmdlineReader.read()) > 0) {
processName.append((char) c);
}
return processName.toString();
} catch (Throwable throwable) {
DexLog.w("getProcessName: " + throwable.getMessage());
} finally {
try {
if (cmdlineReader != null) {
cmdlineReader.close();
}
} catch (Throwable throwable) {
DexLog.e("getProcessName: " + throwable.getMessage());
}
}
return "";
}
public static boolean isLastPidAlive(File lastPidFile) {
String lastPidInfo = FileUtils.readLine(lastPidFile);
try {
String[] split = lastPidInfo.split(":", 2);
return checkProcessAlive(Integer.parseInt(split[0]), split[1]);
} catch (Throwable throwable) {
DexLog.w("error when check last pid " + lastPidFile + ": " + throwable.getMessage());
return false;
}
}
public static void saveLastPidInfo(File lastPidFile, int pid, String processName) {
try {
if (!lastPidFile.exists()) {
lastPidFile.getParentFile().mkdirs();
lastPidFile.createNewFile();
}
} catch (Throwable throwable) {
}
FileUtils.writeLine(lastPidFile, pid + ":" + processName);
}
public static boolean checkProcessAlive(int pid, String processName) {
String existsPrcName = getProcessName(pid);
DexLog.w("checking pid alive: " + pid + ", " + processName + ", processName=" + existsPrcName);
return existsPrcName.equals(processName);
}
}
package de.robv.android.xposed; package de.robv.android.xposed;
import android.content.res.XResources; //import android.content.res.XResources;
import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_InitPackageResources;
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam; import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;
......
package de.robv.android.xposed; package de.robv.android.xposed;
import android.os.SELinux; //import android.os.SELinux;
import de.robv.android.xposed.services.BaseService; import de.robv.android.xposed.services.BaseService;
import de.robv.android.xposed.services.DirectAccessService; import de.robv.android.xposed.services.DirectAccessService;
...@@ -25,18 +25,18 @@ public final class SELinuxHelper { ...@@ -25,18 +25,18 @@ public final class SELinuxHelper {
* *
* @return A boolean indicating whether SELinux is enforcing. * @return A boolean indicating whether SELinux is enforcing.
*/ */
public static boolean isSELinuxEnforced() { // public static boolean isSELinuxEnforced() {
return sIsSELinuxEnabled && SELinux.isSELinuxEnforced(); // return sIsSELinuxEnabled && SELinux.isSELinuxEnforced();
} // }
/** /**
* Gets the security context of the current process. * Gets the security context of the current process.
* *
* @return A String representing the security context of the current process. * @return A String representing the security context of the current process.
*/ */
public static String getContext() { // public static String getContext() {
return sIsSELinuxEnabled ? SELinux.getContext() : null; // return sIsSELinuxEnabled ? SELinux.getContext() : null;
} // }
/** /**
* Retrieve the service to be used when accessing files in {@code /data/data/*}. * Retrieve the service to be used when accessing files in {@code /data/data/*}.
......
...@@ -7,7 +7,6 @@ import android.os.Environment; ...@@ -7,7 +7,6 @@ import android.os.Environment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
...@@ -121,14 +120,12 @@ public final class XSharedPreferences implements SharedPreferences { ...@@ -121,14 +120,12 @@ public final class XSharedPreferences implements SharedPreferences {
try { try {
result = SELinuxHelper.getAppDataFileService().getFileInputStream(mFilename, mFileSize, mLastModified); result = SELinuxHelper.getAppDataFileService().getFileInputStream(mFilename, mFileSize, mLastModified);
if (result.stream != null) { if (result.stream != null) {
map = XmlUtils.readMapXml(result.stream); //map = XmlUtils.readMapXml(result.stream);
result.stream.close(); result.stream.close();
} else { } else {
// The file is unchanged, keep the current values // The file is unchanged, keep the current values
map = mMap; map = mMap;
} }
} catch (XmlPullParserException e) {
Log.w(TAG, "getSharedPreferences", e);
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
// SharedPreferencesImpl has a canRead() check, so it doesn't log anything in case the file doesn't exist // SharedPreferencesImpl has a canRead() check, so it doesn't log anything in case the file doesn't exist
} catch (IOException e) { } catch (IOException e) {
......
...@@ -4,6 +4,8 @@ import android.annotation.SuppressLint; ...@@ -4,6 +4,8 @@ import android.annotation.SuppressLint;
import android.util.Log; import android.util.Log;
import com.swift.sandhook.xposedcompat.methodgen.DynamicBridge;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.AccessibleObject;
...@@ -151,7 +153,6 @@ public final class XposedBridge { ...@@ -151,7 +153,6 @@ public final class XposedBridge {
* @see #hookAllConstructors * @see #hookAllConstructors
*/ */
public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) { public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) {
hookMethod = MethodHookUtils.preCheck(hookMethod);
if (!(hookMethod instanceof Method) && !(hookMethod instanceof Constructor<?>)) { if (!(hookMethod instanceof Method) && !(hookMethod instanceof Constructor<?>)) {
throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod.toString()); throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod.toString());
} else if (hookMethod.getDeclaringClass().isInterface()) { } else if (hookMethod.getDeclaringClass().isInterface()) {
...@@ -196,16 +197,7 @@ public final class XposedBridge { ...@@ -196,16 +197,7 @@ public final class XposedBridge {
} }
AdditionalHookInfo additionalInfo = new AdditionalHookInfo(callbacks, parameterTypes, returnType); AdditionalHookInfo additionalInfo = new AdditionalHookInfo(callbacks, parameterTypes, returnType);
MethodInfo methodInfo = new MethodInfo(hookMethod); hookMethodNative(hookMethod, declaringClass, slot, additionalInfo);
declaringClass = methodInfo.getClassForSure();
Member reflectMethod = (Member) HookMain.findMethod(
declaringClass, methodInfo.methodName, methodInfo.methodSig);
if (reflectMethod == null) {
Log.e(TAG, "method not found: name="
+ methodInfo.methodName + ", sig=" + methodInfo.methodSig);
reflectMethod = hookMethod;
}
hookMethodNative(reflectMethod, declaringClass, slot, additionalInfo);
} }
return callback.new Unhook(hookMethod); return callback.new Unhook(hookMethod);
......
package de.robv.android.xposed.callbacks; package de.robv.android.xposed.callbacks;
import android.content.res.XResources; //import android.content.res.XResources;
import de.robv.android.xposed.IXposedHookInitPackageResources; import de.robv.android.xposed.IXposedHookInitPackageResources;
import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet; import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
...@@ -45,7 +45,7 @@ public abstract class XC_InitPackageResources extends XCallback implements IXpos ...@@ -45,7 +45,7 @@ public abstract class XC_InitPackageResources extends XCallback implements IXpos
* Reference to the resources that can be used for calls to * Reference to the resources that can be used for calls to
* {@link XResources#setReplacement(String, String, String, Object)}. * {@link XResources#setReplacement(String, String, String, Object)}.
*/ */
public XResources res; //public XResources res;
} }
/** @hide */ /** @hide */
......
package de.robv.android.xposed.callbacks; package de.robv.android.xposed.callbacks;
import android.content.res.XResources; //import android.content.res.XResources;
import android.content.res.XResources.ResourceNames; //import android.content.res.XResources.ResourceNames;
import android.view.View; import android.view.View;
import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet; import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
...@@ -41,13 +41,13 @@ public abstract class XC_LayoutInflated extends XCallback { ...@@ -41,13 +41,13 @@ public abstract class XC_LayoutInflated extends XCallback {
public View view; public View view;
/** Container with the ID and name of the underlying resource. */ /** Container with the ID and name of the underlying resource. */
public ResourceNames resNames; // public ResourceNames resNames;
/** Directory from which the layout was actually loaded (e.g. "layout-sw600dp"). */ /** Directory from which the layout was actually loaded (e.g. "layout-sw600dp"). */
public String variant; // public String variant;
/** Resources containing the layout. */ /** Resources containing the layout. */
public XResources res; // public XResources res;
} }
/** @hide */ /** @hide */
...@@ -92,7 +92,7 @@ public abstract class XC_LayoutInflated extends XCallback { ...@@ -92,7 +92,7 @@ public abstract class XC_LayoutInflated extends XCallback {
@Override @Override
public void unhook() { public void unhook() {
XResources.unhookLayout(resDir, id, XC_LayoutInflated.this); // XResources.unhookLayout(resDir, id, XC_LayoutInflated.this);
} }
} }
......
...@@ -2,6 +2,9 @@ package de.robv.android.xposed.callbacks; ...@@ -2,6 +2,9 @@ package de.robv.android.xposed.callbacks;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import com.swift.sandhook.xposedcompat.ProcessUtils;
import com.swift.sandhook.xposedcompat.XposedCompat;
import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet; import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
...@@ -39,19 +42,19 @@ public abstract class XC_LoadPackage extends XCallback implements IXposedHookLoa ...@@ -39,19 +42,19 @@ public abstract class XC_LoadPackage extends XCallback implements IXposedHookLoa
} }
/** The name of the package being loaded. */ /** The name of the package being loaded. */
public String packageName; public String packageName = XposedCompat.context.getPackageName();
/** The process in which the package is executed. */ /** The process in which the package is executed. */
public String processName; public String processName = ProcessUtils.getProcessName(XposedCompat.context);
/** The ClassLoader used for this package. */ /** The ClassLoader used for this package. */
public ClassLoader classLoader; public ClassLoader classLoader = XposedCompat.classLoader;
/** More information about the application being loaded. */ /** More information about the application being loaded. */
public ApplicationInfo appInfo; public ApplicationInfo appInfo = XposedCompat.context.getApplicationInfo();
/** Set to {@code true} if this is the first (and main) application for this process. */ /** Set to {@code true} if this is the first (and main) application for this process. */
public boolean isFirstApplication; public boolean isFirstApplication = XposedCompat.isFirstApplication;
} }
/** @hide */ /** @hide */
......
...@@ -3,7 +3,7 @@ package de.robv.android.xposed.services; ...@@ -3,7 +3,7 @@ package de.robv.android.xposed.services;
import android.os.IBinder; import android.os.IBinder;
import android.os.Parcel; import android.os.Parcel;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; //import android.os.ServiceManager;
import java.io.IOException; import java.io.IOException;
...@@ -158,7 +158,7 @@ public final class BinderService extends BaseService { ...@@ -158,7 +158,7 @@ public final class BinderService extends BaseService {
private final IBinder mRemote; private final IBinder mRemote;
private BinderService(int target) { private BinderService(int target) {
IBinder binder = ServiceManager.getService(SERVICE_NAMES[target]); IBinder binder = null; //ServiceManager.getService(SERVICE_NAMES[target]);
if (binder == null) if (binder == null)
throw new IllegalStateException("Service " + SERVICE_NAMES[target] + " does not exist"); throw new IllegalStateException("Service " + SERVICE_NAMES[target] + " does not exist");
this.mRemote = binder; this.mRemote = binder;
......
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