Skip to content

Commit

Permalink
adj: new dexkit cache and browser use this for debugging
Browse files Browse the repository at this point in the history
  • Loading branch information
Sevtinge committed May 16, 2024
1 parent 7b0304f commit 6089de5
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class Browser extends BaseModule {

@Override
public void handleLoadPackage() {
initHook(DebugMode.INSTANCE, mPrefsMap.getBoolean("browser_debug_mode"));
initHook(new DebugMode(), mPrefsMap.getBoolean("browser_debug_mode"));
initHook(new DisableReadFiles(), mPrefsMap.getBoolean("browser_disable_blacklist"));
initHook(new EnableDebugEnvironment(), mPrefsMap.getBoolean("browser_enable_debug_environment"));
initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getStringAsInt("various_super_clipboard_e", 0) != 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.sevtinge.hyperceiler.module.base.dexkit;

import static com.sevtinge.hyperceiler.utils.log.XposedLogUtils.logD;
import static com.sevtinge.hyperceiler.utils.log.XposedLogUtils.logE;
import static com.sevtinge.hyperceiler.utils.log.XposedLogUtils.logI;

import org.json.JSONArray;
import org.json.JSONException;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class DexKitCacheFile {

static String TAG = "DexKitCacheFile";

public static String getFilePath(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
return "/data/user/0/" + loadPackageParam.packageName + "/cache/HyperCeiler_" + callingClassName + "_" + tag + "_DexKit_Cache.dat";
}

public static void checkFile(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
String path = getFilePath(loadPackageParam, callingClassName, tag);
File file = new File(path);
File parentDir = file.getParentFile();
if (parentDir == null) {
logE(TAG, "parentDir is null: " + path);
}
if (parentDir != null && !parentDir.exists()) {
if (parentDir.mkdirs()) {
logI(TAG, "mkdirs: " + parentDir);
} else {
logE(TAG, "mkdirs: " + parentDir);
}
}
if (!file.exists()) {
try {
if (file.createNewFile()) {
writeFile(loadPackageParam, new JSONArray(), callingClassName, tag);
setPermission(path);
logI(TAG, "createNewFile: " + file);
} else {
logE(TAG, "createNewFile: " + file);
}
} catch (IOException e) {
logE(TAG, "createNewFile: " + e);
}
} else {
setPermission(path);
}
}

public static void writeFile(XC_LoadPackage.LoadPackageParam loadPackageParam, JSONArray jsonArray, String callingClassName, String tag) {
String path = getFilePath(loadPackageParam, callingClassName, tag);
if (jsonArray == null) {
logE(TAG, "write json is null");
return;
}
try (BufferedWriter writer = new BufferedWriter(new
FileWriter(path, false))) {
writer.write(jsonArray.toString());
} catch (IOException e) {
logE(TAG, "writeFile: " + e);
}
}

public static boolean isEmptyFile(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
if(!isFileExists(loadPackageParam, callingClassName, tag)){
JSONArray jsonArray = readFile(loadPackageParam, callingClassName, tag);
return jsonArray.length() == 0;
}
return false;
}

public static boolean isFileExists(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
File file = new File(getFilePath(loadPackageParam, callingClassName, tag));
return file.exists();
}

public static JSONArray readFile(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
String path = getFilePath(loadPackageParam, callingClassName, tag);
try (BufferedReader reader = new BufferedReader(new
FileReader(path))) {
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String jsonString = builder.toString();
if (jsonString.isEmpty()) {
jsonString = "[]";
}
return new JSONArray(jsonString);
} catch (IOException | JSONException e) {
logE(TAG, "readFile: " + e);
}
return new JSONArray();
}

public static boolean resetFile(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) {
// 清空文件内容
writeFile(loadPackageParam, new JSONArray(), callingClassName, tag);
return isEmptyFile(loadPackageParam, callingClassName, tag);
}

public static void setPermission(String paths) {
// 指定文件的路径
Path filePath = Paths.get(paths);

try {
// 获取当前文件的权限
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(filePath);

// 添加世界可读写权限
permissions.add(PosixFilePermission.OTHERS_READ);
permissions.add(PosixFilePermission.OTHERS_WRITE);
permissions.add(PosixFilePermission.GROUP_READ);
permissions.add(PosixFilePermission.GROUP_WRITE);

// 设置新的权限
Files.setPosixFilePermissions(filePath, permissions);
} catch (IOException e) {
logE(TAG, "setPermission: " + e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.sevtinge.hyperceiler.module.base.dexkit;

import static com.sevtinge.hyperceiler.module.base.dexkit.DexKitCacheFile.readFile;
import static com.sevtinge.hyperceiler.module.base.tool.OtherTool.getPackageVersionCode;
import static com.sevtinge.hyperceiler.utils.log.XposedLogUtils.logD;
import static com.sevtinge.hyperceiler.utils.log.XposedLogUtils.logE;

import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClassIfExists;

import com.sevtinge.hyperceiler.module.base.dexkit.DexKitCacheFile;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.luckypray.dexkit.query.FindMethod;
import org.luckypray.dexkit.query.matchers.MethodMatcher;
import org.luckypray.dexkit.result.MethodData;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class DexKitData {

public static void hookMethodWithDexKit(String tag, XC_LoadPackage.LoadPackageParam loadPackageParam, MethodMatcher methodMatcher, Object... callback) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String callingClassName = stackTrace[3].getClassName();
int lastDotIndex = callingClassName.lastIndexOf('.');
callingClassName = callingClassName.substring(lastDotIndex + 1);
try {
String className;
String methodName;
List<String> paramList;
if (!DexKitCacheFile.isEmptyFile(loadPackageParam, callingClassName, tag)) {
try {
className = getClassName(loadPackageParam, callingClassName, tag);
methodName = getMethodName(loadPackageParam, callingClassName, tag);
paramList = getParamList(loadPackageParam, callingClassName, tag);
} catch (JSONException e) {
throw new RuntimeException(e);
}
} else {
MethodData methodData = DexKit.getDexKitBridge().findMethod(FindMethod.create()
.matcher(methodMatcher)
).singleOrThrow(() -> new IllegalStateException("No Such Method Found."));
className = methodData.getClassName();
methodName = methodData.getMethodName();
paramList = methodData.getParamNames();
putDexKitCache(loadPackageParam, callingClassName, tag, className, methodName, paramList);
}
if (paramList == null) {
findAndHookMethod(findClassIfExists(className, loadPackageParam.classLoader), methodName, callback);
} else {
findAndHookMethod(findClassIfExists(className, loadPackageParam.classLoader), methodName, paramList.toArray(), callback);
}
} catch (Exception e){
logE(callingClassName, loadPackageParam.packageName, "Having trouble finding "+tag+": "+e);
}
}

public static void putDexKitCache(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag, String className, String methodName, List<String> paramList) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("ClassName", className);
jsonObject.put("MethodName", methodName);
jsonObject.put("ParamList", paramList);
} catch (JSONException e) {
throw new RuntimeException(e);
}
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonObject);
DexKitCacheFile.writeFile(loadPackageParam, jsonArray, callingClassName, tag);
}

public static String getClassName(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) throws JSONException {
return readFile(loadPackageParam, callingClassName, tag).getJSONObject(0).getString("ClassName");
}

public static String getMethodName(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) throws JSONException {
return readFile(loadPackageParam, callingClassName, tag).getJSONObject(0).getString("MethodName");
}

public static List<String> getParamList(XC_LoadPackage.LoadPackageParam loadPackageParam, String callingClassName, String tag) throws JSONException {
JSONObject jsonObject = readFile(loadPackageParam, callingClassName, tag).getJSONObject(0);
if (jsonObject.has("ParamList")) {
List<String> list = Arrays.asList(jsonObject.getString("ParamList").split(","));
if (!list.isEmpty()) {
return list;
}
}
return null;
}

public static class MethodHookWithDexKit extends XC_MethodHook {

protected void before(MethodHookParam param) throws Throwable {
}

protected void after(MethodHookParam param) throws Throwable {
}

public MethodHookWithDexKit() {
super();
}

public MethodHookWithDexKit(int priority) {
super(priority);
}

public static MethodHookWithDexKit returnConstant(final Object result) {
return new MethodHookWithDexKit(PRIORITY_DEFAULT) {
@Override
protected void before(MethodHookParam param) {
param.setResult(result);
}
};
}

public static final MethodHookWithDexKit DO_NOTHING = new MethodHookWithDexKit(PRIORITY_HIGHEST * 2) {
@Override
protected void before(MethodHookParam param) {
param.setResult(null);
}
};

@Override
public void beforeHookedMethod(MethodHookParam param) throws Throwable {
try {
this.before(param);
} catch (Throwable t) {
// logE("BeforeHook", t);
}
}

@Override
public void afterHookedMethod(MethodHookParam param) throws Throwable {
try {
this.after(param);
} catch (Throwable t) {
// logE("AfterHook", t);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.sevtinge.hyperceiler.module.hook.browser;

import static com.sevtinge.hyperceiler.module.base.tool.OtherTool.getPackageVersionCode;

import com.sevtinge.hyperceiler.module.base.BaseHook;
import com.sevtinge.hyperceiler.module.base.dexkit.DexKitData;

import org.luckypray.dexkit.query.matchers.MethodMatcher;

public class DebugMode extends BaseHook {
@Override
public void init() throws NoSuchMethodException {
DexKitData.hookMethodWithDexKit("EnvironmentFlag", lpparam,
MethodMatcher.create()
.usingStrings("environment_flag")
.returnType(String.class),
new DexKitData.MethodHookWithDexKit() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.setResult(1);
}
});
DexKitData.hookMethodWithDexKit("DebugMode0", lpparam,
MethodMatcher.create()
.usingStrings("pref_key_debug_mode_new")
.returnType(boolean.class),
new DexKitData.MethodHookWithDexKit() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.setResult(true);
}
});
DexKitData.hookMethodWithDexKit("DebugMode1", lpparam,
MethodMatcher.create()
.usingStrings("pref_key_debug_mode")
.returnType(boolean.class),
new DexKitData.MethodHookWithDexKit() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.setResult(true);
}
});
DexKitData.hookMethodWithDexKit("Key", lpparam,
MethodMatcher.create()
.usingStrings("pref_key_debug_mode_" + getPackageVersionCode(lpparam))
.returnType(boolean.class), new DexKitData.MethodHookWithDexKit() {
@Override
protected void before(MethodHookParam param) throws Throwable {
param.setResult(true);
}
});
}
}
Loading

0 comments on commit 6089de5

Please sign in to comment.